Skip to content

Commit

Permalink
Catch more exceptions (#134)
Browse files Browse the repository at this point in the history
* Catch more exceptions

* Catch more exceptions
  • Loading branch information
joostlek authored Jul 1, 2024
1 parent fbd3e03 commit 3c58204
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 10 deletions.
30 changes: 21 additions & 9 deletions src/airgradient/airgradient.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@

from __future__ import annotations

from asyncio import timeout
import asyncio
from dataclasses import dataclass
from importlib import metadata
import socket
from typing import TYPE_CHECKING, Any

from aiohttp import ClientSession
from aiohttp import ClientError, ClientResponseError, ClientSession
from aiohttp.hdrs import METH_GET, METH_PUT
from yarl import URL

Expand Down Expand Up @@ -56,13 +57,24 @@ async def _request(
self.session = ClientSession()
self._close_session = True

async with timeout(self.request_timeout):
response = await self.session.request(
method,
url,
headers=headers,
json=data,
)
try:
async with asyncio.timeout(self.request_timeout):
response = await self.session.request(
method,
url,
headers=headers,
json=data,
)
except asyncio.TimeoutError as exception:
msg = "Timeout occurred while connecting to the device"
raise AirGradientConnectionError(msg) from exception
except (
ClientError,
ClientResponseError,
socket.gaierror,
) as exception:
msg = "Error occurred while communicating with the device"
raise AirGradientConnectionError(msg) from exception

if response.status != 200:
content_type = response.headers.get("Content-Type", "")
Expand Down
43 changes: 42 additions & 1 deletion tests/test_airgradient.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,18 @@

from __future__ import annotations

import asyncio
from typing import TYPE_CHECKING, Any, Awaitable, Callable

import aiohttp
from aiohttp import ClientError
from aiohttp.hdrs import METH_PUT
from aioresponses import aioresponses
from aioresponses import CallbackResult, aioresponses
import pytest

from airgradient import (
AirGradientClient,
AirGradientConnectionError,
AirGradientError,
ConfigurationControl,
LedBarMode,
Expand Down Expand Up @@ -74,6 +77,44 @@ async def test_unexpected_server_response(
assert await client.get_current_measures()


async def test_timeout(
responses: aioresponses,
) -> None:
"""Test request timeout."""

# Faking a timeout by sleeping
async def response_handler(_: str, **_kwargs: Any) -> CallbackResult:
"""Response handler for this test."""
await asyncio.sleep(2)
return CallbackResult(body="Goodmorning!")

responses.get(
f"{MOCK_URL}/measures/current",
callback=response_handler,
)
async with AirGradientClient(request_timeout=1, host=MOCK_HOST) as airgradient:
with pytest.raises(AirGradientConnectionError):
assert await airgradient.get_current_measures()


async def test_client_error(
client: AirGradientClient,
responses: aioresponses,
) -> None:
"""Test client error."""

async def response_handler(_: str, **_kwargs: Any) -> CallbackResult:
"""Response handler for this test."""
raise ClientError

responses.post(
f"{MOCK_URL}/measures/current",
callback=response_handler,
)
with pytest.raises(AirGradientConnectionError):
assert await client.get_current_measures()


@pytest.mark.parametrize(
"fixture",
["current_measures.json", "measures_after_boot.json"],
Expand Down

0 comments on commit 3c58204

Please sign in to comment.