From 3351a8677e5bd1e1b8cfe2860b73b3422cde4f31 Mon Sep 17 00:00:00 2001 From: David Lord Date: Sun, 5 Jun 2022 15:44:28 -0700 Subject: [PATCH] add errorhandler type check tests --- src/flask/blueprints.py | 6 +++-- src/flask/scaffold.py | 4 ++-- src/flask/typing.py | 1 + tests/typing/typing_error_handler.py | 33 ++++++++++++++++++++++++++++ 4 files changed, 40 insertions(+), 4 deletions(-) create mode 100644 tests/typing/typing_error_handler.py diff --git a/src/flask/blueprints.py b/src/flask/blueprints.py index cf04cd78..87617989 100644 --- a/src/flask/blueprints.py +++ b/src/flask/blueprints.py @@ -561,12 +561,14 @@ class Blueprint(Scaffold): ) return f - def app_errorhandler(self, code: t.Union[t.Type[Exception], int]) -> t.Callable: + def app_errorhandler( + self, code: t.Union[t.Type[Exception], int] + ) -> t.Callable[[ft.ErrorHandlerDecorator], ft.ErrorHandlerDecorator]: """Like :meth:`Flask.errorhandler` but for a blueprint. This handler is used for all requests, even if outside of the blueprint. """ - def decorator(f: ft.ErrorHandlerCallable) -> ft.ErrorHandlerCallable: + def decorator(f: ft.ErrorHandlerDecorator) -> ft.ErrorHandlerDecorator: self.record_once(lambda s: s.app.errorhandler(code)(f)) return f diff --git a/src/flask/scaffold.py b/src/flask/scaffold.py index 8400e892..dedfe309 100644 --- a/src/flask/scaffold.py +++ b/src/flask/scaffold.py @@ -654,7 +654,7 @@ class Scaffold: @setupmethod def errorhandler( self, code_or_exception: t.Union[t.Type[Exception], int] - ) -> t.Callable[[ft.ErrorHandlerCallable], ft.ErrorHandlerCallable]: + ) -> t.Callable[[ft.ErrorHandlerDecorator], ft.ErrorHandlerDecorator]: """Register a function to handle errors by code or exception class. A decorator that is used to register a function given an @@ -684,7 +684,7 @@ class Scaffold: an arbitrary exception """ - def decorator(f: ft.ErrorHandlerCallable) -> ft.ErrorHandlerCallable: + def decorator(f: ft.ErrorHandlerDecorator) -> ft.ErrorHandlerDecorator: self.register_error_handler(code_or_exception, f) return f diff --git a/src/flask/typing.py b/src/flask/typing.py index d463a8de..e6d67f20 100644 --- a/src/flask/typing.py +++ b/src/flask/typing.py @@ -52,6 +52,7 @@ URLValuePreprocessorCallable = t.Callable[[t.Optional[str], t.Optional[dict]], N # https://github.com/pallets/flask/issues/4295 # https://github.com/pallets/flask/issues/4297 ErrorHandlerCallable = t.Callable[[t.Any], ResponseReturnValue] +ErrorHandlerDecorator = t.TypeVar("ErrorHandlerDecorator", bound=ErrorHandlerCallable) ViewCallable = t.Callable[..., ResponseReturnValue] RouteDecorator = t.TypeVar("RouteDecorator", bound=ViewCallable) diff --git a/tests/typing/typing_error_handler.py b/tests/typing/typing_error_handler.py new file mode 100644 index 00000000..ec9c886f --- /dev/null +++ b/tests/typing/typing_error_handler.py @@ -0,0 +1,33 @@ +from __future__ import annotations + +from http import HTTPStatus + +from werkzeug.exceptions import BadRequest +from werkzeug.exceptions import NotFound + +from flask import Flask + +app = Flask(__name__) + + +@app.errorhandler(400) +@app.errorhandler(HTTPStatus.BAD_REQUEST) +@app.errorhandler(BadRequest) +def handle_400(e: BadRequest) -> str: + return "" + + +@app.errorhandler(ValueError) +def handle_custom(e: ValueError) -> str: + return "" + + +@app.errorhandler(ValueError) +def handle_accept_base(e: Exception) -> str: + return "" + + +@app.errorhandler(BadRequest) +@app.errorhandler(404) +def handle_multiple(e: BadRequest | NotFound) -> str: + return ""