Skip to content

Commit fa0bba3

Browse files
committed
udpates web-exceptions-extension
1 parent 1a5aa02 commit fa0bba3

File tree

1 file changed

+70
-1
lines changed

1 file changed

+70
-1
lines changed
Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,77 @@
1-
from aiohttp.web_exceptions import HTTPClientError
1+
import inspect
2+
from typing import Any
3+
4+
from aiohttp import web_exceptions
5+
from aiohttp.web_exceptions import (
6+
HTTPClientError,
7+
HTTPError,
8+
HTTPException,
9+
HTTPServerError,
10+
)
211

312
from . import status
413

14+
# NOTE: these are the status codes that DO NOT have an aiohttp.HTTPException associated
15+
STATUS_CODES_WITHOUT_AIOHTTP_EXCEPTION_CLASS = (
16+
status.HTTP_100_CONTINUE,
17+
status.HTTP_101_SWITCHING_PROTOCOLS,
18+
status.HTTP_102_PROCESSING,
19+
status.HTTP_103_EARLY_HINTS,
20+
status.HTTP_207_MULTI_STATUS,
21+
status.HTTP_208_ALREADY_REPORTED,
22+
status.HTTP_226_IM_USED,
23+
status.HTTP_306_RESERVED,
24+
status.HTTP_418_IM_A_TEAPOT,
25+
status.HTTP_425_TOO_EARLY,
26+
)
27+
528

629
class HTTPLockedError(HTTPClientError):
730
# pylint: disable=too-many-ancestors
831
status_code = status.HTTP_423_LOCKED
32+
33+
34+
class HTTPLoopDetectedError(HTTPServerError):
35+
# pylint: disable=too-many-ancestors
36+
status_code = status.HTTP_508_LOOP_DETECTED
37+
38+
39+
def get_all_aiohttp_http_exceptions(
40+
exception_cls: type[HTTPException] = HTTPException,
41+
) -> dict[int, type[HTTPException]]:
42+
# Inverse map from code to HTTPException classes
43+
44+
def _pred(obj) -> bool:
45+
return (
46+
inspect.isclass(obj)
47+
and issubclass(obj, exception_cls)
48+
and getattr(obj, "status_code", 0) > 0
49+
)
50+
51+
found: list[tuple[str, Any]] = inspect.getmembers(web_exceptions, _pred)
52+
assert found # nosec
53+
54+
status_to_http_exception_map = {cls.status_code: cls for _, cls in found}
55+
assert len(status_to_http_exception_map) == len(found), "No duplicates" # nosec
56+
57+
for cls in (
58+
HTTPLockedError,
59+
HTTPLoopDetectedError,
60+
):
61+
62+
status_to_http_exception_map[cls.status_code] = cls # type:ignore
63+
64+
return status_to_http_exception_map
65+
66+
67+
_STATUS_CODE_TO_HTTP_ERRORS: dict[
68+
int, type[HTTPError]
69+
] = get_all_aiohttp_http_exceptions(HTTPError)
70+
71+
72+
def get_http_error_class_or_none(status_code: int) -> type[HTTPError] | None:
73+
"""Returns aiohttp error class corresponding to a 4XX or 5XX status code
74+
75+
NOTE: any non-error code (i.e. 2XX, 3XX and 4XX) will return None
76+
"""
77+
return _STATUS_CODE_TO_HTTP_ERRORS.get(status_code)

0 commit comments

Comments
 (0)