def compile_func(parser, token): bits = token.split_contents()[1:] if len(bits) > 2 and bits[-2] == 'as': target_var = bits[-1] bits = bits[:-2] args, kwargs = parse_bits(parser, bits, params, varargs, varkw, defaults, takes_context, function_name) return AssignmentNode(takes_context, args, kwargs, target_var) else: args, kwargs = parse_bits(parser, bits, params, varargs, varkw, defaults, takes_context, function_name) return SimpleNode(takes_context, args, kwargs)
def do_include_with(parser, token): """ Include template with object attributes injected to context. It takes object and template path as arguments. Object should have template_exposed_attributes list defined. .. code-block:: text {% include_with obj 'path/to/included/template.html' %} It is also possible to overvrite / add additional kwaegs. .. code-block:: text {% include_with obj 'path/to/included/template.html' foo='bar'%} """ bits = token.split_contents() if django_version[0] >= 2: options = parse_bits( parser, bits[1:], ['with_object', 'template_name'], False, True, None, [], None, False, 'include_with', ) else: options = parse_bits( parser, bits[1:], ['with_object', 'template_name'], False, True, None, False, 'include_with', ) bits[2] = construct_relative_path(parser.origin.template_name, bits[2]) template_filter = parser.compile_filter(bits[2]) return IncludeWithNode(bits[1], template_filter, extra_context=options[1])
def compile_func(parser, token): bits = token.split_contents()[1:] # When there is an "as" if len(bits) >= 2 and bits[-2] == 'as': target_var = bits[-1] bits = bits[:-2] args, kwargs = parse_bits( parser, bits, params, varargs, varkw, defaults, takes_context, function_name ) return AssignmentNode(function_name, takes_context, args, kwargs, target_var) else: args, kwargs = parse_bits( parser, bits, params, varargs, varkw, defaults, takes_context, function_name ) return SimpleNode(function_name, takes_context, args, kwargs)
def compile_func(parser,token): bits = token.split_contents()[1:] nodelist = parser.parse((f"end{function_name}",)) parser.delete_first_token() args, kwargs = parse_bits( parser, bits, params, varargs, varkw, defaults, kwonly, kwonly_defaults, takes_context, function_name, ) def _func(context,*args,**kwargs): if takes_context: ret = func(context, *args,**kwargs) else: ret = func(*args,**kwargs) return { **ret, "content": nodelist.render(context) } return InclusionNode( _func, True, # takes_context, there are 2 different kinds of context here args, kwargs, filename )
def tabdeck(parser, token): bits = token.split_contents()[1:] args, kwargs = parse_bits(parser, bits, [], 'args', 'kwargs', None, False, 'tabdeck') nodelist = parser.parse(('endtabdeck',)) parser.delete_first_token() # discard the 'endtabdeck' tag return TabDeckNode(nodelist, kwargs)
def parse_bits(parser, bits, params, varargs, varkw, defaults, takes_context, name): from django.template import library return library.parse_bits( parser=parser, bits=bits, params=params, varargs=varargs, varkw=varkw, defaults=defaults, kwonly=(), kwonly_defaults=(), takes_context=takes_context, name=name)
def parse_content(self, parser, token): """ This is called to parse the incoming context. It's return value will be set to self.args, self.kwargs, self.variable """ bits = token.split_contents()[1:] target_var = None if len(bits) >= 2 and bits[-2] == 'as': target_var = bits[-1] bits = bits[:-2] params, varargs, varkw, defaults = inspect.signature(self.component.render) if params[0] == 'context': takes_context = True else: takes_context = False self.takes_context = takes_context function_name = self.component.name args, kwargs = parse_bits( parser, bits, params, varargs, varkw, defaults, takes_context, function_name ) return args, kwargs, target_var
def compile_func(parser, token): bits = token.split_contents()[1:] args, kwargs = parse_bits( parser, bits, params, varargs, varkw, defaults, kwonly, kwonly_defaults, takes_context, function_name, ) kwargs[context_text_name] = parser.parse((end_tag_name, tag_name)) parser.delete_first_token() return CustomNode( func, takes_context, args, kwargs, filename, )
def compile_func(parser, token): bits = token.split_contents()[1:] target_var = None if len(bits) >= 2 and bits[-2] == 'as': target_var = bits[-1] bits = bits[:-2] + ["_asvar=True"] args, kwargs = parse_bits(parser, bits, params, varargs, varkw, defaults, takes_context, function_name) return SimpleNode(func, takes_context, args, kwargs, target_var)
def __init__(self, parser, token, func, template_name, takes_context=True): self.template_name = template_name params, varargs, varkw, defaults, kwonly, kwonly_defaults, _ = getfullargspec(func) bits = token.split_contents() args, kwargs = parse_bits( parser, bits[1:], params, varargs, varkw, defaults, kwonly, kwonly_defaults, takes_context, bits[0], ) super().__init__(func, takes_context, args, kwargs, filename=None)
def compile_func(parser, token): bits = token.split_contents()[1:] args, kwargs = parse_bits( parser, bits, params, varargs, varkw, defaults, kwonly, kwonly_defaults, takes_context, function_name, ) return InclusionNode( func, takes_context, args, kwargs, filename )
def _compile(parser, token): # content nodelist = parser.parse(('end' + name,)) parser.delete_first_token() # args bits = token.split_contents()[1:] args, kwargs = parse_bits(parser, bits, params, varargs, varkw, defaults, takes_context=takes_context, name=name) return CachedNode(func, takes_context, args, kwargs, nodelist)
def compile_func(parser,token): bits = token.split_contents()[1:] # TODO: figure out if this is lazy/thread-safe # parser.delete_first_token() token = parser.next_token() nodelists_by_name = {} end_tag_token = f"end{function_name}" blocks_left = len(block_names) + 1 # +1 for the eng_tag_token while blocks_left: useless = parser.parse(("blockarg",end_tag_token)) token = parser.next_token() if token.contents.startswith(end_tag_token): blocks_left = 0 for name in block_names: if name not in nodelists_by_name: nodelists_by_name[name] = None else: # {% block_arg <block_name> %} block_name = token.split_contents()[1][1:-1] # TODO: make it clear that this needs to be a literal string ""/ '' and not a variable block_nodelist = parser.parse(f"endblockarg") nodelists_by_name[block_name] = block_nodelist token = parser.next_token() blocks_left = blocks_left - 1 args, kwargs = parse_bits( parser, bits, params, varargs, varkw, defaults, kwonly, kwonly_defaults, takes_context, function_name, ) def _func(context,*args,**kwargs): if takes_context: ret = func(context, *args,**kwargs) else: ret = func(*args,**kwargs) return { **ret, **{ name: nodelist and nodelist.render(context) for (name,nodelist) in nodelists_by_name.items() } } return InclusionNode( _func, True, # takes_context, there are 2 different kinds of context here args, kwargs, filename )
def compile_func(parser, token): bits = token.split_contents()[1:] if len(bits) < 2 or bits[-2] != 'as': target_var = None else: target_var = bits[-1] bits = bits[:-2] args, kwargs = parse_bits(parser, bits, params, varargs, varkw, defaults, kwonly, kwonly_defaults, takes_context, function_name) return AssignmentNode(takes_context, args, kwargs, target_var)
def do_component(parser, token): """ {% component_block "name" variable="value" variable2="value2" ... %} """ bits = token.split_contents() tag_args, tag_kwargs = parse_bits( parser=parser, bits=bits, params=["tag_name", "component_name"], takes_context=False, name="component_block", **PARSE_BITS_DEFAULTS ) tag_name = tag_args.pop(0) if len(bits) < 2: raise TemplateSyntaxError( "Call the '%s' tag with a component name as the first parameter" % tag_name ) component_name = bits[1] if not component_name.startswith(('"', "'")) or not component_name.endswith( ('"', "'") ): raise TemplateSyntaxError( "Component name '%s' should be in quotes" % component_name ) component_name = component_name.strip('"\'') component_class = registry.get(component_name) component = component_class() extra_context = {} if len(bits) > 2: extra_context = component.context(**token_kwargs(bits[2:], parser)) slots_filled = NodeList() tag_name = bits[0] while tag_name != "endcomponent_block": token = parser.next_token() if token.token_type != TokenType.BLOCK: continue tag_name = token.split_contents()[0] if tag_name == "slot": slots_filled += do_slot(parser, token, component=component) elif tag_name == "endcomponent_block": break return ComponentNode(component, extra_context, slots_filled)
def tab(parser, token): bits = token.split_contents()[1:] args, kwargs = parse_bits(parser, bits, ['heading_expr'], 'args', 'kwargs', None, False, 'tab') if len(args) != 1: raise template.TemplateSyntaxError("The 'tab' tag requires exactly one unnamed argument (the tab heading).") heading_expr = args[0] nodelist = parser.parse(('endtab',)) parser.delete_first_token() # discard the 'endtab' tag return TabNode(nodelist, heading_expr, kwargs)
def generic_tag_compiler(parser, token, params, varargs, varkw, defaults, name, takes_context, node_class): """ Returns a template.Node subclass. This got inlined into django.template.library since Django since 1.9, this here is a copypasta replacement: https://github.com/django/django/blob/stable/1.8.x/django/template/base.py#L1089 """ bits = token.split_contents()[1:] args, kwargs = parse_bits(parser, bits, params, varargs, varkw, defaults, takes_context, name) return node_class(takes_context, args, kwargs)
def compile_func(parser, token): takes_context = True bits = token.split_contents()[1:] args, kwargs = library.parse_bits(parser, bits, params, varargs, varkw, defaults, takes_context, tag_name) nodelist = parser.parse(('end' + tag_name,)) parser.delete_first_token() try: # Django<1.9 return InlineCompileNode(nodelist, takes_context, args, kwargs) except TypeError: # Django>=1.9 return InlineCompileNode(nodelist, func, takes_context, args, kwargs)
def __init__(self, parser, token, func, template_name, takes_context=True): self.template_name = template_name params, varargs, varkw, defaults, kwonly, kwonly_defaults, _ = getfullargspec(func) if len(params) > 0 and params[0] == 'self': params = params[1:] # ignore 'self' bits = token.split_contents() args, kwargs = parse_bits( parser, bits[1:], params, varargs, varkw, defaults, kwonly, kwonly_defaults, takes_context, bits[0] ) super().__init__( func=func, takes_context=takes_context, args=args, kwargs=kwargs, filename=None )
def compile_func(parser, token): takes_context = True bits = token.split_contents()[1:] args, kwargs = library.parse_bits(parser, bits, params, varargs, varkw, defaults, takes_context, tag_name) nodelist = parser.parse(('end' + tag_name, )) parser.delete_first_token() try: # Django<1.9 return InlineCompileNode(nodelist, takes_context, args, kwargs) except TypeError: # Django>=1.9 return InlineCompileNode(nodelist, func, takes_context, args, kwargs)
def compile_func(parser, token): bits = token.split_contents()[1:] args, kwargs = parse_bits( parser, bits, params, varargs, varkw, defaults, kwonly, kwonly_defaults, takes_context, function_name, ) return InclusionNode(func, takes_context, args, kwargs, filename)
def __init__(self, parser, token, func, template_name, takes_context=True): self.template_name = template_name params, varargs, varkw, defaults, kwonly, kwonly_defaults, _ = getfullargspec( func) if len(params) > 0 and params[0] == 'self': params = params[1:] # ignore 'self' bits = token.split_contents() args, kwargs = parse_bits(parser, bits[1:], params, varargs, varkw, defaults, kwonly, kwonly_defaults, takes_context, bits[0]) super().__init__(func=func, takes_context=takes_context, args=args, kwargs=kwargs, filename=None)
def _compile(parser, token): # content nodelist = parser.parse(('end' + name, )) parser.delete_first_token() # args bits = token.split_contents()[1:] args, kwargs = parse_bits(parser, bits, params, varargs, varkw, defaults, takes_context=takes_context, name=name) return CachedNode(func, takes_context, args, kwargs, nodelist)
def handler_parser(cls, parser, token, name, handler): """ Returns a wrapped partial of ``handler`` with the arguments supplied by the calling template. Errors will bubble up for invalid or missing arguments to the handler. """ params, varargs, varkw, defaults = getargspec(handler) wrapped = cls.wrap_handler(handler) params.pop(0) # removes inspected 'self' from required tag arguments special_params = ['context', 'nodelist'] # Rendering params that aren't given by template for param in special_params: if param in params: params.pop(params.index(param)) bits = token.split_contents()[1:] args, kwargs = parse_bits(parser, bits, params, varargs, varkw, defaults, None, name) kwargs.update(zip(params, args)) return partial(wrapped, **kwargs)
def parse_component_with_args(parser, bits, tag_name): tag_args, tag_kwargs = parse_bits( parser=parser, bits=bits, params=["tag_name", "name"], takes_context=False, name=tag_name, varargs=True, varkw=[], defaults=None, kwonly=[], kwonly_defaults=None, ) assert ( tag_name == tag_args[0].token ), "Internal error: Expected tag_name to be {}, but it was {}".format( tag_name, tag_args[0].token) if ( len(tag_args) > 1 ): # At least one position arg, so take the first as the component name component_name = tag_args[1].token context_args = tag_args[2:] context_kwargs = tag_kwargs else: # No positional args, so look for component name as keyword arg try: component_name = tag_kwargs.pop("name").token context_args = [] context_kwargs = tag_kwargs except IndexError: raise TemplateSyntaxError( "Call the '%s' tag with a component name as the first parameter" % tag_name) if not is_wrapped_in_quotes(component_name): raise TemplateSyntaxError("Component name '%s' should be in quotes" % component_name) trimmed_component_name = component_name[1:-1] component_class = registry.get(trimmed_component_name) component = component_class(trimmed_component_name) return component, context_args, context_kwargs
def flowurl(parser, token): """ Returns flow url:: {% flowurl ref [urlname] [user=] [as varname]%} Usage examples:: {% flowurl 'app_label/FlowCls' 'viewflow:index' %} {% flowurl flow_cls 'index' as index_url %} {% flowurl process 'index' %} {% flowurl process 'details' %} {% flowurl task 'assign' user=request.user %} {% flowurl task user=request.user %} """ def geturl(ref, url_name=None, user=None): if isinstance(ref, Flow): url_ref = '{}:{}'.format(ref.namespace, url_name if url_name else 'index') return reverse(url_ref) elif isinstance(ref, AbstractProcess): kwargs, url_ref = {}, '{}:{}'.format( ref.flow_cls.instance.namespace, url_name if url_name else 'index') if url_name in ['details', 'cancel']: kwargs['process_pk'] = ref.pk return reverse(url_ref, kwargs=kwargs) elif isinstance(ref, AbstractTask): return ref.flow_task.get_task_url( ref, url_type=url_name if url_name else 'guess', user=user) else: try: app_label, flow_cls_path = ref.split('/') except ValueError: raise TemplateSyntaxError( "Flow reference string should looks like 'app_label/FlowCls' but '{}'" .format(ref)) app_package = get_app_package(app_label) if app_package is None: raise TemplateSyntaxError("{} app not found".format(app_label)) flow_cls = import_by_path('{}.flows.{}'.format( app_package, flow_cls_path)) url_ref = '{}:{}'.format(flow_cls.instance.namespace, url_name if url_name else 'index') return reverse(url_ref) class URLNode(TagHelperNode): def __init__(self, args, kwargs, target_var): super(URLNode, self).__init__(func=None, takes_context=False, args=args, kwargs=kwargs) self.target_var = target_var def render(self, context): resolved_args, resolved_kwargs = self.get_resolved_arguments( context) url = geturl(*resolved_args, **resolved_kwargs) if self.target_var: context[self.target_var] = url return '' else: return url bits = token.split_contents()[1:] target_var = None if bits[-2] == 'as': target_var = bits[-1] bits = bits[:-2] params, varargs, varkw, defaults = getargspec(geturl) args, kwargs = parse_bits(parser, bits, params, varargs, varkw, defaults, takes_context=False, name='flowurl') return URLNode(args, kwargs, target_var)