From 464fedb6b1fe499e179ff8c97625e3bfc04c3fc8 Mon Sep 17 00:00:00 2001 From: Eric Zhang Date: Sun, 5 May 2024 23:31:40 -0400 Subject: [PATCH] Make the `.message` field on exceptions non-empty This allows subclasses of SanicException to access their message via the `message` attribute. This makes it consistent with the `status_code`, `quiet`, `headers` attributes that were previously present on the class. Currently, the message attribute is present on the class but not on the instance, so accessing SanicException().message will return an empty string "" instead of the actual message "Internal Server Error", which you can get by calling the __str__() method or str(). This is a bit surprising, since the .message attribute shows up in autocomplete and type-checking. It also happens for the other exceptions, like str(BadRequest()) == "" as well. I set the message attribute on instances of SanicException and added tests for this new behavior. --- sanic/exceptions.py | 6 ++++-- tests/test_exceptions.py | 13 +++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/sanic/exceptions.py b/sanic/exceptions.py index 52e210580e..ce7c91db58 100644 --- a/sanic/exceptions.py +++ b/sanic/exceptions.py @@ -75,8 +75,9 @@ def __init__( quiet = quiet or getattr(self.__class__, "quiet", None) headers = headers or getattr(self.__class__, "headers", {}) if message is None: - if self.message: - message = self.message + cls_message = getattr(self.__class__, "message", None) + if cls_message: + message = cls_message elif status_code: msg: bytes = STATUS_CODES.get(status_code, b"") message = msg.decode("utf8") @@ -86,6 +87,7 @@ def __init__( self.status_code = status_code or self.status_code self.quiet = quiet self.headers = headers + self.message = message class HTTPException(SanicException): diff --git a/tests/test_exceptions.py b/tests/test_exceptions.py index 29c4e45c8f..ebcda8f9bc 100644 --- a/tests/test_exceptions.py +++ b/tests/test_exceptions.py @@ -398,3 +398,16 @@ def test_exception_aliases(): assert MethodNotSupported is MethodNotAllowed assert ContentRangeError is RangeNotSatisfiable assert HeaderExpectationFailed is ExpectationFailed + + +def test_exception_message_attribute(): + assert ServerError("it failed").message == "it failed" + assert ServerError(b"it failed").message == b"it failed" + assert ServerError().message == str(ServerError()) == "Internal Server Error" + + class CustomError(SanicException): + message = "Something bad happened" + + assert CustomError().message == CustomError.message == str(CustomError()) + assert SanicException().message != "" + assert SanicException("").message == ""