diff --git a/CHANGELOG.md b/CHANGELOG.md index 507f5341..47bb98f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,15 +21,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixes #455, reported by @Klavionik. This error caused the WebSocket handler to erroneously return an instance of BlackSheep response to the underlying ASGI server, causing an error to be logged in the console. -- Update type annotations in the `Application` class code to be more explicit +- Updates type annotations in the `Application` class code to be more explicit about the fact that certain methods must return None (return in __call__ is used to interrupt code execution and not to return objects). -- Improve the normalization logic to not normalize the output for WebSocket +- Improves the normalization logic to not normalize the output for WebSocket requests (as ASGI servers do not allow controlling the response for WebSocket handshake requests). -- Improve the normalization logic to not normalize request handlers that are +- Improves the normalization logic to not normalize request handlers that are valid as they are, as asynchronous functions with a single parameter annotated as Request or WebSocket. +- Fixes #421 reported by @mohd-akram, causing handled exceptions to be logged + like unhandled, when defining exception handlers using subclasses. +- Removes wrong type annotations in two functions in `blacksheep.utils`. ## [2.0.3] - 2023-12-18 :gift: diff --git a/blacksheep/baseapp.pxd b/blacksheep/baseapp.pxd index f8e8fdb5..373b5a30 100644 --- a/blacksheep/baseapp.pxd +++ b/blacksheep/baseapp.pxd @@ -15,3 +15,4 @@ cdef class BaseApplication: cdef public dict exceptions_handlers cdef object get_http_exception_handler(self, HTTPException http_exception) cdef object get_exception_handler(self, Exception exception) + cdef bint is_handled_exception(self, Exception exception) diff --git a/blacksheep/baseapp.pyx b/blacksheep/baseapp.pyx index ddc0bb9c..60a8a6e1 100644 --- a/blacksheep/baseapp.pyx +++ b/blacksheep/baseapp.pyx @@ -96,7 +96,7 @@ cdef class BaseApplication: await self.log_handled_exc(request, exc) return await self.handle_http_exception(request, exc) - if type(exc) in self.exceptions_handlers: + if self.is_handled_exception(exc): await self.log_handled_exc(request, exc) else: await self.log_unhandled_exc(request, exc) @@ -109,6 +109,12 @@ cdef class BaseApplication: except KeyError: return self.exceptions_handlers.get(http_exception.status, common_http_exception_handler) + cdef bint is_handled_exception(self, Exception exception): + for current_class_in_hierarchy in get_class_instance_hierarchy(exception): + if current_class_in_hierarchy in self.exceptions_handlers: + return True + return False + cdef object get_exception_handler(self, Exception exception): for current_class_in_hierarchy in get_class_instance_hierarchy(exception): if current_class_in_hierarchy in self.exceptions_handlers: diff --git a/blacksheep/utils/__init__.py b/blacksheep/utils/__init__.py index 59ce6616..b2484c75 100644 --- a/blacksheep/utils/__init__.py +++ b/blacksheep/utils/__init__.py @@ -1,5 +1,5 @@ import re -from typing import AnyStr, Tuple, Type, TypeVar +from typing import AnyStr, Type, TypeVar T = TypeVar("T") @@ -31,11 +31,11 @@ def join_fragments(*args: AnyStr) -> str: ) -def get_class_hierarchy(cls: Type[T]) -> Tuple[Type[T], ...]: +def get_class_hierarchy(cls: Type[T]): return cls.__mro__ -def get_class_instance_hierarchy(instance: T) -> Tuple[Type[T], ...]: +def get_class_instance_hierarchy(instance: T): return get_class_hierarchy(type(instance))