def increment(token: "Token", parser: "Parser") -> List[nodes.Node]: """The increment tag {% increment 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.Add(varnode, nodes.Const(1)), nodes.Const(0), ), lineno=token.lineno, ), nodes.Output([varnode], lineno=token.lineno), ]
def include_relative(token: Token, parser: Parser) -> nodes.Node: """The {% include_relative ... %} tag""" node = nodes.Include(lineno=token.lineno) path = parser.parse_expression() if parser.stream.filename: node.template = nodes.Add( nodes.Add( nodes.Const(os.path.dirname(parser.stream.filename)), nodes.Const(os.path.sep), ), path, ) else: node.template = path node.ignore_missing = False return parser.parse_import_context(node, True)
def parse_add(self): lineno = self.stream.current.lineno left = self.parse_sub() while self.stream.current.type == 'add': next(self.stream) right = self.parse_sub() left = nodes.Add(left, right, lineno=lineno) lineno = self.stream.current.lineno return left
def tablerow( token: "Token", parser: "Parser" ) -> Union[nodes.Node, List[nodes.Node]]: """The tablerow tag {% tablerow ... %} ... {% endtablerow %} Args: token: The token matches tag name parser: The parser Returns: The parsed node """ target = parser.parse_assign_target(extra_end_rules=("name:in", )) parser.stream.expect("name:in") iter_ = parser.parse_tuple( with_condexpr=False, extra_end_rules=("name:cols", "name:limit", "name:offset"), ) cols = parse_tag_args(parser.stream, "cols", token.lineno) limit = parse_tag_args(parser.stream, "limit", token.lineno) offset = parse_tag_args(parser.stream, "offset", token.lineno) if limit and offset: limit = nodes.Add(offset, limit) if limit or offset: iter_ = nodes.Getitem(iter_, nodes.Slice(offset, limit, None), "load") if cols: slice_start = nodes.Mul(nodes.Name("_tablerow_i", "load"), cols) inner_iter = nodes.Getitem( iter_, nodes.Slice( slice_start, nodes.Add(slice_start, cols), None, ), "load", ) else: inner_iter: nodes.Getitem = iter_ inner_body = [ nodes.Output( [ nodes.Const('<td class="col'), nodes.Getattr(nodes.Name("loop", "load"), "index", "load"), nodes.Const('">'), ] ), *parser.parse_statements(("name:endtablerow",), drop_needle=True), nodes.Output([nodes.Const("</td>")]), ] tr_begin = nodes.Output( [ nodes.Const('<tr class="row'), nodes.CondExpr( nodes.Name("loop", "load"), nodes.Getattr(nodes.Name("loop", "load"), "index", "load"), nodes.Const(1), ), nodes.Const('">'), ] ) tr_end = nodes.Output([nodes.Const("</tr>")]) inner_loop = nodes.For( target, inner_iter, inner_body, [], None, False, lineno=token.lineno ) if not cols: return [tr_begin, inner_loop, tr_end] # (iter_ | length) / cols iter_length = nodes.Div( nodes.Filter(iter_, "length", [], [], None, None), cols, ) # float # int(iter_length) iter_length_int = nodes.Filter(iter_length, "int", [], [], None, None) # implement ceil, as jinja's ceil is implemented as round(..., "ceil") # while liquid has a ceil filter # iter_length_int if iter_length == iter_length_int # else iter_length_int + 1 iter_length = nodes.CondExpr( nodes.Compare(iter_length, [nodes.Operand("eq", iter_length_int)]), iter_length_int, nodes.Add(iter_length_int, nodes.Const(1)), ) return nodes.For( nodes.Name("_tablerow_i", "store"), nodes.Call(nodes.Name("range", "load"), [iter_length], [], None, None), [tr_begin, inner_loop, tr_end], [], None, False, lineno=token.lineno, )
def _selected_templates(self, templates, prefixes): return nodes.List([ nodes.Add(prefix, template) for template in templates.items for prefix in prefixes.items ])