|
@@ -16,7 +16,6 @@ from werkzeug.exceptions import BadRequest
|
|
|
from werkzeug.exceptions import BadRequestKeyError
|
|
|
from werkzeug.exceptions import HTTPException
|
|
|
from werkzeug.exceptions import InternalServerError
|
|
|
-from werkzeug.local import ContextVar
|
|
|
from werkzeug.routing import BuildError
|
|
|
from werkzeug.routing import Map
|
|
|
from werkzeug.routing import MapAdapter
|
|
@@ -27,6 +26,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
|
|
@@ -51,6 +51,7 @@ from .scaffold import find_package
|
|
|
from .scaffold import Scaffold
|
|
|
from .scaffold import setupmethod
|
|
|
from .sessions import SecureCookieSessionInterface
|
|
|
+from .sessions import SessionInterface
|
|
|
from .signals import appcontext_tearing_down
|
|
|
from .signals import got_request_exception
|
|
|
from .signals import request_finished
|
|
@@ -58,12 +59,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
|
|
|
|
|
@@ -72,7 +67,6 @@ if t.TYPE_CHECKING:
|
|
|
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
|
|
@@ -379,7 +373,7 @@ class Flask(Scaffold):
|
|
|
#: :class:`~flask.sessions.SecureCookieSessionInterface` is used here.
|
|
|
#:
|
|
|
#: .. versionadded:: 0.8
|
|
|
- session_interface = SecureCookieSessionInterface()
|
|
|
+ session_interface: SessionInterface = SecureCookieSessionInterface()
|
|
|
|
|
|
def __init__(
|
|
|
self,
|
|
@@ -436,7 +430,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
|
|
@@ -444,7 +438,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.
|
|
@@ -1039,7 +1033,7 @@ class Flask(Scaffold):
|
|
|
self,
|
|
|
rule: str,
|
|
|
endpoint: t.Optional[str] = None,
|
|
|
- view_func: t.Optional[t.Callable] = None,
|
|
|
+ view_func: t.Optional[ft.ViewCallable] = None,
|
|
|
provide_automatic_options: t.Optional[bool] = None,
|
|
|
**options: t.Any,
|
|
|
) -> None:
|
|
@@ -1096,7 +1090,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::
|
|
@@ -1109,7 +1103,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
|
|
|
|
|
@@ -1117,7 +1111,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.
|
|
@@ -1130,7 +1124,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::
|
|
@@ -1150,7 +1144,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
|
|
|
|
|
@@ -1158,7 +1152,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.
|
|
@@ -1173,7 +1167,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::
|
|
@@ -1188,7 +1182,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
|
|
|
|
|
@@ -1196,7 +1190,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.
|
|
@@ -1210,8 +1204,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.
|
|
|
|
|
@@ -1224,7 +1218,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.
|
|
@@ -1265,9 +1259,7 @@ class Flask(Scaffold):
|
|
|
self.shell_context_processors.append(f)
|
|
|
return f
|
|
|
|
|
|
- def _find_error_handler(
|
|
|
- self, e: Exception
|
|
|
- ) -> t.Optional["ErrorHandlerCallable[Exception]"]:
|
|
|
+ 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
|
|
@@ -1292,7 +1284,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.
|
|
@@ -1362,7 +1354,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
|
|
@@ -1432,7 +1424,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)
|
|
|
|
|
@@ -1459,17 +1451,26 @@ class Flask(Scaffold):
|
|
|
)
|
|
|
|
|
|
def raise_routing_exception(self, request: Request) -> "te.NoReturn":
|
|
|
- """Exceptions that are recording during routing are reraised with
|
|
|
- this method. During debug we are not reraising redirect requests
|
|
|
- for non ``GET``, ``HEAD``, or ``OPTIONS`` requests and we're raising
|
|
|
- a different error instead to help debug situations.
|
|
|
+ """Intercept routing exceptions and possibly do something else.
|
|
|
+
|
|
|
+ In debug mode, intercept a routing redirect and replace it with
|
|
|
+ an error if the body will be discarded.
|
|
|
+
|
|
|
+ With modern Werkzeug this shouldn't occur, since it now uses a
|
|
|
+ 308 status which tells the browser to resend the method and
|
|
|
+ body.
|
|
|
+
|
|
|
+ .. versionchanged:: 2.1
|
|
|
+ Don't intercept 307 and 308 redirects.
|
|
|
|
|
|
+ :meta private:
|
|
|
:internal:
|
|
|
"""
|
|
|
if (
|
|
|
not self.debug
|
|
|
or not isinstance(request.routing_exception, RequestRedirect)
|
|
|
- or request.method in ("GET", "HEAD", "OPTIONS")
|
|
|
+ or request.routing_exception.code in {307, 308}
|
|
|
+ or request.method in {"GET", "HEAD", "OPTIONS"}
|
|
|
):
|
|
|
raise request.routing_exception # type: ignore
|
|
|
|
|
@@ -1477,7 +1478,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
|
|
@@ -1520,7 +1521,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
|
|
@@ -1621,16 +1622,9 @@ class Flask(Scaffold):
|
|
|
"Install Flask with the 'async' extra in order to use async views."
|
|
|
) from None
|
|
|
|
|
|
- # Check that Werkzeug isn't using its fallback ContextVar class.
|
|
|
- if ContextVar.__module__ == "werkzeug.local":
|
|
|
- raise RuntimeError(
|
|
|
- "Async cannot be used with this combination of Python "
|
|
|
- "and Greenlet versions."
|
|
|
- )
|
|
|
-
|
|
|
return asgiref_async_to_sync(func)
|
|
|
|
|
|
- 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`.
|
|
|
|
|
@@ -1681,13 +1675,13 @@ class Flask(Scaffold):
|
|
|
|
|
|
# a 3-tuple is unpacked directly
|
|
|
if len_rv == 3:
|
|
|
- rv, status, headers = rv
|
|
|
+ rv, status, headers = rv # type: ignore[misc]
|
|
|
# decide if a 2-tuple has status or headers
|
|
|
elif len_rv == 2:
|
|
|
if isinstance(rv[1], (Headers, dict, tuple, list)):
|
|
|
rv, headers = rv
|
|
|
else:
|
|
|
- rv, status = rv
|
|
|
+ rv, status = rv # type: ignore[assignment,misc]
|
|
|
# other sized tuples are not allowed
|
|
|
else:
|
|
|
raise TypeError(
|
|
@@ -1710,7 +1704,11 @@ class Flask(Scaffold):
|
|
|
# let the response class set the status and headers instead of
|
|
|
# waiting to do it manually, so that the class can handle any
|
|
|
# special logic
|
|
|
- rv = self.response_class(rv, status=status, headers=headers)
|
|
|
+ rv = self.response_class(
|
|
|
+ rv,
|
|
|
+ status=status,
|
|
|
+ headers=headers, # type: ignore[arg-type]
|
|
|
+ )
|
|
|
status = headers = None
|
|
|
elif isinstance(rv, dict):
|
|
|
rv = jsonify(rv)
|
|
@@ -1718,7 +1716,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"
|
|
@@ -1738,13 +1738,13 @@ class Flask(Scaffold):
|
|
|
# prefer the status if it was provided
|
|
|
if status is not None:
|
|
|
if isinstance(status, (str, bytes, bytearray)):
|
|
|
- rv.status = status # type: ignore
|
|
|
+ rv.status = status
|
|
|
else:
|
|
|
rv.status_code = status
|
|
|
|
|
|
# extend existing headers with provided headers
|
|
|
if headers:
|
|
|
- rv.headers.update(headers)
|
|
|
+ rv.headers.update(headers) # type: ignore[arg-type]
|
|
|
|
|
|
return rv
|
|
|
|
|
@@ -1834,7 +1834,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`
|