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 2fd722c
Show file tree
Hide file tree
Showing 2 changed files with 62 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
52 changes: 52 additions & 0 deletions lona/warnings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import warnings as org_warnings


class ExtendedWarn:
warn = org_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


org_warnings.warn = warn = ExtendedWarn()

_org_formatwarning = org_warnings.formatwarning


def my_formatwarning(message, category, filename, lineno, line):
if (
isinstance(message.args[0], tuple)
and len(message.args[0]) == 5
and message.args[0][0] == 'callee'
):
try:
_, message, filename, lineno, category = message.args[0]
except ValueError: # in case there was no tuple provided
pass
raise
return _org_formatwarning(message, category, filename, lineno, line)


org_warnings.formatwarning = my_formatwarning


class DictResponseDeprecationWarning(PendingDeprecationWarning):
pass


org_warnings.simplefilter(
'once', category=DictResponseDeprecationWarning,
)

0 comments on commit 2fd722c

Please sign in to comment.