diff options
author | robot-piglet <robot-piglet@yandex-team.com> | 2025-01-16 19:09:30 +0300 |
---|---|---|
committer | robot-piglet <robot-piglet@yandex-team.com> | 2025-01-16 19:38:51 +0300 |
commit | 7a23ad1fa2a5561a3575177d7240d8a1aa499718 (patch) | |
tree | b4932bad31f595149e7a42e88cf729919995d735 /contrib/python/Flask/py3/flask/blueprints.py | |
parent | fbb15f5ab8a61fc7c50500e2757af0b47174d825 (diff) | |
download | ydb-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.py | 271 |
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) ) |