diff --git a/lona/view_runtime.py b/lona/view_runtime.py index 555e7e47..f877693e 100644 --- a/lona/view_runtime.py +++ b/lona/view_runtime.py @@ -42,6 +42,7 @@ from lona.connection import Connection from lona.request import Request from lona.routing import Route +import lona.warnings # avoid import cycles if TYPE_CHECKING: # pragma: no cover @@ -344,8 +345,16 @@ def start(self): self.send_view_start() # run view + handle_request_return_value = self.view.handle_request(self.request) + if isinstance(handle_request_return_value, dict): + lona.warnings.warn( # NOQA: G010 + 'Deprecated use of dict as return value of method handle_request\n (see: https://lona-web.org/1.x/api-reference/views.html#response-objects)', + lona.warnings.DictResponseDeprecationWarning, + callee=self.view.handle_request, + ) + response = parse_view_return_value( - return_value=self.view.handle_request(self.request), + return_value=handle_request_return_value, interactive=self.route and self.route.interactive, ) diff --git a/lona/warnings.py b/lona/warnings.py new file mode 100644 index 00000000..510fc026 --- /dev/null +++ b/lona/warnings.py @@ -0,0 +1,55 @@ +import warnings as orginal_warnings + + +class ExtendedWarn: + warn = orginal_warnings.warn + + def __call__( + self, message, category=None, stacklevel=1, source=None, callee=None, + ): + # Check if message is already a Warning object + if isinstance(message, Warning): + category = message.__class__ + if callee: + assert stacklevel == 1 + if category is not None: + filename = callee.__func__.__code__.co_filename + lineno = callee.__func__.__code__.co_firstlineno + message = ('callee', message, filename, lineno, category) + else: + stacklevel += 1 + self.warn(message, category, stacklevel, source) # NOQA: G010 + + +warn = ExtendedWarn() +orginal_warnings.warn = warn # type: ignore + +_original_formatwarning = orginal_warnings.formatwarning + + +def _formatwarning_with_callee(message, category, filename, lineno, line): + try: + if ( + not isinstance(message, str) + and isinstance(message.args[0], tuple) + and len(message.args[0]) == 5 + and message.args[0][0] == 'callee' + ): + _, message, filename, lineno, category = message.args[0] + except Exception: + # show original e.g. when message is not a string, + # but has not .args attribute + pass + return _original_formatwarning(message, category, filename, lineno, line) + + +orginal_warnings.formatwarning = _formatwarning_with_callee # type: ignore + + +class DictResponseDeprecationWarning(PendingDeprecationWarning): + pass + + +orginal_warnings.simplefilter( + 'once', category=DictResponseDeprecationWarning, +)