summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBaptiste Mispelon <bmispelon@gmail.com>2022-01-10 08:31:43 +0100
committerGitHub <noreply@github.com>2022-01-10 08:31:43 +0100
commit3d7ac6420c0ff23305bc50c69c419c4ed5d2a838 (patch)
tree188d8a22bf5902b43ee9f9a6e1b725562793d051
parent3430093a4698b640aa9e501ce2a02e090e77f7ae (diff)
Simplified @stringfilter decorator and Library with unwrap().
Nowadays we can use inspect.unwrap() to retrieve the innermost function object when needed, and most of the uses of _decorated_function were to access the original __name__ which is not needed because @functools.wraps sets that attribute correctly.
-rw-r--r--django/template/defaultfilters.py22
-rw-r--r--django/template/library.py12
2 files changed, 14 insertions, 20 deletions
diff --git a/django/template/defaultfilters.py b/django/template/defaultfilters.py
index 0813cc9dad..f78a96e3eb 100644
--- a/django/template/defaultfilters.py
+++ b/django/template/defaultfilters.py
@@ -4,6 +4,7 @@ import re
import types
from decimal import ROUND_HALF_UP, Context, Decimal, InvalidOperation
from functools import wraps
+from inspect import unwrap
from operator import itemgetter
from pprint import pformat
from urllib.parse import quote
@@ -37,20 +38,15 @@ def stringfilter(func):
Decorator for filters which should only receive strings. The object
passed as the first positional argument will be converted to a string.
"""
- def _dec(*args, **kwargs):
- args = list(args)
- args[0] = str(args[0])
- if (isinstance(args[0], SafeData) and
- getattr(_dec._decorated_function, 'is_safe', False)):
- return mark_safe(func(*args, **kwargs))
- return func(*args, **kwargs)
+ @wraps(func)
+ def _dec(first, *args, **kwargs):
+ first = str(first)
+ result = func(first, *args, **kwargs)
+ if isinstance(first, SafeData) and getattr(unwrap(func), 'is_safe', False):
+ result = mark_safe(result)
+ return result
- # Include a reference to the real function (used to check original
- # arguments by the template parser, and to bear the 'is_safe' attribute
- # when multiple decorators are applied).
- _dec._decorated_function = getattr(func, '_decorated_function', func)
-
- return wraps(func)(_dec)
+ return _dec
###################
diff --git a/django/template/library.py b/django/template/library.py
index be45331309..06ea5f1ad8 100644
--- a/django/template/library.py
+++ b/django/template/library.py
@@ -48,7 +48,7 @@ class Library:
)
def tag_function(self, func):
- self.tags[getattr(func, "_decorated_function", func).__name__] = func
+ self.tags[func.__name__] = func
return func
def filter(self, name=None, filter_func=None, **flags):
@@ -83,8 +83,7 @@ class Library:
setattr(filter_func, attr, value)
# set the flag on the innermost decorated function
# for decorators that need it, e.g. stringfilter
- if hasattr(filter_func, "_decorated_function"):
- setattr(filter_func._decorated_function, attr, value)
+ setattr(unwrap(filter_func), attr, value)
filter_func._filter_name = name
return filter_func
else:
@@ -94,8 +93,7 @@ class Library:
)
def filter_function(self, func, **flags):
- name = getattr(func, "_decorated_function", func).__name__
- return self.filter(name, func, **flags)
+ return self.filter(func.__name__, func, **flags)
def simple_tag(self, func=None, takes_context=None, name=None):
"""
@@ -107,7 +105,7 @@ class Library:
"""
def dec(func):
params, varargs, varkw, defaults, kwonly, kwonly_defaults, _ = getfullargspec(unwrap(func))
- function_name = (name or getattr(func, '_decorated_function', func).__name__)
+ function_name = (name or func.__name__)
@functools.wraps(func)
def compile_func(parser, token):
@@ -144,7 +142,7 @@ class Library:
"""
def dec(func):
params, varargs, varkw, defaults, kwonly, kwonly_defaults, _ = getfullargspec(unwrap(func))
- function_name = (name or getattr(func, '_decorated_function', func).__name__)
+ function_name = name or func.__name__
@functools.wraps(func)
def compile_func(parser, token):