Skip to content

Commit f8e744c

Browse files
committed
renames
1 parent 6f27e33 commit f8e744c

File tree

8 files changed

+75
-37
lines changed

8 files changed

+75
-37
lines changed

services/web/server/src/simcore_service_webserver/exceptions_handlers.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from .exceptions_handlers_base import async_try_except_decorator
1+
from .exceptions_handlers_base import exception_handling_decorator
22
from .exceptions_handlers_http_error_map import (
33
ExceptionToHttpErrorMap,
44
HttpErrorInfo,
@@ -8,7 +8,7 @@
88
__all__: tuple[str, ...] = (
99
"ExceptionToHttpErrorMap",
1010
"HttpErrorInfo",
11-
"async_try_except_decorator",
11+
"exception_handling_decorator",
1212
"to_exceptions_handlers_map",
1313
)
1414

services/web/server/src/simcore_service_webserver/exceptions_handlers_base.py

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
from aiohttp import web
99
from servicelib.aiohttp.typing_extension import Handler as WebHandler
10+
from servicelib.aiohttp.typing_extension import Middleware as WebMiddleware
1011

1112
_logger = logging.getLogger(__name__)
1213

@@ -46,10 +47,7 @@ def _sort_exceptions_by_specificity(
4647
ExceptionHandlersMap: TypeAlias = dict[type[BaseException], AiohttpExceptionHandler]
4748

4849

49-
class AsyncDynamicTryExceptContext(AbstractAsyncContextManager):
50-
"""Context manager to handle exceptions if they match any in the
51-
exception_handlers_map"""
52-
50+
class ExceptionHandlingContextManager(AbstractAsyncContextManager):
5351
def __init__(
5452
self,
5553
exception_handlers_map: ExceptionHandlersMap,
@@ -105,13 +103,15 @@ def get_response(self):
105103
return self._response
106104

107105

108-
def async_try_except_decorator(
106+
def exception_handling_decorator(
109107
exception_handlers_map: dict[type[BaseException], AiohttpExceptionHandler]
110108
):
111109
def _decorator(handler: WebHandler):
112110
@functools.wraps(handler)
113111
async def _wrapper(request: web.Request) -> web.StreamResponse:
114-
cm = AsyncDynamicTryExceptContext(exception_handlers_map, request=request)
112+
cm = ExceptionHandlingContextManager(
113+
exception_handlers_map, request=request
114+
)
115115
async with cm:
116116
return await handler(request)
117117

@@ -123,3 +123,17 @@ async def _wrapper(request: web.Request) -> web.StreamResponse:
123123
return _wrapper
124124

125125
return _decorator
126+
127+
128+
def exception_handling_middleware(
129+
exception_handlers_map: dict[type[BaseException], AiohttpExceptionHandler]
130+
) -> WebMiddleware:
131+
_handle_excs = exception_handling_decorator(
132+
exception_handlers_map=exception_handlers_map
133+
)
134+
135+
@web.middleware
136+
async def middleware_handler(request: web.Request, handler: WebHandler):
137+
return await _handle_excs(handler)(request)
138+
139+
return middleware_handler

services/web/server/src/simcore_service_webserver/exceptions_handlers_http_error_map.py

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,22 @@
88
from models_library.rest_error import ErrorGet
99
from servicelib.aiohttp.web_exceptions_extension import get_all_aiohttp_http_exceptions
1010
from servicelib.logging_errors import create_troubleshotting_log_kwargs
11-
from servicelib.status_codes_utils import is_5xx_server_error
11+
from servicelib.status_codes_utils import is_5xx_server_error, is_error
1212

1313
from .exceptions_handlers_base import AiohttpExceptionHandler, ExceptionHandlersMap
1414

1515
_logger = logging.getLogger(__name__)
1616

1717

18-
_STATUS_CODE_TO_HTTP_ERRORS: dict[
19-
int, type[web.HTTPException]
20-
] = get_all_aiohttp_http_exceptions(web.HTTPError)
18+
def create_error_response(error: ErrorGet, status_code: int) -> web.Response:
19+
assert is_error(status_code), f"{status_code=} must be an error [{error=}]" # nosec
20+
21+
return web.json_response(
22+
data={"error": error.model_dump(exclude_unset=True, mode="json")},
23+
dumps=json_dumps,
24+
reason=error.msg,
25+
status=status_code,
26+
)
2127

2228

2329
class _DefaultDict(dict):
@@ -35,7 +41,7 @@ class HttpErrorInfo(NamedTuple):
3541
ExceptionToHttpErrorMap: TypeAlias = dict[type[BaseException], HttpErrorInfo]
3642

3743

38-
def create_exception_handler_from_http_error(
44+
def create_exception_handler_from_http_info(
3945
status_code: int,
4046
msg_template: str,
4147
) -> AiohttpExceptionHandler:
@@ -56,10 +62,13 @@ def create_exception_handler_from_http_error(
5662
Returns:
5763
A web api exception handler
5864
"""
65+
assert is_error( # nosec
66+
status_code
67+
), f"{status_code=} must be an error [{msg_template=}]"
5968

6069
async def _exception_handler(
6170
request: web.Request,
62-
exception: BaseException,
71+
exception: BaseException, # TODO: for different type of exceptions e.g HTTPError
6372
) -> web.Response:
6473

6574
# safe formatting, i.e. does not raise
@@ -86,12 +95,7 @@ async def _exception_handler(
8695
)
8796
error = ErrorGet(msg=user_msg, support_id=IDStr(oec))
8897

89-
return web.json_response(
90-
data={"error": error.model_dump(exclude_unset=True, mode="json")},
91-
dumps=json_dumps,
92-
reason=user_msg,
93-
status=status_code,
94-
)
98+
return create_error_response(error, status_code=status_code)
9599

96100
return _exception_handler
97101

@@ -101,10 +105,28 @@ def to_exceptions_handlers_map(
101105
) -> ExceptionHandlersMap:
102106
"""Converts { exc_type: (status, msg), ... } -> { exc_type: callable, ... }"""
103107
exc_handlers_map: ExceptionHandlersMap = {
104-
exc_type: create_exception_handler_from_http_error(
108+
exc_type: create_exception_handler_from_http_info(
105109
status_code=info.status_code, msg_template=info.msg_template
106110
)
107111
for exc_type, info in exc_to_http_error_map.items()
108112
}
109113

110114
return exc_handlers_map
115+
116+
117+
_STATUS_CODE_TO_HTTP_ERRORS: dict[
118+
int, type[web.HTTPError]
119+
] = get_all_aiohttp_http_exceptions(web.HTTPError)
120+
121+
122+
def create_http_error_exception_handlers_map():
123+
"""
124+
Creates handles for all web.HTTPError
125+
"""
126+
exc_handlers_map: ExceptionHandlersMap = {
127+
exc_type: create_exception_handler_from_http_info(
128+
status_code=code, msg_template="{reason}"
129+
)
130+
for code, exc_type in _STATUS_CODE_TO_HTTP_ERRORS.items()
131+
}
132+
return exc_handlers_map

services/web/server/src/simcore_service_webserver/folders/_exceptions_handlers.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from ..exceptions_handlers import (
66
ExceptionToHttpErrorMap,
77
HttpErrorInfo,
8-
async_try_except_decorator,
8+
exception_handling_decorator,
99
to_exceptions_handlers_map,
1010
)
1111
from ..projects.exceptions import ProjectRunningConflictError, ProjectStoppingError
@@ -65,7 +65,7 @@
6565
}
6666

6767

68-
handle_plugin_requests_exceptions = async_try_except_decorator(
68+
handle_plugin_requests_exceptions = exception_handling_decorator(
6969
to_exceptions_handlers_map(_TO_HTTP_ERROR_MAP)
7070
)
7171
# this is one decorator with a single exception handler

services/web/server/src/simcore_service_webserver/projects/_trash_handlers.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from ..exceptions_handlers import (
1313
ExceptionToHttpErrorMap,
1414
HttpErrorInfo,
15-
async_try_except_decorator,
15+
exception_handling_decorator,
1616
to_exceptions_handlers_map,
1717
)
1818
from ..login.decorators import get_user_id, login_required
@@ -42,7 +42,7 @@
4242
}
4343

4444

45-
_handle_exceptions = async_try_except_decorator(
45+
_handle_exceptions = exception_handling_decorator(
4646
to_exceptions_handlers_map(_TO_HTTP_ERROR_MAP)
4747
)
4848

services/web/server/src/simcore_service_webserver/workspaces/_exceptions_handlers.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from ..exceptions_handlers import (
66
ExceptionToHttpErrorMap,
77
HttpErrorInfo,
8-
async_try_except_decorator,
8+
exception_handling_decorator,
99
to_exceptions_handlers_map,
1010
)
1111
from ..projects.exceptions import ProjectRunningConflictError, ProjectStoppingError
@@ -43,6 +43,6 @@
4343
}
4444

4545

46-
handle_plugin_requests_exceptions = async_try_except_decorator(
46+
handle_plugin_requests_exceptions = exception_handling_decorator(
4747
to_exceptions_handlers_map(_TO_HTTP_ERROR_MAP)
4848
)

services/web/server/tests/unit/isolated/test_exceptions_handlers_base.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212
from simcore_service_webserver.errors import WebServerBaseError
1313
from simcore_service_webserver.exceptions_handlers_base import (
1414
AiohttpExceptionHandler,
15-
AsyncDynamicTryExceptContext,
15+
ExceptionHandlingContextManager,
1616
_sort_exceptions_by_specificity,
17-
async_try_except_decorator,
17+
exception_handling_decorator,
1818
)
1919

2020
# Some custom errors in my service
@@ -88,7 +88,9 @@ async def _concrete_exc_handler(request, exception):
8888
}
8989

9090
# handles any BaseError returning a response
91-
cm = AsyncDynamicTryExceptContext(exception_handlers_map, request=expected_request)
91+
cm = ExceptionHandlingContextManager(
92+
exception_handlers_map, request=expected_request
93+
)
9294
async with cm:
9395
raise OneError
9496
assert cm.get_response() == expected_response
@@ -115,7 +117,7 @@ async def _suppress_all(request: web.Request, exception):
115117
assert request == expected_request
116118
return expected_response
117119

118-
@async_try_except_decorator({BaseError: _suppress_all})
120+
@exception_handling_decorator({BaseError: _suppress_all})
119121
async def _rest_handler(request: web.Request) -> web.Response:
120122
raise expected_exception
121123

services/web/server/tests/unit/isolated/test_exceptions_handlers_http_error_map.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@
1515
from servicelib.mimetype_constants import MIMETYPE_APPLICATION_JSON
1616
from simcore_service_webserver.errors import WebServerBaseError
1717
from simcore_service_webserver.exceptions_handlers_base import (
18-
AsyncDynamicTryExceptContext,
19-
async_try_except_decorator,
18+
ExceptionHandlingContextManager,
19+
exception_handling_decorator,
2020
)
2121
from simcore_service_webserver.exceptions_handlers_http_error_map import (
2222
ExceptionToHttpErrorMap,
2323
HttpErrorInfo,
24-
create_exception_handler_from_http_error,
24+
create_exception_handler_from_http_info,
2525
to_exceptions_handlers_map,
2626
)
2727

@@ -48,7 +48,7 @@ def fake_request() -> web.Request:
4848
async def test_factory__create_exception_handler_from_http_error(
4949
fake_request: web.Request,
5050
):
51-
one_error_to_404 = create_exception_handler_from_http_error(
51+
one_error_to_404 = create_exception_handler_from_http_info(
5252
status_code=status.HTTP_404_NOT_FOUND,
5353
msg_template="one error message for the user: {code} {value}",
5454
)
@@ -70,7 +70,7 @@ async def test_handling_different_exceptions_with_context(
7070
OneError: HttpErrorInfo(status.HTTP_400_BAD_REQUEST, "Error {code} to 400"),
7171
OtherError: HttpErrorInfo(status.HTTP_500_INTERNAL_SERVER_ERROR, "{code}"),
7272
}
73-
cm = AsyncDynamicTryExceptContext(
73+
cm = ExceptionHandlingContextManager(
7474
to_exceptions_handlers_map(exc_to_http_error_map), request=fake_request
7575
)
7676

@@ -118,7 +118,7 @@ async def test_handling_different_exceptions_with_decorator(
118118
OneError: HttpErrorInfo(status.HTTP_503_SERVICE_UNAVAILABLE, "{code}"),
119119
}
120120

121-
exc_handling_decorator = async_try_except_decorator(
121+
exc_handling_decorator = exception_handling_decorator(
122122
to_exceptions_handlers_map(exc_to_http_error_map)
123123
)
124124

0 commit comments

Comments
 (0)