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.
This commit is contained in:
Baptiste Mispelon 2022-01-10 08:31:43 +01:00 committed by GitHub
parent 3430093a46
commit 3d7ac6420c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 14 additions and 20 deletions

View File

@ -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
###################

View File

@ -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):