1
Fork 0

Update simple tag implementation from Django PR

This commit is contained in:
Jake Howard 2024-08-24 16:26:46 +01:00
parent 5044f6d822
commit 15fd589c6b
Signed by: jake
GPG key ID: 57AFB45680EDD477

View file

@ -1,5 +1,6 @@
from inspect import getfullargspec, unwrap from inspect import getfullargspec, unwrap
from django.template.library import parse_bits, SimpleNode from django.template.library import parse_bits, SimpleNode
from django.template.exceptions import TemplateSyntaxError
from functools import wraps from functools import wraps
class SimpleBlockNode(SimpleNode): class SimpleBlockNode(SimpleNode):
@ -9,43 +10,77 @@ class SimpleBlockNode(SimpleNode):
def get_resolved_arguments(self, context): def get_resolved_arguments(self, context):
resolved_args, resolved_kwargs = super().get_resolved_arguments(context) resolved_args, resolved_kwargs = super().get_resolved_arguments(context)
resolved_args.insert(1 if self.takes_context else 0, self.nodelist.render(context))
# Restore the "content" argument.
# It will move depending on whether takes_context was passed.
resolved_args.insert(
1 if self.takes_context else 0, self.nodelist.render(context)
)
return resolved_args, resolved_kwargs return resolved_args, resolved_kwargs
def simple_block_tag(register, takes_context=None, name=None): def simple_block_tag(register, takes_context=None, name=None):
def dec(func): def dec(func):
argspec = getfullargspec(unwrap(func)) (
params,
varargs,
varkw,
defaults,
kwonly,
kwonly_defaults,
_,
) = getfullargspec(unwrap(func))
function_name = name or func.__name__ function_name = name or func.__name__
@wraps(func) @wraps(func)
def tag_compiler(parser, token): def compile_func(parser, token):
tag_params = params.copy()
if takes_context:
if len(tag_params) >= 2 and tag_params[1] == "content":
del tag_params[1]
else:
raise TemplateSyntaxError(
f"'{function_name}' is decorated with takes_context=True so"
" it must have a first argument of 'context' and a second "
"argument of 'content'"
)
else:
if tag_params and tag_params[0] == "content":
del tag_params[0]
else:
raise TemplateSyntaxError(
f"'{function_name}' must have a first argument of 'content'"
)
bits = token.split_contents()[1:] bits = token.split_contents()[1:]
target_var = None target_var = None
if len(bits) >= 2 and bits[-2] == "as": if len(bits) >= 2 and bits[-2] == "as":
target_var = bits[-1] target_var = bits[-1]
bits = bits[:-2] bits = bits[:-2]
params = argspec.args nodelist = parser.parse((f"end{function_name}",))
del params[1 if takes_context else 0] parser.delete_first_token()
args, kwargs = parse_bits( args, kwargs = parse_bits(
parser=parser, parser,
bits=bits, bits,
params=params, tag_params,
varargs=argspec.varargs, varargs,
varkw=argspec.varkw, varkw,
defaults=argspec.defaults, defaults,
kwonly=argspec.kwonlyargs, kwonly,
kwonly_defaults=argspec.kwonlydefaults, kwonly_defaults,
takes_context=takes_context, takes_context,
name=function_name function_name,
) )
nodelist = parser.parse((f'end{function_name}',)) return SimpleBlockNode(
parser.delete_first_token() nodelist, func, takes_context, args, kwargs, target_var
return SimpleBlockNode(nodelist, func, takes_context, args, kwargs, target_var) )
register.tag(function_name, tag_compiler) register.tag(function_name, compile_func)
return func return func
return dec return dec