Skip to content

Commit

Permalink
Raise SFRBoxError on HTTPError (#59)
Browse files Browse the repository at this point in the history
* Raise SFRBoxError on HTTPError

* Use decorator

* Adjust decorator type hints
  • Loading branch information
epenet authored Jan 17, 2023
1 parent 8c6d2d4 commit a6a6ac1
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 0 deletions.
29 changes: 29 additions & 0 deletions src/sfrbox_api/bridge.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,18 @@
from __future__ import annotations

import logging
from functools import wraps
from typing import Any
from typing import Awaitable
from typing import Callable
from typing import Coroutine
from typing import Mapping
from typing import TypeVar
from xml.etree.ElementTree import Element as XmlElement # noqa: S405

import defusedxml.ElementTree as DefusedElementTree
import httpx
from typing_extensions import ParamSpec

from sfrbox_api.helpers import compute_hash

Expand All @@ -21,6 +27,27 @@


_LOGGER = logging.getLogger(__name__)
_R = TypeVar("_R")
_P = ParamSpec("_P")


def _with_error_wrapping(
func: Callable[_P, Awaitable[_R]]
) -> Callable[_P, Coroutine[Any, Any, _R]]:
"""Catch httpx errors."""

@wraps(func)
async def wrapper(
*args: _P.args,
**kwargs: _P.kwargs,
) -> _R:
"""Catch RequestError errors and raise SFRBoxError."""
try:
return await func(*args, **kwargs)
except httpx.HTTPError as err:
raise SFRBoxError(str(err)) from err

return wrapper


class SFRBox:
Expand Down Expand Up @@ -91,6 +118,7 @@ def _check_response(self, response: httpx.Response) -> XmlElement:
raise SFRBoxError(f"Response was not ok: {response.text}")
return element

@_with_error_wrapping
async def _send_get(self, namespace: str, method: str, **kwargs: str) -> XmlElement:
params = httpx.QueryParams(method=f"{namespace}.{method}", **kwargs)
response = await self._client.get(f"http://{self._ip}/api/1.0/", params=params)
Expand All @@ -102,6 +130,7 @@ async def _send_get(self, namespace: str, method: str, **kwargs: str) -> XmlElem
)
return result

@_with_error_wrapping
async def _send_post(
self,
namespace: str,
Expand Down
24 changes: 24 additions & 0 deletions tests/test_bridge.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,3 +274,27 @@ async def test_wan_getinfo_incorrect_namespace() -> None:
box = SFRBox(ip="192.168.0.1", client=client)
with pytest.raises(SFRBoxError, match="Namespace wan not found in response"):
await box.wan_get_info()


@respx.mock
@pytest.mark.asyncio
async def test_connect_timeout() -> None:
"""It exits with a status code of zero."""
respx.get("http://192.168.0.1/api/1.0/?method=wan.getInfo").mock(
side_effect=httpx.ConnectTimeout
)
async with httpx.AsyncClient() as client:
box = SFRBox(ip="192.168.0.1", client=client)
with pytest.raises(SFRBoxError):
await box.wan_get_info()


@respx.mock
@pytest.mark.asyncio
async def test_500_error() -> None:
"""It exits with a status code of zero."""
respx.get("http://192.168.0.1/api/1.0/?method=wan.getInfo").respond(500)
async with httpx.AsyncClient() as client:
box = SFRBox(ip="192.168.0.1", client=client)
with pytest.raises(SFRBoxError):
await box.wan_get_info()

0 comments on commit a6a6ac1

Please sign in to comment.