diff --git a/README.md b/README.md index 5c7a8f2..3ab78ca 100644 --- a/README.md +++ b/README.md @@ -466,22 +466,10 @@ import pyalex pyalex.config.api_key = "" ``` -To check out whether your API key is indeed working, you can use the following code: - -```python -import requests -pyalex.config.retry_http_codes = None -try: - pyalex.Works().filter(from_updated_date="2023-01-12").get() -except requests.exceptions.HTTPError as e: - if e.response.status_code == 403: - logging.info("API key is NOT working 🔴") - else: - logging.error(f"Unexpected HTTP error: {e}") - raise -else: - logging.info("API key is working 👍") -``` +pyalex will automatically check whether your API key is valid and throw a `ValueError` if it isn't. + +If you want to manually check whether the API key is valid, call `pyalex._check_api_key()` +which will return True if it is valid and False if it isn't. ## Alternatives diff --git a/pyalex/__init__.py b/pyalex/__init__.py index dfe7262..277126d 100644 --- a/pyalex/__init__.py +++ b/pyalex/__init__.py @@ -30,6 +30,7 @@ from pyalex.api import Topics from pyalex.api import Work from pyalex.api import Works +from pyalex.api import _check_api_key from pyalex.api import autocomplete from pyalex.api import config from pyalex.api import invert_abstract @@ -63,4 +64,5 @@ "config", "invert_abstract", "OpenAlexResponseList", + "_check_api_key", ] diff --git a/pyalex/api.py b/pyalex/api.py index 007a1db..7c6e04e 100644 --- a/pyalex/api.py +++ b/pyalex/api.py @@ -1,5 +1,8 @@ +import datetime import logging import warnings +from dataclasses import dataclass +from dataclasses import field from urllib.parse import quote_plus from urllib.parse import urlunparse @@ -13,7 +16,12 @@ __version__ = "0.0.0" -class AlexConfig(dict): +def _check_api_key(): + raise NotImplementedError() + + +@dataclass +class AlexConfig: """Configuration class for OpenAlex API. Attributes @@ -34,22 +42,21 @@ class AlexConfig(dict): List of HTTP status codes to retry on. """ - def __getattr__(self, key): - return super().__getitem__(key) + email: str | None = None + user_agent: str = f"pyalex/{__version__}" + openalex_url: str = "https://api.openalex.org" + max_retries: int = 0 + retry_backoff_factor: float = 0.1 + retry_http_codes: list[int] = field(default_factory=lambda: [429, 500, 503]) + api_key: str | None = None - def __setattr__(self, key, value): - return super().__setitem__(key, value) + def __setattr__(self, prop, val): + super().__setattr__(prop, val) + if prop == "api_key" and val and not _check_api_key(): + raise ValueError("Invalid API key. Please check your OpenAlex API key.") -config = AlexConfig( - email=None, - api_key=None, - user_agent=f"pyalex/{__version__}", - openalex_url="https://api.openalex.org", - max_retries=0, - retry_backoff_factor=0.1, - retry_http_codes=[429, 500, 503], -) +config = AlexConfig() class or_(dict): @@ -1094,3 +1101,24 @@ def autocomplete(s): # aliases People = Authors Journals = Sources + + +def _check_api_key(): + """Check if the API key is valid.""" + bk_cods = config.retry_http_codes + config.retry_http_codes = None + dt = f"{datetime.datetime.now().year}-01-01" + res = None + try: + Works().filter(from_updated_date=dt).get() + except requests.exceptions.HTTPError as e: + if e.response.status_code == 403: + res = False + else: + logging.error(f"Unexpected HTTP error: {e}") + raise + else: + res = True + finally: + config.retry_http_codes = bk_cods + return res