Exemplo n.º 1
0
 def _parse_qblock(self, parser, lineno):
     name = parser.parse_assign_target(name_only=True).name
     body = parser.parse_statements(['name:endqblock'], drop_needle=True)
     return nodes.If(
         nodes.Compare(  # name in __blocks__
             nodes.Const(name),
             [nodes.Operand('in', nodes.Name('__blocks__', 'load'))]),
         body,
         [],  # elif_
         []  # orelse
     ).set_lineno(lineno)
Exemplo n.º 2
0
 def parse_compare(self):
     lineno = self.stream.current.lineno
     expr = self.parse_math1()
     ops = []
     while 1:
         token_type = self.stream.current.type
         if token_type in _compare_operators:
             next(self.stream)
             ops.append(nodes.Operand(token_type, self.parse_math1()))
         elif self.stream.skip_if('name:in'):
             ops.append(nodes.Operand('in', self.parse_math1()))
         elif (self.stream.current.test('name:not')
               and self.stream.look().test('name:in')):
             self.stream.skip(2)
             ops.append(nodes.Operand('notin', self.parse_math1()))
         else:
             break
         lineno = self.stream.current.lineno
     if not ops:
         return expr
     return nodes.Compare(expr, ops, lineno=lineno)
Exemplo n.º 3
0
    def parse(self, parser):
        lineno = next(parser.stream).lineno

        # Get the block selection from the tag argument.
        block_selection = parser.parse_expression()

        # Make "Name" node for "For" node target.
        block_name = nodes.Name('_ext_ob_blknm', 'store')

        # For each block, add an "If" node checking if it matches the target.
        # Also record the original "default" ordering of the blocks.
        blocks = []
        block_names = []
        for node in parser.parse_statements(['name:endorderblocks'],
                                            drop_needle=True):
            if isinstance(node, nodes.Block):
                blocks.append(nodes.If(
                    nodes.Compare(
                        block_name,
                        [nodes.Operand('eq', nodes.Const(node.name))]),
                    [node], []))

                block_names.append(node.name)

        # Make a "For" node iterating over the given block selection.  If the
        # block selection is undefined or None then use the original ordering.
        return nodes.For(
            block_name,
            nodes.CondExpr(
                nodes.And(
                    nodes.Test(block_selection, 'defined',
                               [], [], None, None),
                    nodes.Not(
                        nodes.Test(block_selection, 'none',
                                   [], [], None, None)),
                ),
                block_selection,
                nodes.Tuple([nodes.Const(x) for x in block_names], 'store')),
            blocks, [], None, False)
Exemplo n.º 4
0
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,
    )
Exemplo n.º 5
0
def case(token: "Token", parser: "Parser") -> nodes.Node:
    """The case-when tag {% case x %}{% when y %} ... {% endcase %}

    Args:
        token: The token matches tag name
        parser: The parser

    Returns:
        The parsed node
    """
    lhs = parser.parse_tuple(with_condexpr=False)
    # %}
    if not parser.stream.skip_if("block_end"):
        raise TemplateSyntaxError(  # pragma: no cover
            "Expected 'end of statement block'",
            token.lineno,
        )
    token = next(parser.stream)
    if token.type == "data":
        if token.value.strip():
            raise TemplateSyntaxError(
                "Expected nothing or whitespaces between case and when, "
                f"but got {token}",
                token.lineno,
            )
        token = next(parser.stream)

    if token.type != "block_begin":
        raise TemplateSyntaxError(
            "Expected 'begin of statement block', " f"but got {token}",
            token.lineno,
        )

    token = parser.stream.expect("name:when")
    node = result = nodes.If(lineno=token.lineno)
    while True:
        node.test = nodes.Compare(
            lhs,
            [
                nodes.Operand(
                    "eq",
                    parser.parse_tuple(with_condexpr=False),
                )
            ],
            lineno=token.lineno,
        )
        node.body = parser.parse_statements(
            ("name:when", "name:else", "name:endcase")
        )
        node.elif_ = []
        node.else_ = []
        token = next(parser.stream)
        if token.test("name:when"):
            node = nodes.If(lineno=parser.stream.current.lineno)
            result.elif_.append(node)
            continue
        if token.test("name:else"):
            result.else_ = parser.parse_statements(
                ("name:endcase",), drop_needle=True
            )
        break
    return result