rewrite docs, clean up typing for template decorators

This commit is contained in:
David Lord 2025-08-19 12:29:47 -07:00
parent daf1510a4b
commit edebd37044
No known key found for this signature in database
GPG key ID: 43368A7AA8CC5926
3 changed files with 229 additions and 180 deletions

View file

@ -660,37 +660,34 @@ class App(Scaffold):
)
self.view_functions[endpoint] = view_func
@t.overload
def template_filter(self, name: T_template_filter) -> T_template_filter: ...
@t.overload
def template_filter(
self, name: str | None = None
) -> t.Callable[[T_template_filter], T_template_filter]: ...
@setupmethod
def template_filter(
self, name: t.Callable[..., t.Any] | str | None = None
) -> t.Callable[[T_template_filter], T_template_filter] | T_template_filter:
"""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::
self, name: T_template_filter | str | None = None
) -> T_template_filter | t.Callable[[T_template_filter], T_template_filter]:
"""Decorate a function to register it as a custom Jinja filter. The name
is optional. The decorator may be used without parentheses.
@app.template_filter()
def reverse(s):
return s[::-1]
.. code-block:: python
The decorator also can be used without parentheses::
@app.template_filter("reverse")
def reverse_filter(s):
return reversed(s)
@app.template_filter
def reverse(s):
return s[::-1]
The :meth:`add_template_filter` method may be used to register a
function later rather than decorating.
:param name: the optional name of the filter, otherwise the
function name will be used.
:param name: The name to register the filter as. If not given, uses the
function's name.
"""
if callable(name):
# If name is callable, it is the function to register.
# This is a shortcut for the common case of
# @app.template_filter
# def func():
func = name
self.add_template_filter(func)
return func
self.add_template_filter(name)
return name
def decorator(f: T_template_filter) -> T_template_filter:
self.add_template_filter(f, name=name)
@ -702,24 +699,34 @@ class App(Scaffold):
def add_template_filter(
self, f: ft.TemplateFilterCallable, name: str | None = None
) -> None:
"""Register a custom template filter. Works exactly like the
:meth:`template_filter` decorator.
"""Register a function to use as a custom Jinja filter.
:param name: the optional name of the filter, otherwise the
function name will be used.
The :meth:`template_filter` decorator can be used to register a function
by decorating instead.
:param f: The function to register.
:param name: The name to register the filter as. If not given, uses the
function's name.
"""
self.jinja_env.filters[name or f.__name__] = f
@t.overload
def template_test(self, name: T_template_test) -> T_template_test: ...
@t.overload
def template_test(
self, name: str | None = None
) -> t.Callable[[T_template_test], T_template_test]: ...
@setupmethod
def template_test(
self, name: t.Callable[..., t.Any] | str | None = None
) -> t.Callable[[T_template_test], T_template_test] | T_template_filter:
"""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::
self, name: T_template_test | str | None = None
) -> T_template_test | t.Callable[[T_template_test], T_template_test]:
"""Decorate a function to register it as a custom Jinja test. The name
is optional. The decorator may be used without parentheses.
@app.template_test()
def is_prime(n):
.. code-block:: python
@app.template_test("prime")
def is_prime_test(n):
if n == 2:
return True
for i in range(2, int(math.ceil(math.sqrt(n))) + 1):
@ -727,31 +734,17 @@ class App(Scaffold):
return False
return True
The decorator also can be used without parentheses::
The :meth:`add_template_test` method may be used to register a function
later rather than decorating.
@app.template_test
def is_prime(n):
if n == 2:
return True
for i in range(2, int(math.ceil(math.sqrt(n))) + 1):
if n % i == 0:
return False
:param name: The name to register the filter as. If not given, uses the
function's name.
.. versionadded:: 0.10
:param name: the optional name of the test, otherwise the
function name will be used.
"""
if callable(name):
# If name is callable, it is the function to register.
# This is a shortcut for the common case of
# @app.template_test
# def func():
func = name
self.add_template_test(func)
return func
self.add_template_test(name)
return name # type: ignore[return-value]
def decorator(f: T_template_test) -> T_template_test:
self.add_template_test(f, name=name)
@ -763,49 +756,49 @@ class App(Scaffold):
def add_template_test(
self, f: ft.TemplateTestCallable, name: str | None = None
) -> None:
"""Register a custom template test. Works exactly like the
:meth:`template_test` decorator.
"""Register a function to use as a custom Jinja test.
The :meth:`template_test` decorator can be used to register a function
by decorating instead.
:param f: The function to register.
:param name: The name to register the test as. If not given, uses the
function's name.
.. versionadded:: 0.10
:param name: the optional name of the test, otherwise the
function name will be used.
"""
self.jinja_env.tests[name or f.__name__] = f
@t.overload
def template_global(self, name: T_template_global) -> T_template_global: ...
@t.overload
def template_global(
self, name: str | None = None
) -> t.Callable[[T_template_global], T_template_global]: ...
@setupmethod
def template_global(
self, name: t.Callable[..., t.Any] | str | None = None
) -> t.Callable[[T_template_global], T_template_global] | T_template_filter:
"""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::
self, name: T_template_global | str | None = None
) -> T_template_global | t.Callable[[T_template_global], T_template_global]:
"""Decorate a function to register it as a custom Jinja global. The name
is optional. The decorator may be used without parentheses.
@app.template_global()
def double(n):
return 2 * n
The decorator also can be used without parentheses::
.. code-block:: python
@app.template_global
def double(n):
return 2 * n
The :meth:`add_template_global` method may be used to register a
function later rather than decorating.
:param name: The name to register the global as. If not given, uses the
function's name.
.. versionadded:: 0.10
:param name: the optional name of the global function, otherwise the
function name will be used.
"""
if callable(name):
# If name is callable, it is the function to register.
# This is a shortcut for the common case of
# @app.template_global
# def func():
func = name
self.add_template_global(func)
return func
self.add_template_global(name)
return name
def decorator(f: T_template_global) -> T_template_global:
self.add_template_global(f, name=name)
@ -817,13 +810,16 @@ class App(Scaffold):
def add_template_global(
self, f: ft.TemplateGlobalCallable, name: str | None = None
) -> None:
"""Register a custom template global function. Works exactly like the
:meth:`template_global` decorator.
"""Register a function to use as a custom Jinja global.
The :meth:`template_global` decorator can be used to register a function
by decorating instead.
:param f: The function to register.
:param name: The name to register the global as. If not given, uses the
function's name.
.. versionadded:: 0.10
:param name: the optional name of the global function, otherwise the
function name will be used.
"""
self.jinja_env.globals[name or f.__name__] = f

View file

@ -440,26 +440,31 @@ class Blueprint(Scaffold):
)
)
@t.overload
def app_template_filter(self, name: T_template_filter) -> T_template_filter: ...
@t.overload
def app_template_filter(
self, name: str | None = None
) -> t.Callable[[T_template_filter], T_template_filter]: ...
@setupmethod
def app_template_filter(
self, name: t.Callable[..., t.Any] | str | None = None
) -> t.Callable[[T_template_filter], T_template_filter] | T_template_filter:
"""Register a template filter, available in any template rendered by the
application. Equivalent to :meth:`.Flask.template_filter`.
self, name: T_template_filter | str | None = None
) -> T_template_filter | t.Callable[[T_template_filter], T_template_filter]:
"""Decorate a function to register it as a custom Jinja filter. The name
is optional. The decorator may be used without parentheses.
:param name: the optional name of the filter, otherwise the
function name will be used.
The :meth:`add_app_template_filter` method may be used to register a
function later rather than decorating.
The filter is available in all templates, not only those under this
blueprint. Equivalent to :meth:`.Flask.template_filter`.
:param name: The name to register the filter as. If not given, uses the
function's name.
"""
if callable(name):
# If name is callable, it is the function to register.
# This is a shortcut for the common case of
# @bp.add_template_filter
# def func():
func = name
self.add_app_template_filter(func)
return func
self.add_app_template_filter(name)
return name
def decorator(f: T_template_filter) -> T_template_filter:
self.add_app_template_filter(f, name=name)
@ -471,41 +476,51 @@ class Blueprint(Scaffold):
def add_app_template_filter(
self, f: ft.TemplateFilterCallable, name: str | None = None
) -> None:
"""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`.
"""Register a function to use as a custom Jinja filter.
:param name: the optional name of the filter, otherwise the
function name will be used.
The :meth:`app_template_filter` decorator can be used to register a
function by decorating instead.
The filter is available in all templates, not only those under this
blueprint. Equivalent to :meth:`.Flask.add_template_filter`.
:param f: The function to register.
:param name: The name to register the filter as. If not given, uses the
function's name.
"""
def register_template(state: BlueprintSetupState) -> None:
state.app.jinja_env.filters[name or f.__name__] = f
def register_template_filter(state: BlueprintSetupState) -> None:
state.app.add_template_filter(f, name=name)
self.record_once(register_template)
self.record_once(register_template_filter)
@t.overload
def app_template_test(self, name: T_template_test) -> T_template_test: ...
@t.overload
def app_template_test(
self, name: str | None = None
) -> t.Callable[[T_template_test], T_template_test]: ...
@setupmethod
def app_template_test(
self, name: t.Callable[..., t.Any] | str | None = None
) -> t.Callable[[T_template_test], T_template_test] | T_template_filter:
"""Register a template test, available in any template rendered by the
application. Equivalent to :meth:`.Flask.template_test`.
self, name: T_template_test | str | None = None
) -> T_template_test | t.Callable[[T_template_test], T_template_test]:
"""Decorate a function to register it as a custom Jinja test. The name
is optional. The decorator may be used without parentheses.
The :meth:`add_app_template_test` method may be used to register a
function later rather than decorating.
The test is available in all templates, not only those under this
blueprint. Equivalent to :meth:`.Flask.template_test`.
:param name: The name to register the filter as. If not given, uses the
function's name.
.. versionadded:: 0.10
:param name: the optional name of the test, otherwise the
function name will be used.
"""
if callable(name):
# If name is callable, it is the function to register.
# This is a shortcut for the common case of
# @bp.add_template_test
# def func():
func = name
self.add_app_template_test(func)
return func
self.add_app_template_test(name)
return name # type: ignore[return-value]
def decorator(f: T_template_test) -> T_template_test:
self.add_app_template_test(f, name=name)
@ -517,42 +532,53 @@ class Blueprint(Scaffold):
def add_app_template_test(
self, f: ft.TemplateTestCallable, name: str | None = None
) -> None:
"""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`.
"""Register a function to use as a custom Jinja test.
The :meth:`app_template_test` decorator can be used to register a
function by decorating instead.
The test is available in all templates, not only those under this
blueprint. Equivalent to :meth:`.Flask.add_template_test`.
:param f: The function to register.
:param name: The name to register the test as. If not given, uses the
function's name.
.. versionadded:: 0.10
:param name: the optional name of the test, otherwise the
function name will be used.
"""
def register_template(state: BlueprintSetupState) -> None:
state.app.jinja_env.tests[name or f.__name__] = f
def register_template_test(state: BlueprintSetupState) -> None:
state.app.add_template_test(f, name=name)
self.record_once(register_template)
self.record_once(register_template_test)
@t.overload
def app_template_global(self, name: T_template_global) -> T_template_global: ...
@t.overload
def app_template_global(
self, name: str | None = None
) -> t.Callable[[T_template_global], T_template_global]: ...
@setupmethod
def app_template_global(
self, name: t.Callable[..., t.Any] | str | None = None
) -> t.Callable[[T_template_global], T_template_global] | T_template_filter:
"""Register a template global, available in any template rendered by the
application. Equivalent to :meth:`.Flask.template_global`.
self, name: T_template_global | str | None = None
) -> T_template_global | t.Callable[[T_template_global], T_template_global]:
"""Decorate a function to register it as a custom Jinja global. The name
is optional. The decorator may be used without parentheses.
The :meth:`add_app_template_global` method may be used to register a
function later rather than decorating.
The global is available in all templates, not only those under this
blueprint. Equivalent to :meth:`.Flask.template_global`.
:param name: The name to register the global as. If not given, uses the
function's name.
.. versionadded:: 0.10
:param name: the optional name of the global, otherwise the
function name will be used.
"""
if callable(name):
# If name is callable, it is the function to register.
# This is a shortcut for the common case of
# @bp.add_template_global
# def func():
func = name
self.add_app_template_global(func)
return func
self.add_app_template_global(name)
return name
def decorator(f: T_template_global) -> T_template_global:
self.add_app_template_global(f, name=name)
@ -564,20 +590,25 @@ class Blueprint(Scaffold):
def add_app_template_global(
self, f: ft.TemplateGlobalCallable, name: str | None = None
) -> None:
"""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`.
"""Register a function to use as a custom Jinja global.
The :meth:`app_template_global` decorator can be used to register a function
by decorating instead.
The global is available in all templates, not only those under this
blueprint. Equivalent to :meth:`.Flask.add_template_global`.
:param f: The function to register.
:param name: The name to register the global as. If not given, uses the
function's name.
.. versionadded:: 0.10
:param name: the optional name of the global, otherwise the
function name will be used.
"""
def register_template(state: BlueprintSetupState) -> None:
state.app.jinja_env.globals[name or f.__name__] = f
def register_template_global(state: BlueprintSetupState) -> None:
state.app.add_template_global(f, name=name)
self.record_once(register_template)
self.record_once(register_template_global)
@setupmethod
def before_app_request(self, f: T_before_request) -> T_before_request: