Passed
Push — main ( c55e7f...350561 )
by Guy
01:16
created

ims_envista.commons._verify_response_or_raise()   A

Complexity

Conditions 2

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 6
nop 1
dl 0
loc 8
rs 10
c 0
b 0
f 0
1
"""IMS Envista Commons."""
2
3
import asyncio
4
import http
5
import logging
6
import socket
7
from json import JSONDecodeError
8
from typing import Any
9
from uuid import UUID
10
11
import async_timeout
12
from aiohttp import (
13
    ClientError,
14
    ClientResponse,
15
    ClientSession,
16
    TraceRequestChunkSentParams,
17
    TraceRequestEndParams,
18
    TraceRequestStartParams,
19
)
20
21
logger = logging.getLogger(__name__)
22
23
24
class ImsEnvistaApiClientError(Exception):
25
    """Exception to indicate a general API error."""
26
27
28
class ImsEnvistaApiClientCommunicationError(
29
    ImsEnvistaApiClientError,
30
):
31
    """Exception to indicate a communication error."""
32
33
34
class ImsEnvistaApiClientAuthenticationError(
35
    ImsEnvistaApiClientError,
36
):
37
    """Exception to indicate an authentication error."""
38
39
40
async def on_request_start_debug(session: ClientSession, context,params: TraceRequestStartParams) -> None:  # noqa: ANN001, ARG001
41
    logger.debug("HTTP %s: %s", params.method, params.url)
42
43
44
async def on_request_chunk_sent_debug(
45
    session: ClientSession, context, params: TraceRequestChunkSentParams  # noqa: ANN001, ARG001
46
) -> None:
47
    if (params.method in ("POST", "PUT")) and params.chunk:
48
        logger.debug("HTTP Content %s: %s", params.method, params.chunk)
49
50
51
async def on_request_end_debug(session: ClientSession, context, params: TraceRequestEndParams) -> None:  # noqa: ANN001, ARG001
52
    response_text = await params.response.text()
53
    logger.debug("HTTP %s Response <%s>: %s", params.method, params.response.status, response_text)
54
55
56
def _get_headers(token: UUID | str) -> dict[str, str]:
57
    return {
58
        "Accept": "application/vnd.github.v3.text-match+json",
59
        "Authorization": f"ApiToken {token!s}"
60
    }
61
62
def _verify_response_or_raise(response: ClientResponse) -> None:
63
    """Verify that the response is valid."""
64
    if response.status in (401, 403):
65
        msg = "Invalid credentials"
66
        raise ImsEnvistaApiClientAuthenticationError(
67
            msg,
68
        )
69
    response.raise_for_status()
70
71
72
async def get(
73
    session: ClientSession, url: str, token: UUID | str, headers: dict | None = None
74
) -> dict[str, Any]:
75
    if not headers:
76
        headers = _get_headers(token)
77
78
    try:
79
        async with async_timeout.timeout(30):
80
            response = await session.get(
81
                url=url,
82
                headers=headers
83
            )
84
            _verify_response_or_raise(response)
85
            json_resp = await response.json()
86
87
    except (TimeoutError, asyncio.exceptions.TimeoutError) as exception:
88
        msg = f"Timeout error fetching information from {url} - {exception}"
89
        raise ImsEnvistaApiClientCommunicationError(
90
            msg,
91
        ) from exception
92
    except (ClientError, socket.gaierror) as exception:
93
        msg = f"Error fetching information from {url} - {exception}"
94
        raise ImsEnvistaApiClientCommunicationError(
95
            msg,
96
        ) from exception
97
    except JSONDecodeError as exception:
98
        msg = f"Failed Parsing Response JSON from {url} - {exception!s}"
99
        raise ImsEnvistaApiClientError(msg) from exception
100
    except Exception as exception:  # pylint: disable=broad-except
101
        msg = f"Something really wrong happened! {url} {exception}"
102
        raise ImsEnvistaApiClientError(
103
            msg,
104
        ) from exception
105
106
    if response.status != http.HTTPStatus.OK:
107
        msg = f"Received Error from IMS Envista API from {url}: {response.status, response.reason}"
108
        raise ImsEnvistaApiClientError(msg)
109
110
    return json_resp
111