Skip to content

Commit

Permalink
views: warn if handle_request returns dict
Browse files Browse the repository at this point in the history
With this change a warnings.warn() is invoked when a handle_request
returns a dict instead of a response objec. This warning is issued once
for each unique file-name, line-number of the "offending" handle_request(s).
The warning references the file and line number of the "offending" handle_request
method and a link to the Response Objects documentation.

The end-user can influence the result of the warning in the usual way by
including the following lines:

   import warnings
   from lona.warnings import DictResponseDeprecationWarning

   warnings.simplefilter('always', DictResponseDeprecationWarning)

causing the warning to issue every time (other options include 'error' and 'ignore')

The warnings.warn mechanism is patched to be able to handle printing
callee file-name and line-number (instead of the more usual caller info),
in a similar way as the package ruamel.std.warnings.
  • Loading branch information
AvdN committed Jul 27, 2023
1 parent 1128d62 commit 0746661
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 1 deletion.
11 changes: 10 additions & 1 deletion lona/view_runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
)

Expand Down
55 changes: 55 additions & 0 deletions lona/warnings.py
Original file line number Diff line number Diff line change
@@ -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,
)

0 comments on commit 0746661

Please sign in to comment.