diff --git a/falcon/app.py b/falcon/app.py index 442d41676..34186b418 100644 --- a/falcon/app.py +++ b/falcon/app.py @@ -20,6 +20,7 @@ import re import traceback from typing import Callable, Iterable, Optional, Tuple, Type, Union +import warnings from falcon import app_helpers as helpers from falcon import constants @@ -828,6 +829,12 @@ def handler(req, resp, ex, params): ('ex',), ('exception',), ) or arg_names[1:3] in (('req', 'resp'), ('request', 'response')): + warnings.warn( + f'handler is using a deprecated signature; please order its ' + f'arguments as {handler.__qualname__}(req, resp, ex, params). ' + f'This compatibility shim will be removed in Falcon 5.0.', + deprecation.DeprecatedWarning, + ) handler = wrap_old_handler(handler) exception_tuple: tuple diff --git a/tests/test_error_handlers.py b/tests/test_error_handlers.py index c43589dbb..06282bdc7 100644 --- a/tests/test_error_handlers.py +++ b/tests/test_error_handlers.py @@ -3,6 +3,7 @@ import falcon from falcon import constants, testing import falcon.asgi +from falcon.util.deprecation import DeprecatedWarning from _util import create_app, disable_asgi_non_coroutine_wrapping # NOQA @@ -212,9 +213,12 @@ def legacy_handler3(err, rq, rs, prms): app.add_route('/', ErroredClassResource()) client = testing.TestClient(app) - client.app.add_error_handler(Exception, legacy_handler1) - client.app.add_error_handler(CustomBaseException, legacy_handler2) - client.app.add_error_handler(CustomException, legacy_handler3) + with pytest.warns(DeprecatedWarning, match='deprecated signature'): + client.app.add_error_handler(Exception, legacy_handler1) + with pytest.warns(DeprecatedWarning, match='deprecated signature'): + client.app.add_error_handler(CustomBaseException, legacy_handler2) + with pytest.warns(DeprecatedWarning, match='deprecated signature'): + client.app.add_error_handler(CustomException, legacy_handler3) client.simulate_delete() client.simulate_get() diff --git a/tests/test_middleware.py b/tests/test_middleware.py index c4aecd3e6..52516622e 100644 --- a/tests/test_middleware.py +++ b/tests/test_middleware.py @@ -9,6 +9,7 @@ import falcon import falcon.errors import falcon.testing as testing +from falcon.util.deprecation import DeprecatedWarning from falcon.util.misc import _utcnow from _util import create_app # NOQA @@ -900,14 +901,19 @@ def test_http_status_raised_from_error_handler(self, asgi): def _http_error_handler(error, req, resp, params): raise falcon.HTTPStatus(falcon.HTTP_201) - async def _http_error_handler_async(error, req, resp, params): + async def _http_error_handler_async(req, resp, error, params): raise falcon.HTTPStatus(falcon.HTTP_201) h = _http_error_handler_async if asgi else _http_error_handler # NOTE(kgriffs): This will take precedence over the default # handler for facon.HTTPError. - app.add_error_handler(falcon.HTTPError, h) + if asgi: + # NOTE(vytas): The ASGI flavour supports no reordering shim. + app.add_error_handler(falcon.HTTPError, h) + else: + with pytest.warns(DeprecatedWarning, match='deprecated signature'): + app.add_error_handler(falcon.HTTPError, h) response = client.simulate_request(path='/', method='POST') assert response.status == falcon.HTTP_201