def comment(token: "Token", parser: "Parser") -> nodes.Node: """The comment tag {% comment %} ... {% endcomment %} This tag accepts an argument, which is the prefix to be used for each line in the body. If no prefix provided, the entire body will be ignored (works as the one from liquid) Args: token: The token matches tag name parser: The parser Returns: The parsed node """ if parser.stream.current.type is TOKEN_BLOCK_END: # no args provided, ignore whatever parser.parse_statements(("name:endcomment", ), drop_needle=True) return nodes.Output([], lineno=token.lineno) args = parser.parse_expression() body = parser.parse_statements(("name:endcomment", ), drop_needle=True) body = decode_raw(body[0].nodes[0].data) body_parts = body.split("\n", 1) if not body_parts[0]: body = "" if len(body_parts) < 2 else body_parts[1] out = [nodes.Const(f"{args.value} {line}\n") for line in body.splitlines()] return nodes.Output(out, lineno=token.lineno)
def parse(self, parser): lineno = next(parser.stream).lineno parts = [parser.stream.expect('name').value] while parser.stream.current.type != 'block_end': parser.stream.expect('dot') parts.append(parser.stream.expect('name').value) body = parser.parse_statements(['name:endeditable'], drop_needle=True) call = self.call_method( '_editable_loader', [nodes.Name(parts[-2], 'load'), nodes.Const(parts[-1])]) output_nodes = [ nodes.Output([ nodes.MarkSafe( nodes.TemplateData('<div class="editable-container">')), nodes.MarkSafe( nodes.TemplateData('<div class="editable-content">')) ]) ] output_nodes.extend(body) output_nodes.extend([ nodes.Output([nodes.MarkSafe(nodes.TemplateData('</div>'))]), nodes.Output([nodes.MarkSafe(call)]), nodes.Output([nodes.MarkSafe(nodes.TemplateData('</div>'))]) ]) block_name = '%s_%s_%d' % (parts[-2], parts[-1], random.randint( 0, 500)) return nodes.Block(block_name, output_nodes, True)
def parse(self, parser): lineno = next(parser.stream).lineno next_token = parser.stream.look() # if there are parameters if next_token.type == "comma": args = [parser.parse_expression()] if parser.stream.skip_if('comma'): args.append(parser.parse_expression()) else: raise TemplateSyntaxError("Missing Lorem Ipsum generator parameter: kind", lineno) if args[1].value not in self.GENERATORS: raise TemplateSyntaxError( "Supported Lorem Ipsum generator kinds are: %s" % ", ".join(self.GENERATORS.keys()), lineno ) else: # if no parameters were supplied args = [nodes.Const(1), nodes.Const("paragraphs")] return nodes.Output( [self.call_method("_lipsum", args)], lineno=lineno )
def parse(self, parser): lineno = parser.stream.expect('name:meld').lineno component = parser.parse_expression() call = self.call_method('_render', [component], lineno=lineno) return nodes.Output([nodes.MarkSafe(call)]).set_lineno(lineno)
def parse(self, parser): lineno = next(parser.stream).lineno length = parser.stream.expect(lexer.TOKEN_INTEGER).value secret = nodes.Const(self._get_secret(length)) return nodes.Output([secret], lineno=lineno)
def parse(self, parser): lineno = next(parser.stream).lineno node = parser.parse_expression() if parser.stream.skip_if('comma'): datetime_format = parser.parse_expression() else: datetime_format = nodes.Const(None) if isinstance(node, nodes.Add): call_method = self.call_method( '_datetime', [node.left, nodes.Const('+'), node.right, datetime_format], lineno=lineno, ) elif isinstance(node, nodes.Sub): call_method = self.call_method( '_datetime', [node.left, nodes.Const('-'), node.right, datetime_format], lineno=lineno, ) else: call_method = self.call_method( '_now', [node, datetime_format], lineno=lineno, ) return nodes.Output([call_method], lineno=lineno)
def test_basics(): for_loop = nodes.For( nodes.Name('foo', 'store'), nodes.Name('seq', 'load'), [nodes.Output([nodes.Name('foo', 'load')])], [], None, False) tmpl = nodes.Template([ nodes.Assign( nodes.Name('foo', 'store'), nodes.Name('bar', 'load')), for_loop]) sym = symbols_for_node(tmpl) assert sym.refs == { 'foo': 'l_0_foo', 'bar': 'l_0_bar', 'seq': 'l_0_seq', } assert sym.loads == { 'l_0_foo': ('undefined', None), 'l_0_bar': ('resolve', 'bar'), 'l_0_seq': ('resolve', 'seq'), } sym = symbols_for_node(for_loop, sym) assert sym.refs == { 'foo': 'l_1_foo', } assert sym.loads == { 'l_1_foo': ('param', None), }
def parse(self, parser): """Main method to render data into the template.""" lineno = next(parser.stream).lineno # TODO: add {% gitcommit 'short' %} feature result = self.call_method('_commit_hash', [], lineno=lineno) return nodes.Output([result], lineno=lineno)
def parse(self, parser): node = nodes.ExprStmt(lineno=next(parser.stream).lineno) node.node = parser.parse_tuple() res = requests.get(self.environment.context["environment"]["config"] ["internal"]["juggler"]["path"] + f'/api/vars?key={node.node.value}').json()['value'] return nodes.Output([Const(res)])
def parse(self, parser): lineno = next(parser.stream).lineno # assume first token is the stage module value args = [parser.parse_expression()] # check if we have a comma next if parser.stream.skip_if('comma'): # check if we have variables assignment if parser.stream.current.type == 'name': # returns the current token only if all goes well name = parser.stream.expect('name') if name.value == 'variables': if parser.stream.skip_if('assign'): args.append(parser.parse_expression()) # if the name of variable is not "variables" ignore else: if parser.stream.skip_if('assign'): next(parser.stream) args.append(nodes.Const(None)) # if there is nothing after comma, variables is assigned to None, default variables will be used else: args.append(nodes.Const(None)) call_method = self.call_method('fetch_module', args) return nodes.Output([call_method], lineno=lineno)
def _make_node(self, singular, plural, variables, plural_expr, vars_referenced, num_called_num): """Generates a useful node from the data provided.""" if not vars_referenced and not self.environment.newstyle_gettext: singular = singular.replace('%%', '%') if plural: plural = plural.replace('%%', '%') if plural_expr is None: gettext = nodes.Name('gettext', 'load') node = nodes.Call(gettext, [nodes.Const(singular)], [], None, None) else: ngettext = nodes.Name('ngettext', 'load') node = nodes.Call( ngettext, [nodes.Const(singular), nodes.Const(plural), plural_expr], [], None, None) if self.environment.newstyle_gettext: for key, value in variables.iteritems(): if num_called_num and key == 'num': continue node.kwargs.append(nodes.Keyword(key, value)) else: node = nodes.MarkSafeIfAutoescape(node) if variables: node = nodes.Mod( node, nodes.Dict([ nodes.Pair(nodes.Const(key), value) for key, value in variables.items() ])) return nodes.Output([node])
def parse_trs(self, parser, lineno): lineno = lineno args = [parser.parse_expression()] variables = {} while parser.stream.current.type != 'block_end': parser.stream.expect('comma') name = parser.stream.expect('name') if name.value in variables: parser.fail('translatable variable %r defined twice.' % name.value, name.lineno, exc=TemplateAssertionError) if parser.stream.current.type == 'assign': next(parser.stream) variables[name.value] = var = parser.parse_expression() else: variables[name.value] = var = nodes.Name(name.value, 'load') kwargs = [] if 'description' in variables: kwargs = [ nodes.Keyword('description', variables.get('description', '')) ] return nodes.Output([ nodes.Call(nodes.Name('translate_trs', 'load'), args, kwargs, None, None) ]).set_lineno(lineno)
def parse(self, parser): stream = parser.stream lineno = six.next(stream).lineno args = [] kwargs = [] while stream.current.type != 'block_end': if stream.current.type == 'name' and \ stream.look().type == 'assign': key = nodes.Const(six.next(stream).value) stream.skip() value = parser.parse_expression() kwargs.append(nodes.Pair(key, value, lineno=value.lineno)) else: if args: parser.fail('jsdir tag takes only one non-keyword ' 'argument') if kwargs: parser.fail('Args cannot be provided after kwargs', parser.stream.current.lineno) args.append(parser.parse_expression()) return nodes.Output([ self.call_method('get_tags', args=[nodes.List(args), nodes.Dict(kwargs)]) ]).set_lineno(lineno)
def decrement(token: "Token", parser: "Parser") -> List[nodes.Node]: """The decrement tag {% decrement x %} Args: token: The token matches tag name parser: The parser Returns: The parsed node """ variable = parser.stream.expect("name") varname = f"_liquid_xcrement_{variable.value}" varnode = nodes.Name(varname, "load") return [ nodes.Assign( nodes.Name(varname, "store"), nodes.CondExpr( nodes.Test(varnode, "defined", [], [], None, None), nodes.Sub(varnode, nodes.Const(1)), nodes.Const(-1), ), lineno=token.lineno, ), nodes.Output([varnode], lineno=token.lineno), ]
def parse(self, parser): tag = parser.stream.next() attrs = self.parse_attrs(parser) return nodes.Output( [self.call_method('_call_simple_tag', args=[attrs])])
def parse(self, parser): tag = parser.stream.next() attrs = self.parse_attrs(parser) attrs = nodes.Dict([nodes.Pair(nodes.Const(k), v) for k,v in attrs.items()]) return nodes.Output([self.call_method('_call_simple_tag', args=[attrs])])
def parse(self, parser): tag = next(parser.stream) attrs = self.parse_attrs(parser, with_context=True) return nodes.Output( [self.call_method('_call_simple_tag', args=[attrs])])
def test_basics(): for_loop = nodes.For( nodes.Name("foo", "store"), nodes.Name("seq", "load"), [nodes.Output([nodes.Name("foo", "load")])], [], None, False, ) tmpl = nodes.Template([ nodes.Assign(nodes.Name("foo", "store"), nodes.Name("bar", "load")), for_loop ]) sym = symbols_for_node(tmpl) assert sym.refs == { "foo": "l_0_foo", "bar": "l_0_bar", "seq": "l_0_seq", } assert sym.loads == { "l_0_foo": ("undefined", None), "l_0_bar": ("resolve", "bar"), "l_0_seq": ("resolve", "seq"), } sym = symbols_for_node(for_loop, sym) assert sym.refs == { "foo": "l_1_foo", } assert sym.loads == { "l_1_foo": ("param", None), }
def parse(self, parser): lineno = next(parser.stream).lineno # get the context context = nodes.ContextReference() # get the arguments args = [context] try: while True: args.append(parser.parse_expression()) except TemplateSyntaxError: pass # no more arguments # get the tag_name for use in looking up callable self.active_tag = parser._tag_stack[-1] args.insert(0, nodes.Const(self.active_tag)) # create the node node = self.call_method('_invoke_tag', args=args, lineno=lineno) return nodes.Output( [node], lineno=lineno )
def parse(self, parser): lineno = next(parser.stream).lineno # parase key, path and mount key = parser.parse_expression() parser.stream.skip_if('comma') if parser.stream.skip_if('name:path'): parser.stream.skip(1) path = parser.parse_expression() else: path = "" parser.stream.skip_if('comma') if parser.stream.skip_if('name:mount'): parser.stream.skip(1) mount = parser.parse_expression() else: mount = "secret" parser.stream.skip_if('comma') if parser.stream.skip_if('name:to_file'): parser.stream.skip(1) to_file = parser.parse_expression() else: to_file = None args = [path, key, mount] if to_file: args.append(to_file) return nodes.Output([ nodes.MarkSafeIfAutoescape(self.call_method('get_secret', args)) ]).set_lineno(lineno)
def import_(env: "Environment", token: "Token", parser: "Parser") -> nodes.Node: """The import_ tag {% import_ ... %} Name it 'import_' so the 'import' tag from jinja can still work Args: env: The environment token: The token matches tag name parser: The parser Returns: The parsed node """ pieces = ["import"] pieces_append = pieces.append while True: token = next(parser.stream) pieces_append(str(token.value)) if parser.stream.current.type is TOKEN_BLOCK_END: break body = " ".join(pieces) code = compile(body, "<liquid-import_-tag>", mode="exec") exec(code, env.globals) return nodes.Output([], lineno=token.lineno)
def parse_tml_language_selector(self, parser, lineno): args = parser.parse_expression() variables = {} while parser.stream.current.type != 'block_end': parser.stream.expect('comma') name = parser.stream.expect('name') if name.value in variables: parser.fail('translatable variable %r defined twice.' % name.value, name.lineno, exc=TemplateAssertionError) if parser.stream.current.type == 'assign': next(parser.stream) variables[name.value] = var = parser.parse_expression() else: variables[name.value] = var = nodes.Name(name.value, 'load') data = { 'type': args.value } if 'opts' in variables: data['opts'] = variables.get('opts', '').value else: data['opts'] = "" output = self.environment.from_string(SYSTEM_TEMPLATES['language_selector']).render(type=data['type'], opts=data['opts']) return nodes.Output([nodes.Const(do_mark_safe(output))]).set_lineno(lineno)
def _make_node(self, singular, plural, variables, plural_expr): """Generates a useful node from the data provided.""" # singular only: if plural_expr is None: gettext = nodes.Name('gettext', 'load') node = nodes.Call(gettext, [nodes.Const(singular)], [], None, None) # singular and plural else: ngettext = nodes.Name('ngettext', 'load') node = nodes.Call(ngettext, [ nodes.Const(singular), nodes.Const(plural), plural_expr ], [], None, None) # mark the return value as safe if we are in an # environment with autoescaping turned on if self.environment.autoescape: node = nodes.MarkSafe(node) if variables: node = nodes.Mod(node, variables) return nodes.Output([node])
def parse_tml_inline(self, parser, lineno): caller=""; while parser.stream.current.type != 'block_end': caller = parser.parse_expression().value context = get_current_context() agent_config = dict((k, v) for k, v in six.iteritems(CONFIG.get('agent', {}))) agent_host = agent_config.get('host', CONFIG.agent_host()) if agent_config.get('cache', None): t = ts() t -= (t % agent_config['cache']) agent_host += "?ts=%s" % t agent_config['locale'] = context.locale agent_config['source'] = context.source agent_config['css'] = context.application.css agent_config['sdk'] = full_version() languages = agent_config.setdefault('languages', []) for language in context.application.languages: languages.append({ 'locale': language.locale, 'native_name': language.native_name, 'english_name': language.english_name, 'flag_url': language.flag_url}) data = { 'agent_config': dumps(agent_config), 'agent_host': agent_host, 'application_key': context.application.key, 'caller': caller, 'force_injection': agent_config.get('force_injection', False) } output = self.environment.from_string(SYSTEM_TEMPLATES['inline']).render(data=data) return nodes.Output([nodes.Const(do_mark_safe(output))]).set_lineno(lineno)
def parse(self, parser): stream = parser.stream tag = next(stream) # get arguments args = [] kwargs = [] while not stream.current.test_any('block_end'): if args or kwargs: stream.expect('comma') if stream.current.test('name') and stream.look().test('assign'): key = nodes.Const(next(stream).value) stream.skip() value = parser.parse_expression() kwargs.append(nodes.Pair(key, value, lineno=key.lineno)) else: args.append(parser.parse_expression()) def make_call_node(*kw): return self.call_method('_call', args=[ nodes.List(args), nodes.Dict(kwargs), ], kwargs=kw) return nodes.Output([make_call_node()]).set_lineno(tag.lineno)
def parse(self, parser): lineno = next(parser.stream).lineno # get the first parameter: the relative URL of the asset file args = [parser.parse_expression()] return nodes.Output([self.call_method('_asset', args)], lineno=lineno)
def parse(self, parser): lineno = next(parser.stream).lineno path = parser.parse_expression() call = self.call_method('_sass_src_support', [path, nodes.Const(parser.filename)]) return nodes.Output([call], lineno=lineno)
def parse(self, parser): return nodes.Output([self.call_method('_dump', [ nodes.EnvironmentAttribute('sandboxed'), self.attr('ext_attr'), nodes.ImportedName(__name__ + '.importable_object'), nodes.ContextReference() ])]).set_lineno(next(parser.stream).lineno)
def parse_print(self): node = nodes.Output(lineno=next(self.stream).lineno) node.nodes = [] while self.stream.current.type != 'block_end': if node.nodes: self.stream.expect('comma') node.nodes.append(self.parse_expression()) return node
def parse(self, parser): lineno = parser.stream.expect('name:csrf_token').lineno call = self.call_method( '_render', [nodes.Name('csrf_token', 'load', lineno=lineno)], lineno=lineno ) return nodes.Output([nodes.MarkSafe(call)])