Fix template_filter decorator to support both usage styles and update docstring; update CHANGES.rst

This commit is contained in:
Akshay 2025-05-16 14:49:45 +05:30
parent c94824744c
commit 6ff24afee8
3 changed files with 42 additions and 23 deletions

View file

@ -6,6 +6,8 @@ Unreleased
- Drop support for Python 3.9. :pr:`5730` - Drop support for Python 3.9. :pr:`5730`
- Remove previously deprecated code: ``__version__``. :pr:`5648` - Remove previously deprecated code: ``__version__``. :pr:`5648`
- Fix template_filter decorator to correctly register filters and support usage with or without parentheses.
- Improve docstring for `template_filter` decorator for better clarity and examples.
Version 3.1.1 Version 3.1.1
------------- -------------

View file

@ -664,37 +664,30 @@ class App(Scaffold):
def template_filter( def template_filter(
self, name: str | None = None self, name: str | None = None
) -> t.Callable[[T_template_filter], T_template_filter]: ) -> t.Callable[[T_template_filter], T_template_filter]:
"""A decorator that is used to register custom template filter. """A decorator that is used to register custom template filters.
You can specify a name for the filter, otherwise the function You can use this with or without parentheses. Example::
name will be used. Example::
@app.template_filter() @app.template_filter
def reverse(s): def double(x):
return s[::-1] return x * 2
:param name: the optional name of the filter, otherwise the @app.template_filter()
function name will be used. def reverse(s):
return s[::-1]
:param name: the optional name of the filter, otherwise the
function name will be used.
""" """
if callable(name): if callable(name):
func = name func = name
name = func.__name__ # Use function name as default name = func.__name__
self.add_template_filter(func, name=name) # Register filter with Flask self.add_template_filter(func, name=name)
return func # ✅ return original function (not a wrapper)
@wraps(func)
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
def decorator(func: T_template_filter) -> T_template_filter: def decorator(func: T_template_filter) -> T_template_filter:
self.add_template_filter(func, name=name) # Register filter with Flask self.add_template_filter(func, name=name)
return func # ✅ return original function (not a wrapper)
@wraps(func)
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
return decorator return decorator

View file

@ -0,0 +1,24 @@
import pytest
from flask import Flask, render_template_string
def test_template_filter_without_parentheses():
app = Flask(__name__)
@app.template_filter
def double(x):
return x * 2
with app.app_context():
output = render_template_string("{{ 2 | double }}")
assert output == "4"
def test_template_filter_with_parentheses():
app = Flask(__name__)
@app.template_filter()
def triple(x):
return x * 3
with app.app_context():
output = render_template_string("{{ 3 | triple }}")
assert output == "9"