File: client.py

package info (click to toggle)
python-awair 0.2.4-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,016 kB
  • sloc: python: 1,041; makefile: 12
file content (76 lines) | stat: -rw-r--r-- 2,264 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
"""Wrapper class to query the Awair API."""

from typing import Any, Dict, NoReturn

from aiohttp import ClientResponse, ClientSession

from python_awair.auth import AwairAuth
from python_awair.exceptions import (
    AuthError,
    AwairError,
    NotFoundError,
    QueryError,
    RatelimitError,
)


class AwairClient:
    """Python asyncio client for the Awair GraphQL API."""

    def __init__(self, authenticator: AwairAuth, session: ClientSession,) -> None:
        """Initialize an AwairClient with sensible defaults."""
        self.__authenticator = authenticator
        self.__session = session

    async def query(self, url: str) -> Any:
        """Query the Awair api, and handle errors."""
        headers = await self.__headers()
        async with self.__session.get(url, headers=headers) as resp:
            if resp.status != 200:
                self.__handle_non_200_error(resp)

            json = await resp.json()
            self.__check_errors_array(json)

            return json

    async def __headers(self) -> Dict[str, str]:
        """Return headers to set on the API request."""
        token = await self.__authenticator.get_bearer_token()
        return {
            "Authorization": f"Bearer {token}",
            "Content-Type": "application/json",
        }

    @staticmethod
    def __check_errors_array(json: Dict[Any, Any]) -> None:
        """Check for an "errors" array and process it.

        Holdover from the GraphQL API, unclear if we could still get messages like this.
        """
        if "errors" in json:
            messages = []
            for error in json["errors"]:
                if "Too many requests" in error["message"]:
                    raise RatelimitError()

                messages.append(error.get("message", "Unknown error"))

            if messages:
                raise AwairError(", ".join(messages))

    @staticmethod
    def __handle_non_200_error(resp: ClientResponse) -> NoReturn:
        if resp.status == 400:
            raise QueryError()

        if resp.status in (401, 403):
            raise AuthError()

        if resp.status == 404:
            raise NotFoundError()

        if resp.status == 429:
            raise RatelimitError()

        raise AwairError()