Source code for bungieapi.base

import dataclasses as dt
import functools as ft
import typing as t
from enum import Enum

import aiohttp
from aiohttp import ClientResponse

from bungieapi.forge import forge
from bungieapi.generated.components.schemas.exceptions import PlatformErrorCodes
from bungieapi.json import to_json


QueryInput = t.Any  # t.Union[None, str, bool, int, t.Sequence[Enum]]


[docs]@ft.singledispatch def clean_query_value(in_: QueryInput) -> str: return str(in_)
[docs]@clean_query_value.register def clean_enum_value(in_: Enum) -> str: return in_.value
[docs]@clean_query_value.register def clean_enum_bool(in_: bool) -> str: return "true" if in_ else "false"
[docs]@dt.dataclass(frozen=True) class ApiError: error_code: PlatformErrorCodes throttle_seconds: int error_status: str message: str message_data: t.Mapping[str, t.Any]
[docs]class ApiException(Exception): def __init__(self, error: ApiError): self._error = error def __repr__(self): return repr(self._error)
[docs]class BaseClient: def __init__(self, session: aiohttp.ClientSession, path: str) -> None: self._session = session self._path = path def _clean_query(self, query: t.Mapping[str, QueryInput]) -> t.Mapping[str, str]: return {k: clean_query_value(v) for k, v in query.items() if v is not None}
[docs] async def handle_error(self, response: ClientResponse) -> ClientResponse: if response.status == 400: raise ApiException(forge(ApiError, await response.json())) response.raise_for_status() return response
[docs] async def get( self, path: str, query: t.Optional[t.Mapping[str, QueryInput]] ) -> t.Mapping[str, t.Any]: assert path[0] == "/" query = self._clean_query(query) if query else {} async with self._session.get(f"{self._path}{path}", params=query) as response: response = await self.handle_error(response) return await response.json()
[docs] async def post( self, path: str, query: t.Optional[t.Mapping[str, QueryInput]], request: t.Any = None, ) -> t.Mapping[str, t.Any]: assert path[0] == "/" query = self._clean_query(query) if query else {} async with self._session.post( f"{self._path}{path}", params=query, json=to_json(request) ) as response: response = await self.handle_error(response) return await response.json()