Source code for aioopenexchangerates.client
"""Provide a client for the Open Exchange Rates API."""
from __future__ import annotations
from http import HTTPStatus
from types import TracebackType
from typing import Any, Self, cast
from aiohttp import ClientError, ClientResponse, ClientResponseError, ClientSession
from .exceptions import (
OpenExchangeRatesAuthError,
OpenExchangeRatesClientError,
OpenExchangeRatesRateLimitError,
)
from .model import Latest
BASE_API_ENDPOINT = "https://openexchangerates.org/api/"
[docs]
class Client:
"""Represent the client for the Open Exchange Rates API."""
def __init__(self, api_key: str, session: ClientSession | None = None) -> None:
"""Initialize the client."""
self.api_key = api_key
self.session = session or ClientSession()
[docs]
async def request(self, endpoint: str, **kwargs: Any) -> ClientResponse:
"""Make a request."""
url = f"{BASE_API_ENDPOINT}{endpoint}"
try:
return await self.session.get(url, raise_for_status=True, **kwargs)
except ClientResponseError as err:
if err.status == HTTPStatus.UNAUTHORIZED:
raise OpenExchangeRatesAuthError(err.message) from err
if err.status == HTTPStatus.FORBIDDEN:
raise OpenExchangeRatesAuthError(err.message) from err
if err.status == HTTPStatus.TOO_MANY_REQUESTS:
raise OpenExchangeRatesRateLimitError(err.message) from err
raise OpenExchangeRatesClientError(err.message) from err
except ClientError as err:
raise OpenExchangeRatesClientError(f"Unknown error: {err}") from err
[docs]
async def get_currencies(
self,
show_alternative: bool = False, # noqa: FBT001, FBT002
show_inactive: bool = False, # noqa: FBT001, FBT002
) -> dict[str, str]:
"""Get the supported currencies."""
params = {
"show_alternative": int(show_alternative),
"show_inactive": int(show_inactive),
}
response = await self.request("currencies.json", params=params)
return cast("dict[str, str]", (await response.json()))
[docs]
async def get_latest(
self,
base: str = "USD",
symbols: list[str] | None = None,
) -> Latest:
"""Get the latest rates for the given base and symbols."""
params = {"app_id": self.api_key, "base": base}
if symbols:
params["symbols"] = ",".join(symbols)
response = await self.request("latest.json", params=params)
return Latest.from_dict(await response.json())
[docs]
async def close(self) -> None:
"""Close the client."""
await self.session.close()
async def __aenter__(self) -> Self:
"""Enter the context manager."""
return self
async def __aexit__(
self,
exc_type: type[BaseException] | None,
exc_value: BaseException | None,
traceback: TracebackType | None,
) -> None:
"""Exit the context manager."""
await self.close()