]> jfr.im git - dlqueue.git/blob - venv/lib/python3.11/site-packages/flask/sansio/app.py
init: venv aand flask
[dlqueue.git] / venv / lib / python3.11 / site-packages / flask / sansio / app.py
1 from __future__ import annotations
2
3 import logging
4 import os
5 import sys
6 import typing as t
7 from datetime import timedelta
8 from itertools import chain
9
10 from werkzeug.exceptions import Aborter
11 from werkzeug.exceptions import BadRequest
12 from werkzeug.exceptions import BadRequestKeyError
13 from werkzeug.routing import BuildError
14 from werkzeug.routing import Map
15 from werkzeug.routing import Rule
16 from werkzeug.sansio.response import Response
17 from werkzeug.utils import cached_property
18 from werkzeug.utils import redirect as _wz_redirect
19
20 from .. import typing as ft
21 from ..config import Config
22 from ..config import ConfigAttribute
23 from ..ctx import _AppCtxGlobals
24 from ..helpers import _split_blueprint_path
25 from ..helpers import get_debug_flag
26 from ..json.provider import DefaultJSONProvider
27 from ..json.provider import JSONProvider
28 from ..logging import create_logger
29 from ..templating import DispatchingJinjaLoader
30 from ..templating import Environment
31 from .scaffold import _endpoint_from_view_func
32 from .scaffold import find_package
33 from .scaffold import Scaffold
34 from .scaffold import setupmethod
35
36 if t.TYPE_CHECKING: # pragma: no cover
37 from werkzeug.wrappers import Response as BaseResponse
38 from .blueprints import Blueprint
39 from ..testing import FlaskClient
40 from ..testing import FlaskCliRunner
41
42 T_shell_context_processor = t.TypeVar(
43 "T_shell_context_processor", bound=ft.ShellContextProcessorCallable
44 )
45 T_teardown = t.TypeVar("T_teardown", bound=ft.TeardownCallable)
46 T_template_filter = t.TypeVar("T_template_filter", bound=ft.TemplateFilterCallable)
47 T_template_global = t.TypeVar("T_template_global", bound=ft.TemplateGlobalCallable)
48 T_template_test = t.TypeVar("T_template_test", bound=ft.TemplateTestCallable)
49
50
51 def _make_timedelta(value: timedelta | int | None) -> timedelta | None:
52 if value is None or isinstance(value, timedelta):
53 return value
54
55 return timedelta(seconds=value)
56
57
58 class App(Scaffold):
59 """The flask object implements a WSGI application and acts as the central
60 object. It is passed the name of the module or package of the
61 application. Once it is created it will act as a central registry for
62 the view functions, the URL rules, template configuration and much more.
63
64 The name of the package is used to resolve resources from inside the
65 package or the folder the module is contained in depending on if the
66 package parameter resolves to an actual python package (a folder with
67 an :file:`__init__.py` file inside) or a standard module (just a ``.py`` file).
68
69 For more information about resource loading, see :func:`open_resource`.
70
71 Usually you create a :class:`Flask` instance in your main module or
72 in the :file:`__init__.py` file of your package like this::
73
74 from flask import Flask
75 app = Flask(__name__)
76
77 .. admonition:: About the First Parameter
78
79 The idea of the first parameter is to give Flask an idea of what
80 belongs to your application. This name is used to find resources
81 on the filesystem, can be used by extensions to improve debugging
82 information and a lot more.
83
84 So it's important what you provide there. If you are using a single
85 module, `__name__` is always the correct value. If you however are
86 using a package, it's usually recommended to hardcode the name of
87 your package there.
88
89 For example if your application is defined in :file:`yourapplication/app.py`
90 you should create it with one of the two versions below::
91
92 app = Flask('yourapplication')
93 app = Flask(__name__.split('.')[0])
94
95 Why is that? The application will work even with `__name__`, thanks
96 to how resources are looked up. However it will make debugging more
97 painful. Certain extensions can make assumptions based on the
98 import name of your application. For example the Flask-SQLAlchemy
99 extension will look for the code in your application that triggered
100 an SQL query in debug mode. If the import name is not properly set
101 up, that debugging information is lost. (For example it would only
102 pick up SQL queries in `yourapplication.app` and not
103 `yourapplication.views.frontend`)
104
105 .. versionadded:: 0.7
106 The `static_url_path`, `static_folder`, and `template_folder`
107 parameters were added.
108
109 .. versionadded:: 0.8
110 The `instance_path` and `instance_relative_config` parameters were
111 added.
112
113 .. versionadded:: 0.11
114 The `root_path` parameter was added.
115
116 .. versionadded:: 1.0
117 The ``host_matching`` and ``static_host`` parameters were added.
118
119 .. versionadded:: 1.0
120 The ``subdomain_matching`` parameter was added. Subdomain
121 matching needs to be enabled manually now. Setting
122 :data:`SERVER_NAME` does not implicitly enable it.
123
124 :param import_name: the name of the application package
125 :param static_url_path: can be used to specify a different path for the
126 static files on the web. Defaults to the name
127 of the `static_folder` folder.
128 :param static_folder: The folder with static files that is served at
129 ``static_url_path``. Relative to the application ``root_path``
130 or an absolute path. Defaults to ``'static'``.
131 :param static_host: the host to use when adding the static route.
132 Defaults to None. Required when using ``host_matching=True``
133 with a ``static_folder`` configured.
134 :param host_matching: set ``url_map.host_matching`` attribute.
135 Defaults to False.
136 :param subdomain_matching: consider the subdomain relative to
137 :data:`SERVER_NAME` when matching routes. Defaults to False.
138 :param template_folder: the folder that contains the templates that should
139 be used by the application. Defaults to
140 ``'templates'`` folder in the root path of the
141 application.
142 :param instance_path: An alternative instance path for the application.
143 By default the folder ``'instance'`` next to the
144 package or module is assumed to be the instance
145 path.
146 :param instance_relative_config: if set to ``True`` relative filenames
147 for loading the config are assumed to
148 be relative to the instance path instead
149 of the application root.
150 :param root_path: The path to the root of the application files.
151 This should only be set manually when it can't be detected
152 automatically, such as for namespace packages.
153 """
154
155 #: The class of the object assigned to :attr:`aborter`, created by
156 #: :meth:`create_aborter`. That object is called by
157 #: :func:`flask.abort` to raise HTTP errors, and can be
158 #: called directly as well.
159 #:
160 #: Defaults to :class:`werkzeug.exceptions.Aborter`.
161 #:
162 #: .. versionadded:: 2.2
163 aborter_class = Aborter
164
165 #: The class that is used for the Jinja environment.
166 #:
167 #: .. versionadded:: 0.11
168 jinja_environment = Environment
169
170 #: The class that is used for the :data:`~flask.g` instance.
171 #:
172 #: Example use cases for a custom class:
173 #:
174 #: 1. Store arbitrary attributes on flask.g.
175 #: 2. Add a property for lazy per-request database connectors.
176 #: 3. Return None instead of AttributeError on unexpected attributes.
177 #: 4. Raise exception if an unexpected attr is set, a "controlled" flask.g.
178 #:
179 #: In Flask 0.9 this property was called `request_globals_class` but it
180 #: was changed in 0.10 to :attr:`app_ctx_globals_class` because the
181 #: flask.g object is now application context scoped.
182 #:
183 #: .. versionadded:: 0.10
184 app_ctx_globals_class = _AppCtxGlobals
185
186 #: The class that is used for the ``config`` attribute of this app.
187 #: Defaults to :class:`~flask.Config`.
188 #:
189 #: Example use cases for a custom class:
190 #:
191 #: 1. Default values for certain config options.
192 #: 2. Access to config values through attributes in addition to keys.
193 #:
194 #: .. versionadded:: 0.11
195 config_class = Config
196
197 #: The testing flag. Set this to ``True`` to enable the test mode of
198 #: Flask extensions (and in the future probably also Flask itself).
199 #: For example this might activate test helpers that have an
200 #: additional runtime cost which should not be enabled by default.
201 #:
202 #: If this is enabled and PROPAGATE_EXCEPTIONS is not changed from the
203 #: default it's implicitly enabled.
204 #:
205 #: This attribute can also be configured from the config with the
206 #: ``TESTING`` configuration key. Defaults to ``False``.
207 testing = ConfigAttribute("TESTING")
208
209 #: If a secret key is set, cryptographic components can use this to
210 #: sign cookies and other things. Set this to a complex random value
211 #: when you want to use the secure cookie for instance.
212 #:
213 #: This attribute can also be configured from the config with the
214 #: :data:`SECRET_KEY` configuration key. Defaults to ``None``.
215 secret_key = ConfigAttribute("SECRET_KEY")
216
217 #: A :class:`~datetime.timedelta` which is used to set the expiration
218 #: date of a permanent session. The default is 31 days which makes a
219 #: permanent session survive for roughly one month.
220 #:
221 #: This attribute can also be configured from the config with the
222 #: ``PERMANENT_SESSION_LIFETIME`` configuration key. Defaults to
223 #: ``timedelta(days=31)``
224 permanent_session_lifetime = ConfigAttribute(
225 "PERMANENT_SESSION_LIFETIME", get_converter=_make_timedelta
226 )
227
228 json_provider_class: type[JSONProvider] = DefaultJSONProvider
229 """A subclass of :class:`~flask.json.provider.JSONProvider`. An
230 instance is created and assigned to :attr:`app.json` when creating
231 the app.
232
233 The default, :class:`~flask.json.provider.DefaultJSONProvider`, uses
234 Python's built-in :mod:`json` library. A different provider can use
235 a different JSON library.
236
237 .. versionadded:: 2.2
238 """
239
240 #: Options that are passed to the Jinja environment in
241 #: :meth:`create_jinja_environment`. Changing these options after
242 #: the environment is created (accessing :attr:`jinja_env`) will
243 #: have no effect.
244 #:
245 #: .. versionchanged:: 1.1.0
246 #: This is a ``dict`` instead of an ``ImmutableDict`` to allow
247 #: easier configuration.
248 #:
249 jinja_options: dict = {}
250
251 #: The rule object to use for URL rules created. This is used by
252 #: :meth:`add_url_rule`. Defaults to :class:`werkzeug.routing.Rule`.
253 #:
254 #: .. versionadded:: 0.7
255 url_rule_class = Rule
256
257 #: The map object to use for storing the URL rules and routing
258 #: configuration parameters. Defaults to :class:`werkzeug.routing.Map`.
259 #:
260 #: .. versionadded:: 1.1.0
261 url_map_class = Map
262
263 #: The :meth:`test_client` method creates an instance of this test
264 #: client class. Defaults to :class:`~flask.testing.FlaskClient`.
265 #:
266 #: .. versionadded:: 0.7
267 test_client_class: type[FlaskClient] | None = None
268
269 #: The :class:`~click.testing.CliRunner` subclass, by default
270 #: :class:`~flask.testing.FlaskCliRunner` that is used by
271 #: :meth:`test_cli_runner`. Its ``__init__`` method should take a
272 #: Flask app object as the first argument.
273 #:
274 #: .. versionadded:: 1.0
275 test_cli_runner_class: type[FlaskCliRunner] | None = None
276
277 default_config: dict
278 response_class: type[Response]
279
280 def __init__(
281 self,
282 import_name: str,
283 static_url_path: str | None = None,
284 static_folder: str | os.PathLike | None = "static",
285 static_host: str | None = None,
286 host_matching: bool = False,
287 subdomain_matching: bool = False,
288 template_folder: str | os.PathLike | None = "templates",
289 instance_path: str | None = None,
290 instance_relative_config: bool = False,
291 root_path: str | None = None,
292 ):
293 super().__init__(
294 import_name=import_name,
295 static_folder=static_folder,
296 static_url_path=static_url_path,
297 template_folder=template_folder,
298 root_path=root_path,
299 )
300
301 if instance_path is None:
302 instance_path = self.auto_find_instance_path()
303 elif not os.path.isabs(instance_path):
304 raise ValueError(
305 "If an instance path is provided it must be absolute."
306 " A relative path was given instead."
307 )
308
309 #: Holds the path to the instance folder.
310 #:
311 #: .. versionadded:: 0.8
312 self.instance_path = instance_path
313
314 #: The configuration dictionary as :class:`Config`. This behaves
315 #: exactly like a regular dictionary but supports additional methods
316 #: to load a config from files.
317 self.config = self.make_config(instance_relative_config)
318
319 #: An instance of :attr:`aborter_class` created by
320 #: :meth:`make_aborter`. This is called by :func:`flask.abort`
321 #: to raise HTTP errors, and can be called directly as well.
322 #:
323 #: .. versionadded:: 2.2
324 #: Moved from ``flask.abort``, which calls this object.
325 self.aborter = self.make_aborter()
326
327 self.json: JSONProvider = self.json_provider_class(self)
328 """Provides access to JSON methods. Functions in ``flask.json``
329 will call methods on this provider when the application context
330 is active. Used for handling JSON requests and responses.
331
332 An instance of :attr:`json_provider_class`. Can be customized by
333 changing that attribute on a subclass, or by assigning to this
334 attribute afterwards.
335
336 The default, :class:`~flask.json.provider.DefaultJSONProvider`,
337 uses Python's built-in :mod:`json` library. A different provider
338 can use a different JSON library.
339
340 .. versionadded:: 2.2
341 """
342
343 #: A list of functions that are called by
344 #: :meth:`handle_url_build_error` when :meth:`.url_for` raises a
345 #: :exc:`~werkzeug.routing.BuildError`. Each function is called
346 #: with ``error``, ``endpoint`` and ``values``. If a function
347 #: returns ``None`` or raises a ``BuildError``, it is skipped.
348 #: Otherwise, its return value is returned by ``url_for``.
349 #:
350 #: .. versionadded:: 0.9
351 self.url_build_error_handlers: list[
352 t.Callable[[Exception, str, dict[str, t.Any]], str]
353 ] = []
354
355 #: A list of functions that are called when the application context
356 #: is destroyed. Since the application context is also torn down
357 #: if the request ends this is the place to store code that disconnects
358 #: from databases.
359 #:
360 #: .. versionadded:: 0.9
361 self.teardown_appcontext_funcs: list[ft.TeardownCallable] = []
362
363 #: A list of shell context processor functions that should be run
364 #: when a shell context is created.
365 #:
366 #: .. versionadded:: 0.11
367 self.shell_context_processors: list[ft.ShellContextProcessorCallable] = []
368
369 #: Maps registered blueprint names to blueprint objects. The
370 #: dict retains the order the blueprints were registered in.
371 #: Blueprints can be registered multiple times, this dict does
372 #: not track how often they were attached.
373 #:
374 #: .. versionadded:: 0.7
375 self.blueprints: dict[str, Blueprint] = {}
376
377 #: a place where extensions can store application specific state. For
378 #: example this is where an extension could store database engines and
379 #: similar things.
380 #:
381 #: The key must match the name of the extension module. For example in
382 #: case of a "Flask-Foo" extension in `flask_foo`, the key would be
383 #: ``'foo'``.
384 #:
385 #: .. versionadded:: 0.7
386 self.extensions: dict = {}
387
388 #: The :class:`~werkzeug.routing.Map` for this instance. You can use
389 #: this to change the routing converters after the class was created
390 #: but before any routes are connected. Example::
391 #:
392 #: from werkzeug.routing import BaseConverter
393 #:
394 #: class ListConverter(BaseConverter):
395 #: def to_python(self, value):
396 #: return value.split(',')
397 #: def to_url(self, values):
398 #: return ','.join(super(ListConverter, self).to_url(value)
399 #: for value in values)
400 #:
401 #: app = Flask(__name__)
402 #: app.url_map.converters['list'] = ListConverter
403 self.url_map = self.url_map_class(host_matching=host_matching)
404
405 self.subdomain_matching = subdomain_matching
406
407 # tracks internally if the application already handled at least one
408 # request.
409 self._got_first_request = False
410
411 # Set the name of the Click group in case someone wants to add
412 # the app's commands to another CLI tool.
413 self.cli.name = self.name
414
415 def _check_setup_finished(self, f_name: str) -> None:
416 if self._got_first_request:
417 raise AssertionError(
418 f"The setup method '{f_name}' can no longer be called"
419 " on the application. It has already handled its first"
420 " request, any changes will not be applied"
421 " consistently.\n"
422 "Make sure all imports, decorators, functions, etc."
423 " needed to set up the application are done before"
424 " running it."
425 )
426
427 @cached_property
428 def name(self) -> str: # type: ignore
429 """The name of the application. This is usually the import name
430 with the difference that it's guessed from the run file if the
431 import name is main. This name is used as a display name when
432 Flask needs the name of the application. It can be set and overridden
433 to change the value.
434
435 .. versionadded:: 0.8
436 """
437 if self.import_name == "__main__":
438 fn = getattr(sys.modules["__main__"], "__file__", None)
439 if fn is None:
440 return "__main__"
441 return os.path.splitext(os.path.basename(fn))[0]
442 return self.import_name
443
444 @cached_property
445 def logger(self) -> logging.Logger:
446 """A standard Python :class:`~logging.Logger` for the app, with
447 the same name as :attr:`name`.
448
449 In debug mode, the logger's :attr:`~logging.Logger.level` will
450 be set to :data:`~logging.DEBUG`.
451
452 If there are no handlers configured, a default handler will be
453 added. See :doc:`/logging` for more information.
454
455 .. versionchanged:: 1.1.0
456 The logger takes the same name as :attr:`name` rather than
457 hard-coding ``"flask.app"``.
458
459 .. versionchanged:: 1.0.0
460 Behavior was simplified. The logger is always named
461 ``"flask.app"``. The level is only set during configuration,
462 it doesn't check ``app.debug`` each time. Only one format is
463 used, not different ones depending on ``app.debug``. No
464 handlers are removed, and a handler is only added if no
465 handlers are already configured.
466
467 .. versionadded:: 0.3
468 """
469 return create_logger(self)
470
471 @cached_property
472 def jinja_env(self) -> Environment:
473 """The Jinja environment used to load templates.
474
475 The environment is created the first time this property is
476 accessed. Changing :attr:`jinja_options` after that will have no
477 effect.
478 """
479 return self.create_jinja_environment()
480
481 def create_jinja_environment(self) -> Environment:
482 raise NotImplementedError()
483
484 def make_config(self, instance_relative: bool = False) -> Config:
485 """Used to create the config attribute by the Flask constructor.
486 The `instance_relative` parameter is passed in from the constructor
487 of Flask (there named `instance_relative_config`) and indicates if
488 the config should be relative to the instance path or the root path
489 of the application.
490
491 .. versionadded:: 0.8
492 """
493 root_path = self.root_path
494 if instance_relative:
495 root_path = self.instance_path
496 defaults = dict(self.default_config)
497 defaults["DEBUG"] = get_debug_flag()
498 return self.config_class(root_path, defaults)
499
500 def make_aborter(self) -> Aborter:
501 """Create the object to assign to :attr:`aborter`. That object
502 is called by :func:`flask.abort` to raise HTTP errors, and can
503 be called directly as well.
504
505 By default, this creates an instance of :attr:`aborter_class`,
506 which defaults to :class:`werkzeug.exceptions.Aborter`.
507
508 .. versionadded:: 2.2
509 """
510 return self.aborter_class()
511
512 def auto_find_instance_path(self) -> str:
513 """Tries to locate the instance path if it was not provided to the
514 constructor of the application class. It will basically calculate
515 the path to a folder named ``instance`` next to your main file or
516 the package.
517
518 .. versionadded:: 0.8
519 """
520 prefix, package_path = find_package(self.import_name)
521 if prefix is None:
522 return os.path.join(package_path, "instance")
523 return os.path.join(prefix, "var", f"{self.name}-instance")
524
525 def create_global_jinja_loader(self) -> DispatchingJinjaLoader:
526 """Creates the loader for the Jinja2 environment. Can be used to
527 override just the loader and keeping the rest unchanged. It's
528 discouraged to override this function. Instead one should override
529 the :meth:`jinja_loader` function instead.
530
531 The global loader dispatches between the loaders of the application
532 and the individual blueprints.
533
534 .. versionadded:: 0.7
535 """
536 return DispatchingJinjaLoader(self)
537
538 def select_jinja_autoescape(self, filename: str) -> bool:
539 """Returns ``True`` if autoescaping should be active for the given
540 template name. If no template name is given, returns `True`.
541
542 .. versionchanged:: 2.2
543 Autoescaping is now enabled by default for ``.svg`` files.
544
545 .. versionadded:: 0.5
546 """
547 if filename is None:
548 return True
549 return filename.endswith((".html", ".htm", ".xml", ".xhtml", ".svg"))
550
551 @property
552 def debug(self) -> bool:
553 """Whether debug mode is enabled. When using ``flask run`` to start the
554 development server, an interactive debugger will be shown for unhandled
555 exceptions, and the server will be reloaded when code changes. This maps to the
556 :data:`DEBUG` config key. It may not behave as expected if set late.
557
558 **Do not enable debug mode when deploying in production.**
559
560 Default: ``False``
561 """
562 return self.config["DEBUG"]
563
564 @debug.setter
565 def debug(self, value: bool) -> None:
566 self.config["DEBUG"] = value
567
568 if self.config["TEMPLATES_AUTO_RELOAD"] is None:
569 self.jinja_env.auto_reload = value
570
571 @setupmethod
572 def register_blueprint(self, blueprint: Blueprint, **options: t.Any) -> None:
573 """Register a :class:`~flask.Blueprint` on the application. Keyword
574 arguments passed to this method will override the defaults set on the
575 blueprint.
576
577 Calls the blueprint's :meth:`~flask.Blueprint.register` method after
578 recording the blueprint in the application's :attr:`blueprints`.
579
580 :param blueprint: The blueprint to register.
581 :param url_prefix: Blueprint routes will be prefixed with this.
582 :param subdomain: Blueprint routes will match on this subdomain.
583 :param url_defaults: Blueprint routes will use these default values for
584 view arguments.
585 :param options: Additional keyword arguments are passed to
586 :class:`~flask.blueprints.BlueprintSetupState`. They can be
587 accessed in :meth:`~flask.Blueprint.record` callbacks.
588
589 .. versionchanged:: 2.0.1
590 The ``name`` option can be used to change the (pre-dotted)
591 name the blueprint is registered with. This allows the same
592 blueprint to be registered multiple times with unique names
593 for ``url_for``.
594
595 .. versionadded:: 0.7
596 """
597 blueprint.register(self, options)
598
599 def iter_blueprints(self) -> t.ValuesView[Blueprint]:
600 """Iterates over all blueprints by the order they were registered.
601
602 .. versionadded:: 0.11
603 """
604 return self.blueprints.values()
605
606 @setupmethod
607 def add_url_rule(
608 self,
609 rule: str,
610 endpoint: str | None = None,
611 view_func: ft.RouteCallable | None = None,
612 provide_automatic_options: bool | None = None,
613 **options: t.Any,
614 ) -> None:
615 if endpoint is None:
616 endpoint = _endpoint_from_view_func(view_func) # type: ignore
617 options["endpoint"] = endpoint
618 methods = options.pop("methods", None)
619
620 # if the methods are not given and the view_func object knows its
621 # methods we can use that instead. If neither exists, we go with
622 # a tuple of only ``GET`` as default.
623 if methods is None:
624 methods = getattr(view_func, "methods", None) or ("GET",)
625 if isinstance(methods, str):
626 raise TypeError(
627 "Allowed methods must be a list of strings, for"
628 ' example: @app.route(..., methods=["POST"])'
629 )
630 methods = {item.upper() for item in methods}
631
632 # Methods that should always be added
633 required_methods = set(getattr(view_func, "required_methods", ()))
634
635 # starting with Flask 0.8 the view_func object can disable and
636 # force-enable the automatic options handling.
637 if provide_automatic_options is None:
638 provide_automatic_options = getattr(
639 view_func, "provide_automatic_options", None
640 )
641
642 if provide_automatic_options is None:
643 if "OPTIONS" not in methods:
644 provide_automatic_options = True
645 required_methods.add("OPTIONS")
646 else:
647 provide_automatic_options = False
648
649 # Add the required methods now.
650 methods |= required_methods
651
652 rule = self.url_rule_class(rule, methods=methods, **options)
653 rule.provide_automatic_options = provide_automatic_options # type: ignore
654
655 self.url_map.add(rule)
656 if view_func is not None:
657 old_func = self.view_functions.get(endpoint)
658 if old_func is not None and old_func != view_func:
659 raise AssertionError(
660 "View function mapping is overwriting an existing"
661 f" endpoint function: {endpoint}"
662 )
663 self.view_functions[endpoint] = view_func
664
665 @setupmethod
666 def template_filter(
667 self, name: str | None = None
668 ) -> t.Callable[[T_template_filter], T_template_filter]:
669 """A decorator that is used to register custom template filter.
670 You can specify a name for the filter, otherwise the function
671 name will be used. Example::
672
673 @app.template_filter()
674 def reverse(s):
675 return s[::-1]
676
677 :param name: the optional name of the filter, otherwise the
678 function name will be used.
679 """
680
681 def decorator(f: T_template_filter) -> T_template_filter:
682 self.add_template_filter(f, name=name)
683 return f
684
685 return decorator
686
687 @setupmethod
688 def add_template_filter(
689 self, f: ft.TemplateFilterCallable, name: str | None = None
690 ) -> None:
691 """Register a custom template filter. Works exactly like the
692 :meth:`template_filter` decorator.
693
694 :param name: the optional name of the filter, otherwise the
695 function name will be used.
696 """
697 self.jinja_env.filters[name or f.__name__] = f
698
699 @setupmethod
700 def template_test(
701 self, name: str | None = None
702 ) -> t.Callable[[T_template_test], T_template_test]:
703 """A decorator that is used to register custom template test.
704 You can specify a name for the test, otherwise the function
705 name will be used. Example::
706
707 @app.template_test()
708 def is_prime(n):
709 if n == 2:
710 return True
711 for i in range(2, int(math.ceil(math.sqrt(n))) + 1):
712 if n % i == 0:
713 return False
714 return True
715
716 .. versionadded:: 0.10
717
718 :param name: the optional name of the test, otherwise the
719 function name will be used.
720 """
721
722 def decorator(f: T_template_test) -> T_template_test:
723 self.add_template_test(f, name=name)
724 return f
725
726 return decorator
727
728 @setupmethod
729 def add_template_test(
730 self, f: ft.TemplateTestCallable, name: str | None = None
731 ) -> None:
732 """Register a custom template test. Works exactly like the
733 :meth:`template_test` decorator.
734
735 .. versionadded:: 0.10
736
737 :param name: the optional name of the test, otherwise the
738 function name will be used.
739 """
740 self.jinja_env.tests[name or f.__name__] = f
741
742 @setupmethod
743 def template_global(
744 self, name: str | None = None
745 ) -> t.Callable[[T_template_global], T_template_global]:
746 """A decorator that is used to register a custom template global function.
747 You can specify a name for the global function, otherwise the function
748 name will be used. Example::
749
750 @app.template_global()
751 def double(n):
752 return 2 * n
753
754 .. versionadded:: 0.10
755
756 :param name: the optional name of the global function, otherwise the
757 function name will be used.
758 """
759
760 def decorator(f: T_template_global) -> T_template_global:
761 self.add_template_global(f, name=name)
762 return f
763
764 return decorator
765
766 @setupmethod
767 def add_template_global(
768 self, f: ft.TemplateGlobalCallable, name: str | None = None
769 ) -> None:
770 """Register a custom template global function. Works exactly like the
771 :meth:`template_global` decorator.
772
773 .. versionadded:: 0.10
774
775 :param name: the optional name of the global function, otherwise the
776 function name will be used.
777 """
778 self.jinja_env.globals[name or f.__name__] = f
779
780 @setupmethod
781 def teardown_appcontext(self, f: T_teardown) -> T_teardown:
782 """Registers a function to be called when the application
783 context is popped. The application context is typically popped
784 after the request context for each request, at the end of CLI
785 commands, or after a manually pushed context ends.
786
787 .. code-block:: python
788
789 with app.app_context():
790 ...
791
792 When the ``with`` block exits (or ``ctx.pop()`` is called), the
793 teardown functions are called just before the app context is
794 made inactive. Since a request context typically also manages an
795 application context it would also be called when you pop a
796 request context.
797
798 When a teardown function was called because of an unhandled
799 exception it will be passed an error object. If an
800 :meth:`errorhandler` is registered, it will handle the exception
801 and the teardown will not receive it.
802
803 Teardown functions must avoid raising exceptions. If they
804 execute code that might fail they must surround that code with a
805 ``try``/``except`` block and log any errors.
806
807 The return values of teardown functions are ignored.
808
809 .. versionadded:: 0.9
810 """
811 self.teardown_appcontext_funcs.append(f)
812 return f
813
814 @setupmethod
815 def shell_context_processor(
816 self, f: T_shell_context_processor
817 ) -> T_shell_context_processor:
818 """Registers a shell context processor function.
819
820 .. versionadded:: 0.11
821 """
822 self.shell_context_processors.append(f)
823 return f
824
825 def _find_error_handler(
826 self, e: Exception, blueprints: list[str]
827 ) -> ft.ErrorHandlerCallable | None:
828 """Return a registered error handler for an exception in this order:
829 blueprint handler for a specific code, app handler for a specific code,
830 blueprint handler for an exception class, app handler for an exception
831 class, or ``None`` if a suitable handler is not found.
832 """
833 exc_class, code = self._get_exc_class_and_code(type(e))
834 names = (*blueprints, None)
835
836 for c in (code, None) if code is not None else (None,):
837 for name in names:
838 handler_map = self.error_handler_spec[name][c]
839
840 if not handler_map:
841 continue
842
843 for cls in exc_class.__mro__:
844 handler = handler_map.get(cls)
845
846 if handler is not None:
847 return handler
848 return None
849
850 def trap_http_exception(self, e: Exception) -> bool:
851 """Checks if an HTTP exception should be trapped or not. By default
852 this will return ``False`` for all exceptions except for a bad request
853 key error if ``TRAP_BAD_REQUEST_ERRORS`` is set to ``True``. It
854 also returns ``True`` if ``TRAP_HTTP_EXCEPTIONS`` is set to ``True``.
855
856 This is called for all HTTP exceptions raised by a view function.
857 If it returns ``True`` for any exception the error handler for this
858 exception is not called and it shows up as regular exception in the
859 traceback. This is helpful for debugging implicitly raised HTTP
860 exceptions.
861
862 .. versionchanged:: 1.0
863 Bad request errors are not trapped by default in debug mode.
864
865 .. versionadded:: 0.8
866 """
867 if self.config["TRAP_HTTP_EXCEPTIONS"]:
868 return True
869
870 trap_bad_request = self.config["TRAP_BAD_REQUEST_ERRORS"]
871
872 # if unset, trap key errors in debug mode
873 if (
874 trap_bad_request is None
875 and self.debug
876 and isinstance(e, BadRequestKeyError)
877 ):
878 return True
879
880 if trap_bad_request:
881 return isinstance(e, BadRequest)
882
883 return False
884
885 def should_ignore_error(self, error: BaseException | None) -> bool:
886 """This is called to figure out if an error should be ignored
887 or not as far as the teardown system is concerned. If this
888 function returns ``True`` then the teardown handlers will not be
889 passed the error.
890
891 .. versionadded:: 0.10
892 """
893 return False
894
895 def redirect(self, location: str, code: int = 302) -> BaseResponse:
896 """Create a redirect response object.
897
898 This is called by :func:`flask.redirect`, and can be called
899 directly as well.
900
901 :param location: The URL to redirect to.
902 :param code: The status code for the redirect.
903
904 .. versionadded:: 2.2
905 Moved from ``flask.redirect``, which calls this method.
906 """
907 return _wz_redirect(
908 location, code=code, Response=self.response_class # type: ignore[arg-type]
909 )
910
911 def inject_url_defaults(self, endpoint: str, values: dict) -> None:
912 """Injects the URL defaults for the given endpoint directly into
913 the values dictionary passed. This is used internally and
914 automatically called on URL building.
915
916 .. versionadded:: 0.7
917 """
918 names: t.Iterable[str | None] = (None,)
919
920 # url_for may be called outside a request context, parse the
921 # passed endpoint instead of using request.blueprints.
922 if "." in endpoint:
923 names = chain(
924 names, reversed(_split_blueprint_path(endpoint.rpartition(".")[0]))
925 )
926
927 for name in names:
928 if name in self.url_default_functions:
929 for func in self.url_default_functions[name]:
930 func(endpoint, values)
931
932 def handle_url_build_error(
933 self, error: BuildError, endpoint: str, values: dict[str, t.Any]
934 ) -> str:
935 """Called by :meth:`.url_for` if a
936 :exc:`~werkzeug.routing.BuildError` was raised. If this returns
937 a value, it will be returned by ``url_for``, otherwise the error
938 will be re-raised.
939
940 Each function in :attr:`url_build_error_handlers` is called with
941 ``error``, ``endpoint`` and ``values``. If a function returns
942 ``None`` or raises a ``BuildError``, it is skipped. Otherwise,
943 its return value is returned by ``url_for``.
944
945 :param error: The active ``BuildError`` being handled.
946 :param endpoint: The endpoint being built.
947 :param values: The keyword arguments passed to ``url_for``.
948 """
949 for handler in self.url_build_error_handlers:
950 try:
951 rv = handler(error, endpoint, values)
952 except BuildError as e:
953 # make error available outside except block
954 error = e
955 else:
956 if rv is not None:
957 return rv
958
959 # Re-raise if called with an active exception, otherwise raise
960 # the passed in exception.
961 if error is sys.exc_info()[1]:
962 raise
963
964 raise error