aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python/Flask/py3/flask/blueprints.py
diff options
context:
space:
mode:
authorrobot-piglet <robot-piglet@yandex-team.com>2025-01-16 19:09:30 +0300
committerrobot-piglet <robot-piglet@yandex-team.com>2025-01-16 19:38:51 +0300
commit7a23ad1fa2a5561a3575177d7240d8a1aa499718 (patch)
treeb4932bad31f595149e7a42e88cf729919995d735 /contrib/python/Flask/py3/flask/blueprints.py
parentfbb15f5ab8a61fc7c50500e2757af0b47174d825 (diff)
downloadydb-7a23ad1fa2a5561a3575177d7240d8a1aa499718.tar.gz
Intermediate changes
commit_hash:ae9e37c897fc6d514389f7089184df33bf781005
Diffstat (limited to 'contrib/python/Flask/py3/flask/blueprints.py')
-rw-r--r--contrib/python/Flask/py3/flask/blueprints.py271
1 files changed, 196 insertions, 75 deletions
diff --git a/contrib/python/Flask/py3/flask/blueprints.py b/contrib/python/Flask/py3/flask/blueprints.py
index 87617989e04..eb6642358d8 100644
--- a/contrib/python/Flask/py3/flask/blueprints.py
+++ b/contrib/python/Flask/py3/flask/blueprints.py
@@ -1,3 +1,4 @@
+import json
import os
import typing as t
from collections import defaultdict
@@ -7,11 +8,29 @@ from . import typing as ft
from .scaffold import _endpoint_from_view_func
from .scaffold import _sentinel
from .scaffold import Scaffold
+from .scaffold import setupmethod
-if t.TYPE_CHECKING:
+if t.TYPE_CHECKING: # pragma: no cover
from .app import Flask
DeferredSetupFunction = t.Callable[["BlueprintSetupState"], t.Callable]
+T_after_request = t.TypeVar("T_after_request", bound=ft.AfterRequestCallable)
+T_before_first_request = t.TypeVar(
+ "T_before_first_request", bound=ft.BeforeFirstRequestCallable
+)
+T_before_request = t.TypeVar("T_before_request", bound=ft.BeforeRequestCallable)
+T_error_handler = t.TypeVar("T_error_handler", bound=ft.ErrorHandlerCallable)
+T_teardown = t.TypeVar("T_teardown", bound=ft.TeardownCallable)
+T_template_context_processor = t.TypeVar(
+ "T_template_context_processor", bound=ft.TemplateContextProcessorCallable
+)
+T_template_filter = t.TypeVar("T_template_filter", bound=ft.TemplateFilterCallable)
+T_template_global = t.TypeVar("T_template_global", bound=ft.TemplateGlobalCallable)
+T_template_test = t.TypeVar("T_template_test", bound=ft.TemplateTestCallable)
+T_url_defaults = t.TypeVar("T_url_defaults", bound=ft.URLDefaultCallable)
+T_url_value_preprocessor = t.TypeVar(
+ "T_url_value_preprocessor", bound=ft.URLValuePreprocessorCallable
+)
class BlueprintSetupState:
@@ -152,15 +171,78 @@ class Blueprint(Scaffold):
.. versionadded:: 0.7
"""
- warn_on_modifications = False
_got_registered_once = False
- #: Blueprint local JSON encoder class to use. Set to ``None`` to use
- #: the app's :class:`~flask.Flask.json_encoder`.
- json_encoder = None
- #: Blueprint local JSON decoder class to use. Set to ``None`` to use
- #: the app's :class:`~flask.Flask.json_decoder`.
- json_decoder = None
+ _json_encoder: t.Union[t.Type[json.JSONEncoder], None] = None
+ _json_decoder: t.Union[t.Type[json.JSONDecoder], None] = None
+
+ @property
+ def json_encoder(
+ self,
+ ) -> t.Union[t.Type[json.JSONEncoder], None]:
+ """Blueprint-local JSON encoder class to use. Set to ``None`` to use the app's.
+
+ .. deprecated:: 2.2
+ Will be removed in Flask 2.3. Customize
+ :attr:`json_provider_class` instead.
+
+ .. versionadded:: 0.10
+ """
+ import warnings
+
+ warnings.warn(
+ "'bp.json_encoder' is deprecated and will be removed in Flask 2.3."
+ " Customize 'app.json_provider_class' or 'app.json' instead.",
+ DeprecationWarning,
+ stacklevel=2,
+ )
+ return self._json_encoder
+
+ @json_encoder.setter
+ def json_encoder(self, value: t.Union[t.Type[json.JSONEncoder], None]) -> None:
+ import warnings
+
+ warnings.warn(
+ "'bp.json_encoder' is deprecated and will be removed in Flask 2.3."
+ " Customize 'app.json_provider_class' or 'app.json' instead.",
+ DeprecationWarning,
+ stacklevel=2,
+ )
+ self._json_encoder = value
+
+ @property
+ def json_decoder(
+ self,
+ ) -> t.Union[t.Type[json.JSONDecoder], None]:
+ """Blueprint-local JSON decoder class to use. Set to ``None`` to use the app's.
+
+ .. deprecated:: 2.2
+ Will be removed in Flask 2.3. Customize
+ :attr:`json_provider_class` instead.
+
+ .. versionadded:: 0.10
+ """
+ import warnings
+
+ warnings.warn(
+ "'bp.json_decoder' is deprecated and will be removed in Flask 2.3."
+ " Customize 'app.json_provider_class' or 'app.json' instead.",
+ DeprecationWarning,
+ stacklevel=2,
+ )
+ return self._json_decoder
+
+ @json_decoder.setter
+ def json_decoder(self, value: t.Union[t.Type[json.JSONDecoder], None]) -> None:
+ import warnings
+
+ warnings.warn(
+ "'bp.json_decoder' is deprecated and will be removed in Flask 2.3."
+ " Customize 'app.json_provider_class' or 'app.json' instead.",
+ DeprecationWarning,
+ stacklevel=2,
+ )
+ self._json_decoder = value
def __init__(
self,
@@ -168,7 +250,7 @@ class Blueprint(Scaffold):
import_name: str,
static_folder: t.Optional[t.Union[str, os.PathLike]] = None,
static_url_path: t.Optional[str] = None,
- template_folder: t.Optional[str] = None,
+ template_folder: t.Optional[t.Union[str, os.PathLike]] = None,
url_prefix: t.Optional[str] = None,
subdomain: t.Optional[str] = None,
url_defaults: t.Optional[dict] = None,
@@ -198,27 +280,33 @@ class Blueprint(Scaffold):
self.cli_group = cli_group
self._blueprints: t.List[t.Tuple["Blueprint", dict]] = []
- def _is_setup_finished(self) -> bool:
- return self.warn_on_modifications and self._got_registered_once
+ def _check_setup_finished(self, f_name: str) -> None:
+ if self._got_registered_once:
+ import warnings
+
+ warnings.warn(
+ f"The setup method '{f_name}' can no longer be called on"
+ f" the blueprint '{self.name}'. It has already been"
+ " registered at least once, any changes will not be"
+ " applied consistently.\n"
+ "Make sure all imports, decorators, functions, etc."
+ " needed to set up the blueprint are done before"
+ " registering it.\n"
+ "This warning will become an exception in Flask 2.3.",
+ UserWarning,
+ stacklevel=3,
+ )
+ @setupmethod
def record(self, func: t.Callable) -> None:
"""Registers a function that is called when the blueprint is
registered on the application. This function is called with the
state as argument as returned by the :meth:`make_setup_state`
method.
"""
- if self._got_registered_once and self.warn_on_modifications:
- from warnings import warn
-
- warn(
- Warning(
- "The blueprint was already registered once but is"
- " getting modified now. These changes will not show"
- " up."
- )
- )
self.deferred_functions.append(func)
+ @setupmethod
def record_once(self, func: t.Callable) -> None:
"""Works like :meth:`record` but wraps the function in another
function that will ensure the function is only called once. If the
@@ -230,7 +318,7 @@ class Blueprint(Scaffold):
if state.first_registration:
func(state)
- return self.record(update_wrapper(wrapper, func))
+ self.record(update_wrapper(wrapper, func))
def make_setup_state(
self, app: "Flask", options: dict, first_registration: bool = False
@@ -241,6 +329,7 @@ class Blueprint(Scaffold):
"""
return BlueprintSetupState(self, app, options, first_registration)
+ @setupmethod
def register_blueprint(self, blueprint: "Blueprint", **options: t.Any) -> None:
"""Register a :class:`~flask.Blueprint` on this blueprint. Keyword
arguments passed to this method will override the defaults set
@@ -380,16 +469,20 @@ class Blueprint(Scaffold):
bp_options["name_prefix"] = name
blueprint.register(app, bp_options)
+ @setupmethod
def add_url_rule(
self,
rule: str,
endpoint: t.Optional[str] = None,
- view_func: t.Optional[ft.ViewCallable] = None,
+ view_func: t.Optional[ft.RouteCallable] = None,
provide_automatic_options: t.Optional[bool] = None,
**options: t.Any,
) -> None:
- """Like :meth:`Flask.add_url_rule` but for a blueprint. The endpoint for
- the :func:`url_for` function is prefixed with the name of the blueprint.
+ """Register a URL rule with the blueprint. See :meth:`.Flask.add_url_rule` for
+ full documentation.
+
+ The URL rule is prefixed with the blueprint's URL prefix. The endpoint name,
+ used with :func:`url_for`, is prefixed with the blueprint's name.
"""
if endpoint and "." in endpoint:
raise ValueError("'endpoint' may not contain a dot '.' character.")
@@ -407,28 +500,30 @@ class Blueprint(Scaffold):
)
)
+ @setupmethod
def app_template_filter(
self, name: t.Optional[str] = None
- ) -> t.Callable[[ft.TemplateFilterCallable], ft.TemplateFilterCallable]:
- """Register a custom template filter, available application wide. Like
- :meth:`Flask.template_filter` but for a blueprint.
+ ) -> t.Callable[[T_template_filter], T_template_filter]:
+ """Register a template filter, available in any template rendered by the
+ application. Equivalent to :meth:`.Flask.template_filter`.
:param name: the optional name of the filter, otherwise the
function name will be used.
"""
- def decorator(f: ft.TemplateFilterCallable) -> ft.TemplateFilterCallable:
+ def decorator(f: T_template_filter) -> T_template_filter:
self.add_app_template_filter(f, name=name)
return f
return decorator
+ @setupmethod
def add_app_template_filter(
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
- like the :meth:`app_template_filter` decorator.
+ """Register a template filter, available in any template rendered by the
+ application. Works like the :meth:`app_template_filter` decorator. Equivalent to
+ :meth:`.Flask.add_template_filter`.
:param name: the optional name of the filter, otherwise the
function name will be used.
@@ -439,11 +534,12 @@ class Blueprint(Scaffold):
self.record_once(register_template)
+ @setupmethod
def app_template_test(
self, name: t.Optional[str] = None
- ) -> t.Callable[[ft.TemplateTestCallable], ft.TemplateTestCallable]:
- """Register a custom template test, available application wide. Like
- :meth:`Flask.template_test` but for a blueprint.
+ ) -> t.Callable[[T_template_test], T_template_test]:
+ """Register a template test, available in any template rendered by the
+ application. Equivalent to :meth:`.Flask.template_test`.
.. versionadded:: 0.10
@@ -451,18 +547,19 @@ class Blueprint(Scaffold):
function name will be used.
"""
- def decorator(f: ft.TemplateTestCallable) -> ft.TemplateTestCallable:
+ def decorator(f: T_template_test) -> T_template_test:
self.add_app_template_test(f, name=name)
return f
return decorator
+ @setupmethod
def add_app_template_test(
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
- like the :meth:`app_template_test` decorator.
+ """Register a template test, available in any template rendered by the
+ application. Works like the :meth:`app_template_test` decorator. Equivalent to
+ :meth:`.Flask.add_template_test`.
.. versionadded:: 0.10
@@ -475,11 +572,12 @@ class Blueprint(Scaffold):
self.record_once(register_template)
+ @setupmethod
def app_template_global(
self, name: t.Optional[str] = None
- ) -> t.Callable[[ft.TemplateGlobalCallable], ft.TemplateGlobalCallable]:
- """Register a custom template global, available application wide. Like
- :meth:`Flask.template_global` but for a blueprint.
+ ) -> t.Callable[[T_template_global], T_template_global]:
+ """Register a template global, available in any template rendered by the
+ application. Equivalent to :meth:`.Flask.template_global`.
.. versionadded:: 0.10
@@ -487,18 +585,19 @@ class Blueprint(Scaffold):
function name will be used.
"""
- def decorator(f: ft.TemplateGlobalCallable) -> ft.TemplateGlobalCallable:
+ def decorator(f: T_template_global) -> T_template_global:
self.add_app_template_global(f, name=name)
return f
return decorator
+ @setupmethod
def add_app_template_global(
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
- like the :meth:`app_template_global` decorator.
+ """Register a template global, available in any template rendered by the
+ application. Works like the :meth:`app_template_global` decorator. Equivalent to
+ :meth:`.Flask.add_template_global`.
.. versionadded:: 0.10
@@ -511,80 +610,102 @@ class Blueprint(Scaffold):
self.record_once(register_template)
- 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.
+ @setupmethod
+ def before_app_request(self, f: T_before_request) -> T_before_request:
+ """Like :meth:`before_request`, but before every request, not only those handled
+ by the blueprint. Equivalent to :meth:`.Flask.before_request`.
"""
self.record_once(
lambda s: s.app.before_request_funcs.setdefault(None, []).append(f)
)
return f
+ @setupmethod
def before_app_first_request(
- 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, f: T_before_first_request
+ ) -> T_before_first_request:
+ """Register a function to run before the first request to the application is
+ handled by the worker. Equivalent to :meth:`.Flask.before_first_request`.
+
+ .. deprecated:: 2.2
+ Will be removed in Flask 2.3. Run setup code when creating
+ the application instead.
"""
+ import warnings
+
+ warnings.warn(
+ "'before_app_first_request' is deprecated and will be"
+ " removed in Flask 2.3. Use 'record_once' instead to run"
+ " setup code when registering the blueprint.",
+ DeprecationWarning,
+ stacklevel=2,
+ )
self.record_once(lambda s: s.app.before_first_request_funcs.append(f))
return f
- 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.
+ @setupmethod
+ def after_app_request(self, f: T_after_request) -> T_after_request:
+ """Like :meth:`after_request`, but after every request, not only those handled
+ by the blueprint. Equivalent to :meth:`.Flask.after_request`.
"""
self.record_once(
lambda s: s.app.after_request_funcs.setdefault(None, []).append(f)
)
return f
- 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.
+ @setupmethod
+ def teardown_app_request(self, f: T_teardown) -> T_teardown:
+ """Like :meth:`teardown_request`, but after every request, not only those
+ handled by the blueprint. Equivalent to :meth:`.Flask.teardown_request`.
"""
self.record_once(
lambda s: s.app.teardown_request_funcs.setdefault(None, []).append(f)
)
return f
+ @setupmethod
def app_context_processor(
- 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.
+ self, f: T_template_context_processor
+ ) -> T_template_context_processor:
+ """Like :meth:`context_processor`, but for templates rendered by every view, not
+ only by the blueprint. Equivalent to :meth:`.Flask.context_processor`.
"""
self.record_once(
lambda s: s.app.template_context_processors.setdefault(None, []).append(f)
)
return f
+ @setupmethod
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.
+ ) -> t.Callable[[T_error_handler], T_error_handler]:
+ """Like :meth:`errorhandler`, but for every request, not only those handled by
+ the blueprint. Equivalent to :meth:`.Flask.errorhandler`.
"""
- def decorator(f: ft.ErrorHandlerDecorator) -> ft.ErrorHandlerDecorator:
+ def decorator(f: T_error_handler) -> T_error_handler:
self.record_once(lambda s: s.app.errorhandler(code)(f))
return f
return decorator
+ @setupmethod
def app_url_value_preprocessor(
- self, f: ft.URLValuePreprocessorCallable
- ) -> ft.URLValuePreprocessorCallable:
- """Same as :meth:`url_value_preprocessor` but application wide."""
+ self, f: T_url_value_preprocessor
+ ) -> T_url_value_preprocessor:
+ """Like :meth:`url_value_preprocessor`, but for every request, not only those
+ handled by the blueprint. Equivalent to :meth:`.Flask.url_value_preprocessor`.
+ """
self.record_once(
lambda s: s.app.url_value_preprocessors.setdefault(None, []).append(f)
)
return f
- def app_url_defaults(self, f: ft.URLDefaultCallable) -> ft.URLDefaultCallable:
- """Same as :meth:`url_defaults` but application wide."""
+ @setupmethod
+ def app_url_defaults(self, f: T_url_defaults) -> T_url_defaults:
+ """Like :meth:`url_defaults`, but for every request, not only those handled by
+ the blueprint. Equivalent to :meth:`.Flask.url_defaults`.
+ """
self.record_once(
lambda s: s.app.url_default_functions.setdefault(None, []).append(f)
)