Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve exception names and documentation #4

Merged
merged 1 commit into from
Jul 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 40 additions & 4 deletions src/aiochris/errors.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
from typing import Optional, Any

import aiohttp
import yarl


async def raise_for_status(res: aiohttp.ClientResponse) -> None:
Expand All @@ -8,6 +11,8 @@ async def raise_for_status(res: aiohttp.ClientResponse) -> None:
if res.status < 400:
res.raise_for_status()
return
if res.status == 401:
raise UnauthorizedError()
exception = BadRequestError if res.status < 500 else InternalServerError
try:
raise exception(res.status, res.url, await res.json())
Expand All @@ -16,26 +21,57 @@ async def raise_for_status(res: aiohttp.ClientResponse) -> None:


class BaseClientError(Exception):
"""Base error raised by aiochris functions."""

pass


class ResponseError(BaseClientError):
class StatusError(BaseClientError):
"""Base exception for 4xx and 5xx HTTP codes."""

def __init__(
self,
status: int,
url: yarl.URL,
message: Optional[Any] = None,
request_data: Optional[Any] = None,
):
super().__init__()
self.status = status
"""HTTP status code"""
self.url = url
"""URL where this error comes from"""
self.message = message
"""Response body"""
self.request_data = request_data
"""Request body"""


class BadRequestError(StatusError):
"""Bad request error."""

pass


class BadRequestError(ResponseError):
class InternalServerError(StatusError):
"""Internal server error."""

pass


class InternalServerError(ResponseError):
class UnauthorizedError(BaseClientError):
"""Unauthorized request."""

pass


class IncorrectLoginError(BaseClientError):
"""Failed HTTP basic auth with bad username or password."""

pass


class NonsenseResponseError(ResponseError):
class NonsenseResponseError(BaseClientError):
"""CUBE returned data which does not make sense."""

pass
9 changes: 5 additions & 4 deletions src/aiochris/link/linked.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import yarl
import importlib

from aiochris.errors import raise_for_status, ResponseError
from aiochris.errors import raise_for_status, StatusError

T = TypeVar("T")

Expand Down Expand Up @@ -150,8 +150,9 @@ async def deserialize_res(
async with sent_request as res:
try:
await raise_for_status(res)
except ResponseError as e:
raise e.__class__(*e.args, f"data={sent_data}")
except StatusError as e:
e.request_data = sent_data
raise e
if return_type is type(None): # noqa
return None
sent_data = await res.json(content_type="application/json")
Expand All @@ -175,4 +176,4 @@ def _beartype_workaround410(t):
"""
See https://github.com/beartype/beartype/issues/410#issuecomment-2249195428
"""
return getattr(t, '__type_beartype__', None) or t
return getattr(t, "__type_beartype__", None) or t