mirror of https://github.com/pallets/flask.git
Merge branch '2.1.x'
This commit is contained in:
commit
9e2e1de2fc
10
CHANGES.rst
10
CHANGES.rst
|
|
@ -22,6 +22,16 @@ Unreleased
|
|||
:issue:`4571`
|
||||
|
||||
|
||||
Version 2.1.3
|
||||
-------------
|
||||
|
||||
Unreleased
|
||||
|
||||
- Inline some optional imports that are only used for certain CLI
|
||||
commands. :pr:`4606`
|
||||
- Relax type annotation for ``after_request`` functions. :issue:`4600`
|
||||
|
||||
|
||||
Version 2.1.2
|
||||
-------------
|
||||
|
||||
|
|
|
|||
|
|
@ -34,17 +34,15 @@ Celery without any reconfiguration with Flask, it becomes a bit nicer by
|
|||
subclassing tasks and adding support for Flask's application contexts and
|
||||
hooking it up with the Flask configuration.
|
||||
|
||||
This is all that is necessary to properly integrate Celery with Flask::
|
||||
This is all that is necessary to integrate Celery with Flask:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from celery import Celery
|
||||
|
||||
def make_celery(app):
|
||||
celery = Celery(
|
||||
app.import_name,
|
||||
backend=app.config['CELERY_RESULT_BACKEND'],
|
||||
broker=app.config['CELERY_BROKER_URL']
|
||||
)
|
||||
celery.conf.update(app.config)
|
||||
celery = Celery(app.import_name)
|
||||
celery.conf.update(app.config["CELERY_CONFIG"])
|
||||
|
||||
class ContextTask(celery.Task):
|
||||
def __call__(self, *args, **kwargs):
|
||||
|
|
@ -59,6 +57,12 @@ from the application config, updates the rest of the Celery config from
|
|||
the Flask config and then creates a subclass of the task that wraps the
|
||||
task execution in an application context.
|
||||
|
||||
.. note::
|
||||
Celery 5.x deprecated uppercase configuration keys, and 6.x will
|
||||
remove them. See their official `migration guide`_.
|
||||
|
||||
.. _migration guide: https://docs.celeryproject.org/en/stable/userguide/configuration.html#conf-old-settings-map.
|
||||
|
||||
An example task
|
||||
---------------
|
||||
|
||||
|
|
@ -69,10 +73,10 @@ application using the factory from above, and then use it to define the task. ::
|
|||
from flask import Flask
|
||||
|
||||
flask_app = Flask(__name__)
|
||||
flask_app.config.update(
|
||||
CELERY_BROKER_URL='redis://localhost:6379',
|
||||
CELERY_RESULT_BACKEND='redis://localhost:6379'
|
||||
)
|
||||
flask_app.config.update(CELERY_CONFIG={
|
||||
'broker_url': 'redis://localhost:6379',
|
||||
'result_backend': 'redis://localhost:6379',
|
||||
})
|
||||
celery = make_celery(flask_app)
|
||||
|
||||
@celery.task()
|
||||
|
|
|
|||
|
|
@ -67,10 +67,12 @@ This tells Python to copy everything in the ``static`` and ``templates``
|
|||
directories, and the ``schema.sql`` file, but to exclude all bytecode
|
||||
files.
|
||||
|
||||
See the `official packaging guide`_ for another explanation of the files
|
||||
See the official `Packaging tutorial <packaging tutorial_>`_ and
|
||||
`detailed guide <packaging guide_>`_ for more explanation of the files
|
||||
and options used.
|
||||
|
||||
.. _official packaging guide: https://packaging.python.org/tutorials/packaging-projects/
|
||||
.. _packaging tutorial: https://packaging.python.org/tutorials/packaging-projects/
|
||||
.. _packaging guide: https://packaging.python.org/guides/distributing-packages-using-setuptools/
|
||||
|
||||
|
||||
Install the Project
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ click==8.1.3
|
|||
# pip-tools
|
||||
distlib==0.3.4
|
||||
# via virtualenv
|
||||
filelock==3.7.0
|
||||
filelock==3.7.1
|
||||
# via
|
||||
# tox
|
||||
# virtualenv
|
||||
|
|
@ -30,7 +30,7 @@ pep517==0.12.0
|
|||
# via pip-tools
|
||||
pip-compile-multi==2.4.5
|
||||
# via -r requirements/dev.in
|
||||
pip-tools==6.6.1
|
||||
pip-tools==6.6.2
|
||||
# via pip-compile-multi
|
||||
platformdirs==2.5.2
|
||||
# via virtualenv
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ cffi==1.15.0
|
|||
# via cryptography
|
||||
cryptography==37.0.2
|
||||
# via -r requirements/typing.in
|
||||
mypy==0.950
|
||||
mypy==0.960
|
||||
# via -r requirements/typing.in
|
||||
mypy-extensions==0.4.3
|
||||
# via mypy
|
||||
|
|
@ -17,11 +17,11 @@ pycparser==2.21
|
|||
# via cffi
|
||||
tomli==2.0.1
|
||||
# via mypy
|
||||
types-contextvars==2.4.5
|
||||
types-contextvars==2.4.6
|
||||
# via -r requirements/typing.in
|
||||
types-dataclasses==0.6.5
|
||||
# via -r requirements/typing.in
|
||||
types-setuptools==57.4.15
|
||||
types-setuptools==57.4.17
|
||||
# via -r requirements/typing.in
|
||||
typing-extensions==4.2.0
|
||||
# via mypy
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ from werkzeug.wrappers import Response as BaseResponse
|
|||
|
||||
from . import cli
|
||||
from . import json
|
||||
from . import typing as ft
|
||||
from .config import Config
|
||||
from .config import ConfigAttribute
|
||||
from .ctx import _AppCtxGlobals
|
||||
|
|
@ -61,12 +62,6 @@ from .signals import request_started
|
|||
from .signals import request_tearing_down
|
||||
from .templating import DispatchingJinjaLoader
|
||||
from .templating import Environment
|
||||
from .typing import BeforeFirstRequestCallable
|
||||
from .typing import ResponseReturnValue
|
||||
from .typing import TeardownCallable
|
||||
from .typing import TemplateFilterCallable
|
||||
from .typing import TemplateGlobalCallable
|
||||
from .typing import TemplateTestCallable
|
||||
from .wrappers import Request
|
||||
from .wrappers import Response
|
||||
|
||||
|
|
@ -75,7 +70,6 @@ if t.TYPE_CHECKING: # pragma: no cover
|
|||
from .blueprints import Blueprint
|
||||
from .testing import FlaskClient
|
||||
from .testing import FlaskCliRunner
|
||||
from .typing import ErrorHandlerCallable
|
||||
|
||||
if sys.version_info >= (3, 8):
|
||||
iscoroutinefunction = inspect.iscoroutinefunction
|
||||
|
|
@ -458,7 +452,7 @@ class Flask(Scaffold):
|
|||
#: :meth:`before_first_request` decorator.
|
||||
#:
|
||||
#: .. versionadded:: 0.8
|
||||
self.before_first_request_funcs: t.List[BeforeFirstRequestCallable] = []
|
||||
self.before_first_request_funcs: t.List[ft.BeforeFirstRequestCallable] = []
|
||||
|
||||
#: A list of functions that are called when the application context
|
||||
#: is destroyed. Since the application context is also torn down
|
||||
|
|
@ -466,7 +460,7 @@ class Flask(Scaffold):
|
|||
#: from databases.
|
||||
#:
|
||||
#: .. versionadded:: 0.9
|
||||
self.teardown_appcontext_funcs: t.List[TeardownCallable] = []
|
||||
self.teardown_appcontext_funcs: t.List[ft.TeardownCallable] = []
|
||||
|
||||
#: A list of shell context processor functions that should be run
|
||||
#: when a shell context is created.
|
||||
|
|
@ -1139,7 +1133,7 @@ class Flask(Scaffold):
|
|||
@setupmethod
|
||||
def template_filter(
|
||||
self, name: t.Optional[str] = None
|
||||
) -> t.Callable[[TemplateFilterCallable], TemplateFilterCallable]:
|
||||
) -> t.Callable[[ft.TemplateFilterCallable], ft.TemplateFilterCallable]:
|
||||
"""A decorator that is used to register custom template filter.
|
||||
You can specify a name for the filter, otherwise the function
|
||||
name will be used. Example::
|
||||
|
|
@ -1152,7 +1146,7 @@ class Flask(Scaffold):
|
|||
function name will be used.
|
||||
"""
|
||||
|
||||
def decorator(f: TemplateFilterCallable) -> TemplateFilterCallable:
|
||||
def decorator(f: ft.TemplateFilterCallable) -> ft.TemplateFilterCallable:
|
||||
self.add_template_filter(f, name=name)
|
||||
return f
|
||||
|
||||
|
|
@ -1160,7 +1154,7 @@ class Flask(Scaffold):
|
|||
|
||||
@setupmethod
|
||||
def add_template_filter(
|
||||
self, f: TemplateFilterCallable, name: t.Optional[str] = None
|
||||
self, f: ft.TemplateFilterCallable, name: t.Optional[str] = None
|
||||
) -> None:
|
||||
"""Register a custom template filter. Works exactly like the
|
||||
:meth:`template_filter` decorator.
|
||||
|
|
@ -1173,7 +1167,7 @@ class Flask(Scaffold):
|
|||
@setupmethod
|
||||
def template_test(
|
||||
self, name: t.Optional[str] = None
|
||||
) -> t.Callable[[TemplateTestCallable], TemplateTestCallable]:
|
||||
) -> t.Callable[[ft.TemplateTestCallable], ft.TemplateTestCallable]:
|
||||
"""A decorator that is used to register custom template test.
|
||||
You can specify a name for the test, otherwise the function
|
||||
name will be used. Example::
|
||||
|
|
@ -1193,7 +1187,7 @@ class Flask(Scaffold):
|
|||
function name will be used.
|
||||
"""
|
||||
|
||||
def decorator(f: TemplateTestCallable) -> TemplateTestCallable:
|
||||
def decorator(f: ft.TemplateTestCallable) -> ft.TemplateTestCallable:
|
||||
self.add_template_test(f, name=name)
|
||||
return f
|
||||
|
||||
|
|
@ -1201,7 +1195,7 @@ class Flask(Scaffold):
|
|||
|
||||
@setupmethod
|
||||
def add_template_test(
|
||||
self, f: TemplateTestCallable, name: t.Optional[str] = None
|
||||
self, f: ft.TemplateTestCallable, name: t.Optional[str] = None
|
||||
) -> None:
|
||||
"""Register a custom template test. Works exactly like the
|
||||
:meth:`template_test` decorator.
|
||||
|
|
@ -1216,7 +1210,7 @@ class Flask(Scaffold):
|
|||
@setupmethod
|
||||
def template_global(
|
||||
self, name: t.Optional[str] = None
|
||||
) -> t.Callable[[TemplateGlobalCallable], TemplateGlobalCallable]:
|
||||
) -> t.Callable[[ft.TemplateGlobalCallable], ft.TemplateGlobalCallable]:
|
||||
"""A decorator that is used to register a custom template global function.
|
||||
You can specify a name for the global function, otherwise the function
|
||||
name will be used. Example::
|
||||
|
|
@ -1231,7 +1225,7 @@ class Flask(Scaffold):
|
|||
function name will be used.
|
||||
"""
|
||||
|
||||
def decorator(f: TemplateGlobalCallable) -> TemplateGlobalCallable:
|
||||
def decorator(f: ft.TemplateGlobalCallable) -> ft.TemplateGlobalCallable:
|
||||
self.add_template_global(f, name=name)
|
||||
return f
|
||||
|
||||
|
|
@ -1239,7 +1233,7 @@ class Flask(Scaffold):
|
|||
|
||||
@setupmethod
|
||||
def add_template_global(
|
||||
self, f: TemplateGlobalCallable, name: t.Optional[str] = None
|
||||
self, f: ft.TemplateGlobalCallable, name: t.Optional[str] = None
|
||||
) -> None:
|
||||
"""Register a custom template global function. Works exactly like the
|
||||
:meth:`template_global` decorator.
|
||||
|
|
@ -1253,8 +1247,8 @@ class Flask(Scaffold):
|
|||
|
||||
@setupmethod
|
||||
def before_first_request(
|
||||
self, f: BeforeFirstRequestCallable
|
||||
) -> BeforeFirstRequestCallable:
|
||||
self, f: ft.BeforeFirstRequestCallable
|
||||
) -> ft.BeforeFirstRequestCallable:
|
||||
"""Registers a function to be run before the first request to this
|
||||
instance of the application.
|
||||
|
||||
|
|
@ -1267,7 +1261,7 @@ class Flask(Scaffold):
|
|||
return f
|
||||
|
||||
@setupmethod
|
||||
def teardown_appcontext(self, f: TeardownCallable) -> TeardownCallable:
|
||||
def teardown_appcontext(self, f: ft.TeardownCallable) -> ft.TeardownCallable:
|
||||
"""Registers a function to be called when the application context
|
||||
ends. These functions are typically also called when the request
|
||||
context is popped.
|
||||
|
|
@ -1308,7 +1302,7 @@ class Flask(Scaffold):
|
|||
self.shell_context_processors.append(f)
|
||||
return f
|
||||
|
||||
def _find_error_handler(self, e: Exception) -> t.Optional["ErrorHandlerCallable"]:
|
||||
def _find_error_handler(self, e: Exception) -> t.Optional[ft.ErrorHandlerCallable]:
|
||||
"""Return a registered error handler for an exception in this order:
|
||||
blueprint handler for a specific code, app handler for a specific code,
|
||||
blueprint handler for an exception class, app handler for an exception
|
||||
|
|
@ -1333,7 +1327,7 @@ class Flask(Scaffold):
|
|||
|
||||
def handle_http_exception(
|
||||
self, e: HTTPException
|
||||
) -> t.Union[HTTPException, ResponseReturnValue]:
|
||||
) -> t.Union[HTTPException, ft.ResponseReturnValue]:
|
||||
"""Handles an HTTP exception. By default this will invoke the
|
||||
registered error handlers and fall back to returning the
|
||||
exception as response.
|
||||
|
|
@ -1403,7 +1397,7 @@ class Flask(Scaffold):
|
|||
|
||||
def handle_user_exception(
|
||||
self, e: Exception
|
||||
) -> t.Union[HTTPException, ResponseReturnValue]:
|
||||
) -> t.Union[HTTPException, ft.ResponseReturnValue]:
|
||||
"""This method is called whenever an exception occurs that
|
||||
should be handled. A special case is :class:`~werkzeug
|
||||
.exceptions.HTTPException` which is forwarded to the
|
||||
|
|
@ -1473,7 +1467,7 @@ class Flask(Scaffold):
|
|||
raise e
|
||||
|
||||
self.log_exception(exc_info)
|
||||
server_error: t.Union[InternalServerError, ResponseReturnValue]
|
||||
server_error: t.Union[InternalServerError, ft.ResponseReturnValue]
|
||||
server_error = InternalServerError(original_exception=e)
|
||||
handler = self._find_error_handler(server_error)
|
||||
|
||||
|
|
@ -1527,7 +1521,7 @@ class Flask(Scaffold):
|
|||
|
||||
raise FormDataRoutingRedirect(request)
|
||||
|
||||
def dispatch_request(self) -> ResponseReturnValue:
|
||||
def dispatch_request(self) -> ft.ResponseReturnValue:
|
||||
"""Does the request dispatching. Matches the URL and returns the
|
||||
return value of the view or error handler. This does not have to
|
||||
be a response object. In order to convert the return value to a
|
||||
|
|
@ -1570,7 +1564,7 @@ class Flask(Scaffold):
|
|||
|
||||
def finalize_request(
|
||||
self,
|
||||
rv: t.Union[ResponseReturnValue, HTTPException],
|
||||
rv: t.Union[ft.ResponseReturnValue, HTTPException],
|
||||
from_error_handler: bool = False,
|
||||
) -> Response:
|
||||
"""Given the return value from a view function this finalizes
|
||||
|
|
@ -1811,7 +1805,7 @@ class Flask(Scaffold):
|
|||
"""
|
||||
return _wz_redirect(location, code=code, Response=self.response_class)
|
||||
|
||||
def make_response(self, rv: ResponseReturnValue) -> Response:
|
||||
def make_response(self, rv: ft.ResponseReturnValue) -> Response:
|
||||
"""Convert the return value from a view function to an instance of
|
||||
:attr:`response_class`.
|
||||
|
||||
|
|
@ -1903,7 +1897,9 @@ class Flask(Scaffold):
|
|||
# evaluate a WSGI callable, or coerce a different response
|
||||
# class to the correct type
|
||||
try:
|
||||
rv = self.response_class.force_type(rv, request.environ) # type: ignore # noqa: B950
|
||||
rv = self.response_class.force_type(
|
||||
rv, request.environ # type: ignore[arg-type]
|
||||
)
|
||||
except TypeError as e:
|
||||
raise TypeError(
|
||||
f"{e}\nThe view function did not return a valid"
|
||||
|
|
@ -2030,7 +2026,7 @@ class Flask(Scaffold):
|
|||
|
||||
raise error
|
||||
|
||||
def preprocess_request(self) -> t.Optional[ResponseReturnValue]:
|
||||
def preprocess_request(self) -> t.Optional[ft.ResponseReturnValue]:
|
||||
"""Called before the request is dispatched. Calls
|
||||
:attr:`url_value_preprocessors` registered with the app and the
|
||||
current blueprint (if any). Then calls :attr:`before_request_funcs`
|
||||
|
|
|
|||
|
|
@ -3,24 +3,14 @@ import typing as t
|
|||
from collections import defaultdict
|
||||
from functools import update_wrapper
|
||||
|
||||
from . import typing as ft
|
||||
from .scaffold import _endpoint_from_view_func
|
||||
from .scaffold import _sentinel
|
||||
from .scaffold import Scaffold
|
||||
from .scaffold import setupmethod
|
||||
from .typing import AfterRequestCallable
|
||||
from .typing import BeforeFirstRequestCallable
|
||||
from .typing import BeforeRequestCallable
|
||||
from .typing import TeardownCallable
|
||||
from .typing import TemplateContextProcessorCallable
|
||||
from .typing import TemplateFilterCallable
|
||||
from .typing import TemplateGlobalCallable
|
||||
from .typing import TemplateTestCallable
|
||||
from .typing import URLDefaultCallable
|
||||
from .typing import URLValuePreprocessorCallable
|
||||
|
||||
if t.TYPE_CHECKING: # pragma: no cover
|
||||
from .app import Flask
|
||||
from .typing import ErrorHandlerCallable
|
||||
|
||||
DeferredSetupFunction = t.Callable[["BlueprintSetupState"], t.Callable]
|
||||
|
||||
|
|
@ -428,7 +418,7 @@ class Blueprint(Scaffold):
|
|||
@setupmethod
|
||||
def app_template_filter(
|
||||
self, name: t.Optional[str] = None
|
||||
) -> t.Callable[[TemplateFilterCallable], TemplateFilterCallable]:
|
||||
) -> t.Callable[[ft.TemplateFilterCallable], ft.TemplateFilterCallable]:
|
||||
"""Register a custom template filter, available application wide. Like
|
||||
:meth:`Flask.template_filter` but for a blueprint.
|
||||
|
||||
|
|
@ -436,7 +426,7 @@ class Blueprint(Scaffold):
|
|||
function name will be used.
|
||||
"""
|
||||
|
||||
def decorator(f: TemplateFilterCallable) -> TemplateFilterCallable:
|
||||
def decorator(f: ft.TemplateFilterCallable) -> ft.TemplateFilterCallable:
|
||||
self.add_app_template_filter(f, name=name)
|
||||
return f
|
||||
|
||||
|
|
@ -444,7 +434,7 @@ class Blueprint(Scaffold):
|
|||
|
||||
@setupmethod
|
||||
def add_app_template_filter(
|
||||
self, f: TemplateFilterCallable, name: t.Optional[str] = None
|
||||
self, f: ft.TemplateFilterCallable, name: t.Optional[str] = None
|
||||
) -> None:
|
||||
"""Register a custom template filter, available application wide. Like
|
||||
:meth:`Flask.add_template_filter` but for a blueprint. Works exactly
|
||||
|
|
@ -462,7 +452,7 @@ class Blueprint(Scaffold):
|
|||
@setupmethod
|
||||
def app_template_test(
|
||||
self, name: t.Optional[str] = None
|
||||
) -> t.Callable[[TemplateTestCallable], TemplateTestCallable]:
|
||||
) -> t.Callable[[ft.TemplateTestCallable], ft.TemplateTestCallable]:
|
||||
"""Register a custom template test, available application wide. Like
|
||||
:meth:`Flask.template_test` but for a blueprint.
|
||||
|
||||
|
|
@ -472,7 +462,7 @@ class Blueprint(Scaffold):
|
|||
function name will be used.
|
||||
"""
|
||||
|
||||
def decorator(f: TemplateTestCallable) -> TemplateTestCallable:
|
||||
def decorator(f: ft.TemplateTestCallable) -> ft.TemplateTestCallable:
|
||||
self.add_app_template_test(f, name=name)
|
||||
return f
|
||||
|
||||
|
|
@ -480,7 +470,7 @@ class Blueprint(Scaffold):
|
|||
|
||||
@setupmethod
|
||||
def add_app_template_test(
|
||||
self, f: TemplateTestCallable, name: t.Optional[str] = None
|
||||
self, f: ft.TemplateTestCallable, name: t.Optional[str] = None
|
||||
) -> None:
|
||||
"""Register a custom template test, available application wide. Like
|
||||
:meth:`Flask.add_template_test` but for a blueprint. Works exactly
|
||||
|
|
@ -500,7 +490,7 @@ class Blueprint(Scaffold):
|
|||
@setupmethod
|
||||
def app_template_global(
|
||||
self, name: t.Optional[str] = None
|
||||
) -> t.Callable[[TemplateGlobalCallable], TemplateGlobalCallable]:
|
||||
) -> t.Callable[[ft.TemplateGlobalCallable], ft.TemplateGlobalCallable]:
|
||||
"""Register a custom template global, available application wide. Like
|
||||
:meth:`Flask.template_global` but for a blueprint.
|
||||
|
||||
|
|
@ -510,7 +500,7 @@ class Blueprint(Scaffold):
|
|||
function name will be used.
|
||||
"""
|
||||
|
||||
def decorator(f: TemplateGlobalCallable) -> TemplateGlobalCallable:
|
||||
def decorator(f: ft.TemplateGlobalCallable) -> ft.TemplateGlobalCallable:
|
||||
self.add_app_template_global(f, name=name)
|
||||
return f
|
||||
|
||||
|
|
@ -518,7 +508,7 @@ class Blueprint(Scaffold):
|
|||
|
||||
@setupmethod
|
||||
def add_app_template_global(
|
||||
self, f: TemplateGlobalCallable, name: t.Optional[str] = None
|
||||
self, f: ft.TemplateGlobalCallable, name: t.Optional[str] = None
|
||||
) -> None:
|
||||
"""Register a custom template global, available application wide. Like
|
||||
:meth:`Flask.add_template_global` but for a blueprint. Works exactly
|
||||
|
|
@ -536,7 +526,9 @@ class Blueprint(Scaffold):
|
|||
self.record_once(register_template)
|
||||
|
||||
@setupmethod
|
||||
def before_app_request(self, f: BeforeRequestCallable) -> BeforeRequestCallable:
|
||||
def before_app_request(
|
||||
self, f: ft.BeforeRequestCallable
|
||||
) -> ft.BeforeRequestCallable:
|
||||
"""Like :meth:`Flask.before_request`. Such a function is executed
|
||||
before each request, even if outside of a blueprint.
|
||||
"""
|
||||
|
|
@ -547,15 +539,15 @@ class Blueprint(Scaffold):
|
|||
|
||||
@setupmethod
|
||||
def before_app_first_request(
|
||||
self, f: BeforeFirstRequestCallable
|
||||
) -> BeforeFirstRequestCallable:
|
||||
self, f: ft.BeforeFirstRequestCallable
|
||||
) -> ft.BeforeFirstRequestCallable:
|
||||
"""Like :meth:`Flask.before_first_request`. Such a function is
|
||||
executed before the first request to the application.
|
||||
"""
|
||||
self.record_once(lambda s: s.app.before_first_request_funcs.append(f))
|
||||
return f
|
||||
|
||||
def after_app_request(self, f: AfterRequestCallable) -> AfterRequestCallable:
|
||||
def after_app_request(self, f: ft.AfterRequestCallable) -> ft.AfterRequestCallable:
|
||||
"""Like :meth:`Flask.after_request` but for a blueprint. Such a function
|
||||
is executed after each request, even if outside of the blueprint.
|
||||
"""
|
||||
|
|
@ -565,7 +557,7 @@ class Blueprint(Scaffold):
|
|||
return f
|
||||
|
||||
@setupmethod
|
||||
def teardown_app_request(self, f: TeardownCallable) -> TeardownCallable:
|
||||
def teardown_app_request(self, f: ft.TeardownCallable) -> ft.TeardownCallable:
|
||||
"""Like :meth:`Flask.teardown_request` but for a blueprint. Such a
|
||||
function is executed when tearing down each request, even if outside of
|
||||
the blueprint.
|
||||
|
|
@ -577,8 +569,8 @@ class Blueprint(Scaffold):
|
|||
|
||||
@setupmethod
|
||||
def app_context_processor(
|
||||
self, f: TemplateContextProcessorCallable
|
||||
) -> TemplateContextProcessorCallable:
|
||||
self, f: ft.TemplateContextProcessorCallable
|
||||
) -> ft.TemplateContextProcessorCallable:
|
||||
"""Like :meth:`Flask.context_processor` but for a blueprint. Such a
|
||||
function is executed each request, even if outside of the blueprint.
|
||||
"""
|
||||
|
|
@ -593,7 +585,7 @@ class Blueprint(Scaffold):
|
|||
handler is used for all requests, even if outside of the blueprint.
|
||||
"""
|
||||
|
||||
def decorator(f: "ErrorHandlerCallable") -> "ErrorHandlerCallable":
|
||||
def decorator(f: ft.ErrorHandlerCallable) -> ft.ErrorHandlerCallable:
|
||||
self.record_once(lambda s: s.app.errorhandler(code)(f))
|
||||
return f
|
||||
|
||||
|
|
@ -601,8 +593,8 @@ class Blueprint(Scaffold):
|
|||
|
||||
@setupmethod
|
||||
def app_url_value_preprocessor(
|
||||
self, f: URLValuePreprocessorCallable
|
||||
) -> URLValuePreprocessorCallable:
|
||||
self, f: ft.URLValuePreprocessorCallable
|
||||
) -> ft.URLValuePreprocessorCallable:
|
||||
"""Same as :meth:`url_value_preprocessor` but application wide."""
|
||||
self.record_once(
|
||||
lambda s: s.app.url_value_preprocessors.setdefault(None, []).append(f)
|
||||
|
|
@ -610,7 +602,7 @@ class Blueprint(Scaffold):
|
|||
return f
|
||||
|
||||
@setupmethod
|
||||
def app_url_defaults(self, f: URLDefaultCallable) -> URLDefaultCallable:
|
||||
def app_url_defaults(self, f: ft.URLDefaultCallable) -> ft.URLDefaultCallable:
|
||||
"""Same as :meth:`url_defaults` but application wide."""
|
||||
self.record_once(
|
||||
lambda s: s.app.url_default_functions.setdefault(None, []).append(f)
|
||||
|
|
|
|||
|
|
@ -5,11 +5,11 @@ from types import TracebackType
|
|||
|
||||
from werkzeug.exceptions import HTTPException
|
||||
|
||||
from . import typing as ft
|
||||
from .globals import _app_ctx_stack
|
||||
from .globals import _request_ctx_stack
|
||||
from .signals import appcontext_popped
|
||||
from .signals import appcontext_pushed
|
||||
from .typing import AfterRequestCallable
|
||||
|
||||
if t.TYPE_CHECKING: # pragma: no cover
|
||||
from .app import Flask
|
||||
|
|
@ -109,7 +109,7 @@ class _AppCtxGlobals:
|
|||
return object.__repr__(self)
|
||||
|
||||
|
||||
def after_this_request(f: AfterRequestCallable) -> AfterRequestCallable:
|
||||
def after_this_request(f: ft.AfterRequestCallable) -> ft.AfterRequestCallable:
|
||||
"""Executes a function after this request. This is useful to modify
|
||||
response objects. The function is passed the response object and has
|
||||
to return the same or a new one.
|
||||
|
|
@ -341,7 +341,7 @@ class RequestContext:
|
|||
# Functions that should be executed after the request on the response
|
||||
# object. These will be called before the regular "after_request"
|
||||
# functions.
|
||||
self._after_request_functions: t.List[AfterRequestCallable] = []
|
||||
self._after_request_functions: t.List[ft.AfterRequestCallable] = []
|
||||
|
||||
@property
|
||||
def g(self) -> _AppCtxGlobals:
|
||||
|
|
|
|||
|
|
@ -12,22 +12,15 @@ from jinja2 import FileSystemLoader
|
|||
from werkzeug.exceptions import default_exceptions
|
||||
from werkzeug.exceptions import HTTPException
|
||||
|
||||
from . import typing as ft
|
||||
from .cli import AppGroup
|
||||
from .globals import current_app
|
||||
from .helpers import get_root_path
|
||||
from .helpers import locked_cached_property
|
||||
from .helpers import send_from_directory
|
||||
from .templating import _default_template_ctx_processor
|
||||
from .typing import AfterRequestCallable
|
||||
from .typing import AppOrBlueprintKey
|
||||
from .typing import BeforeRequestCallable
|
||||
from .typing import TeardownCallable
|
||||
from .typing import TemplateContextProcessorCallable
|
||||
from .typing import URLDefaultCallable
|
||||
from .typing import URLValuePreprocessorCallable
|
||||
|
||||
if t.TYPE_CHECKING: # pragma: no cover
|
||||
from .typing import ErrorHandlerCallable
|
||||
from .wrappers import Response
|
||||
|
||||
# a singleton sentinel value for parameter defaults
|
||||
|
|
@ -131,8 +124,8 @@ class Scaffold:
|
|||
#: This data structure is internal. It should not be modified
|
||||
#: directly and its format may change at any time.
|
||||
self.error_handler_spec: t.Dict[
|
||||
AppOrBlueprintKey,
|
||||
t.Dict[t.Optional[int], t.Dict[t.Type[Exception], "ErrorHandlerCallable"]],
|
||||
ft.AppOrBlueprintKey,
|
||||
t.Dict[t.Optional[int], t.Dict[t.Type[Exception], ft.ErrorHandlerCallable]],
|
||||
] = defaultdict(lambda: defaultdict(dict))
|
||||
|
||||
#: A data structure of functions to call at the beginning of
|
||||
|
|
@ -146,7 +139,7 @@ class Scaffold:
|
|||
#: This data structure is internal. It should not be modified
|
||||
#: directly and its format may change at any time.
|
||||
self.before_request_funcs: t.Dict[
|
||||
AppOrBlueprintKey, t.List[BeforeRequestCallable]
|
||||
ft.AppOrBlueprintKey, t.List[ft.BeforeRequestCallable]
|
||||
] = defaultdict(list)
|
||||
|
||||
#: A data structure of functions to call at the end of each
|
||||
|
|
@ -160,7 +153,7 @@ class Scaffold:
|
|||
#: This data structure is internal. It should not be modified
|
||||
#: directly and its format may change at any time.
|
||||
self.after_request_funcs: t.Dict[
|
||||
AppOrBlueprintKey, t.List[AfterRequestCallable]
|
||||
ft.AppOrBlueprintKey, t.List[ft.AfterRequestCallable]
|
||||
] = defaultdict(list)
|
||||
|
||||
#: A data structure of functions to call at the end of each
|
||||
|
|
@ -175,7 +168,7 @@ class Scaffold:
|
|||
#: This data structure is internal. It should not be modified
|
||||
#: directly and its format may change at any time.
|
||||
self.teardown_request_funcs: t.Dict[
|
||||
AppOrBlueprintKey, t.List[TeardownCallable]
|
||||
ft.AppOrBlueprintKey, t.List[ft.TeardownCallable]
|
||||
] = defaultdict(list)
|
||||
|
||||
#: A data structure of functions to call to pass extra context
|
||||
|
|
@ -190,7 +183,7 @@ class Scaffold:
|
|||
#: This data structure is internal. It should not be modified
|
||||
#: directly and its format may change at any time.
|
||||
self.template_context_processors: t.Dict[
|
||||
AppOrBlueprintKey, t.List[TemplateContextProcessorCallable]
|
||||
ft.AppOrBlueprintKey, t.List[ft.TemplateContextProcessorCallable]
|
||||
] = defaultdict(list, {None: [_default_template_ctx_processor]})
|
||||
|
||||
#: A data structure of functions to call to modify the keyword
|
||||
|
|
@ -205,8 +198,8 @@ class Scaffold:
|
|||
#: This data structure is internal. It should not be modified
|
||||
#: directly and its format may change at any time.
|
||||
self.url_value_preprocessors: t.Dict[
|
||||
AppOrBlueprintKey,
|
||||
t.List[URLValuePreprocessorCallable],
|
||||
ft.AppOrBlueprintKey,
|
||||
t.List[ft.URLValuePreprocessorCallable],
|
||||
] = defaultdict(list)
|
||||
|
||||
#: A data structure of functions to call to modify the keyword
|
||||
|
|
@ -221,7 +214,7 @@ class Scaffold:
|
|||
#: This data structure is internal. It should not be modified
|
||||
#: directly and its format may change at any time.
|
||||
self.url_default_functions: t.Dict[
|
||||
AppOrBlueprintKey, t.List[URLDefaultCallable]
|
||||
ft.AppOrBlueprintKey, t.List[ft.URLDefaultCallable]
|
||||
] = defaultdict(list)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
|
|
@ -529,7 +522,7 @@ class Scaffold:
|
|||
return decorator
|
||||
|
||||
@setupmethod
|
||||
def before_request(self, f: BeforeRequestCallable) -> BeforeRequestCallable:
|
||||
def before_request(self, f: ft.BeforeRequestCallable) -> ft.BeforeRequestCallable:
|
||||
"""Register a function to run before each request.
|
||||
|
||||
For example, this can be used to open a database connection, or
|
||||
|
|
@ -551,7 +544,7 @@ class Scaffold:
|
|||
return f
|
||||
|
||||
@setupmethod
|
||||
def after_request(self, f: AfterRequestCallable) -> AfterRequestCallable:
|
||||
def after_request(self, f: ft.AfterRequestCallable) -> ft.AfterRequestCallable:
|
||||
"""Register a function to run after each request to this object.
|
||||
|
||||
The function is called with the response object, and must return
|
||||
|
|
@ -567,7 +560,7 @@ class Scaffold:
|
|||
return f
|
||||
|
||||
@setupmethod
|
||||
def teardown_request(self, f: TeardownCallable) -> TeardownCallable:
|
||||
def teardown_request(self, f: ft.TeardownCallable) -> ft.TeardownCallable:
|
||||
"""Register a function to be run at the end of each request,
|
||||
regardless of whether there was an exception or not. These functions
|
||||
are executed when the request context is popped, even if not an
|
||||
|
|
@ -607,16 +600,16 @@ class Scaffold:
|
|||
|
||||
@setupmethod
|
||||
def context_processor(
|
||||
self, f: TemplateContextProcessorCallable
|
||||
) -> TemplateContextProcessorCallable:
|
||||
self, f: ft.TemplateContextProcessorCallable
|
||||
) -> ft.TemplateContextProcessorCallable:
|
||||
"""Registers a template context processor function."""
|
||||
self.template_context_processors[None].append(f)
|
||||
return f
|
||||
|
||||
@setupmethod
|
||||
def url_value_preprocessor(
|
||||
self, f: URLValuePreprocessorCallable
|
||||
) -> URLValuePreprocessorCallable:
|
||||
self, f: ft.URLValuePreprocessorCallable
|
||||
) -> ft.URLValuePreprocessorCallable:
|
||||
"""Register a URL value preprocessor function for all view
|
||||
functions in the application. These functions will be called before the
|
||||
:meth:`before_request` functions.
|
||||
|
|
@ -633,7 +626,7 @@ class Scaffold:
|
|||
return f
|
||||
|
||||
@setupmethod
|
||||
def url_defaults(self, f: URLDefaultCallable) -> URLDefaultCallable:
|
||||
def url_defaults(self, f: ft.URLDefaultCallable) -> ft.URLDefaultCallable:
|
||||
"""Callback function for URL defaults for all view functions of the
|
||||
application. It's called with the endpoint and values and should
|
||||
update the values passed in place.
|
||||
|
|
@ -644,7 +637,7 @@ class Scaffold:
|
|||
@setupmethod
|
||||
def errorhandler(
|
||||
self, code_or_exception: t.Union[t.Type[Exception], int]
|
||||
) -> t.Callable[["ErrorHandlerCallable"], "ErrorHandlerCallable"]:
|
||||
) -> t.Callable[[ft.ErrorHandlerCallable], ft.ErrorHandlerCallable]:
|
||||
"""Register a function to handle errors by code or exception class.
|
||||
|
||||
A decorator that is used to register a function given an
|
||||
|
|
@ -674,7 +667,7 @@ class Scaffold:
|
|||
an arbitrary exception
|
||||
"""
|
||||
|
||||
def decorator(f: "ErrorHandlerCallable") -> "ErrorHandlerCallable":
|
||||
def decorator(f: ft.ErrorHandlerCallable) -> ft.ErrorHandlerCallable:
|
||||
self.register_error_handler(code_or_exception, f)
|
||||
return f
|
||||
|
||||
|
|
@ -684,7 +677,7 @@ class Scaffold:
|
|||
def register_error_handler(
|
||||
self,
|
||||
code_or_exception: t.Union[t.Type[Exception], int],
|
||||
f: "ErrorHandlerCallable",
|
||||
f: ft.ErrorHandlerCallable,
|
||||
) -> None:
|
||||
"""Alternative error attach function to the :meth:`errorhandler`
|
||||
decorator that is more straightforward to use for non decorator
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import typing as t
|
|||
if t.TYPE_CHECKING: # pragma: no cover
|
||||
from _typeshed.wsgi import WSGIApplication # noqa: F401
|
||||
from werkzeug.datastructures import Headers # noqa: F401
|
||||
from werkzeug.wrappers.response import Response # noqa: F401
|
||||
from werkzeug.wrappers import Response # noqa: F401
|
||||
|
||||
# The possible types that are directly convertible or are a Response object.
|
||||
ResponseValue = t.Union[
|
||||
|
|
@ -35,8 +35,13 @@ ResponseReturnValue = t.Union[
|
|||
"WSGIApplication",
|
||||
]
|
||||
|
||||
# Allow any subclass of werkzeug.Response, such as the one from Flask,
|
||||
# as a callback argument. Using werkzeug.Response directly makes a
|
||||
# callback annotated with flask.Response fail type checking.
|
||||
ResponseClass = t.TypeVar("ResponseClass", bound="Response")
|
||||
|
||||
AppOrBlueprintKey = t.Optional[str] # The App key is None, whereas blueprints are named
|
||||
AfterRequestCallable = t.Callable[["Response"], "Response"]
|
||||
AfterRequestCallable = t.Callable[[ResponseClass], ResponseClass]
|
||||
BeforeFirstRequestCallable = t.Callable[[], None]
|
||||
BeforeRequestCallable = t.Callable[[], t.Optional[ResponseReturnValue]]
|
||||
TeardownCallable = t.Callable[[t.Optional[BaseException]], None]
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import typing as t
|
||||
|
||||
from . import typing as ft
|
||||
from .globals import current_app
|
||||
from .globals import request
|
||||
from .typing import ResponseReturnValue
|
||||
|
||||
|
||||
http_method_funcs = frozenset(
|
||||
|
|
@ -59,7 +59,7 @@ class View:
|
|||
#: .. versionadded:: 0.8
|
||||
decorators: t.List[t.Callable] = []
|
||||
|
||||
def dispatch_request(self) -> ResponseReturnValue:
|
||||
def dispatch_request(self) -> ft.ResponseReturnValue:
|
||||
"""Subclasses have to override this method to implement the
|
||||
actual view function code. This method is called with all
|
||||
the arguments from the URL rule.
|
||||
|
|
@ -79,7 +79,7 @@ class View:
|
|||
constructor of the class.
|
||||
"""
|
||||
|
||||
def view(*args: t.Any, **kwargs: t.Any) -> ResponseReturnValue:
|
||||
def view(*args: t.Any, **kwargs: t.Any) -> ft.ResponseReturnValue:
|
||||
self = view.view_class(*class_args, **class_kwargs) # type: ignore
|
||||
return current_app.ensure_sync(self.dispatch_request)(*args, **kwargs)
|
||||
|
||||
|
|
@ -146,7 +146,7 @@ class MethodView(View, metaclass=MethodViewType):
|
|||
app.add_url_rule('/counter', view_func=CounterAPI.as_view('counter'))
|
||||
"""
|
||||
|
||||
def dispatch_request(self, *args: t.Any, **kwargs: t.Any) -> ResponseReturnValue:
|
||||
def dispatch_request(self, *args: t.Any, **kwargs: t.Any) -> ft.ResponseReturnValue:
|
||||
meth = getattr(self, request.method.lower(), None)
|
||||
|
||||
# If the request method is HEAD and we don't have a handler for it
|
||||
|
|
|
|||
Loading…
Reference in New Issue