Ejemplo n.º 1
0
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),
    }
Ejemplo n.º 2
0
def test_if_branching_multi_scope():
    for_loop = nodes.For(
        nodes.Name("item", "store"),
        nodes.Name("seq", "load"),
        [
            nodes.If(
                nodes.Name("expression", "load"),
                [nodes.Assign(nodes.Name("x", "store"), nodes.Const(42))],
                [],
                [],
            ),
            nodes.Include(nodes.Const("helper.html"), True, False),
        ],
        [],
        None,
        False,
    )

    tmpl = nodes.Template(
        [nodes.Assign(nodes.Name("x", "store"), nodes.Const(23)), for_loop])

    tmpl_sym = symbols_for_node(tmpl)
    for_sym = symbols_for_node(for_loop, tmpl_sym)
    assert for_sym.stores == set(["item", "x"])
    assert for_sym.loads == {
        "l_1_x": ("alias", "l_0_x"),
        "l_1_item": ("param", None),
        "l_1_expression": ("resolve", "expression"),
    }
Ejemplo n.º 3
0
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),
    }
Ejemplo n.º 4
0
 def parse(self, parser):
     lineno = next(parser.stream).lineno
     index = nodes.Name("_", "store", lineno=lineno)
     how_many_times = parser.parse_expression()
     iterable = nodes.Call(nodes.Name("range", "load"), [how_many_times],
                           [], None, None)
     parser.stream.expect("name:times")
     body = parser.parse_statements(["name:endrepeat"], drop_needle=True)
     return nodes.For(index, iterable, body, [], None, False, lineno=lineno)
Ejemplo n.º 5
0
 def parse_for(self):
     """Parse a for loop."""
     lineno = self.stream.expect('name:for').lineno
     target = self.parse_assign_target(extra_end_rules=('name:in',))
     self.stream.expect('name:in')
     iter = self.parse_tuple(with_condexpr=False,
                             extra_end_rules=('name:recursive',))
     test = None
     if self.stream.skip_if('name:if'):
         test = self.parse_expression()
     recursive = self.stream.skip_if('name:recursive')
     body = self.parse_statements(('name:endfor', 'name:else'))
     if next(self.stream).value == 'endfor':
         else_ = []
     else:
         else_ = self.parse_statements(('name:endfor',), drop_needle=True)
     return nodes.For(target, iter, body, else_, test,
                      recursive, lineno=lineno)
Ejemplo n.º 6
0
def test_if_branching_multi_scope():
    for_loop = nodes.For(nodes.Name('item', 'store'), nodes.Name('seq', 'load'), [
        nodes.If(nodes.Name('expression', 'load'), [
            nodes.Assign(nodes.Name('x', 'store'), nodes.Const(42))], []),
        nodes.Include(nodes.Const('helper.html'), True, False)
    ], [], None, False)

    tmpl = nodes.Template([
        nodes.Assign(nodes.Name('x', 'store'), nodes.Const(23)),
        for_loop
    ])

    tmpl_sym = symbols_for_node(tmpl)
    for_sym = symbols_for_node(for_loop, tmpl_sym)
    assert for_sym.stores == set(['item', 'x'])
    assert for_sym.loads == {
        'l_1_x': ('alias', 'l_0_x'),
        'l_1_item': ('param', None),
        'l_1_expression': ('resolve', 'expression'),
    }
Ejemplo n.º 7
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)
Ejemplo n.º 8
0
def test_complex():
    title_block = nodes.Block(
        "title", [nodes.Output([nodes.TemplateData(u"Page Title")])], False)

    render_title_macro = nodes.Macro(
        "render_title",
        [nodes.Name("title", "param")],
        [],
        [
            nodes.Output([
                nodes.TemplateData(u'\n  <div class="title">\n    <h1>'),
                nodes.Name("title", "load"),
                nodes.TemplateData(u"</h1>\n    <p>"),
                nodes.Name("subtitle", "load"),
                nodes.TemplateData(u"</p>\n    "),
            ]),
            nodes.Assign(nodes.Name("subtitle", "store"),
                         nodes.Const("something else")),
            nodes.Output([
                nodes.TemplateData(u"\n    <p>"),
                nodes.Name("subtitle", "load"),
                nodes.TemplateData(u"</p>\n  </div>\n"),
                nodes.If(
                    nodes.Name("something", "load"),
                    [
                        nodes.Assign(
                            nodes.Name("title_upper", "store"),
                            nodes.Filter(
                                nodes.Name("title", "load"),
                                "upper",
                                [],
                                [],
                                None,
                                None,
                            ),
                        ),
                        nodes.Output([
                            nodes.Name("title_upper", "load"),
                            nodes.Call(
                                nodes.Name("render_title", "load"),
                                [nodes.Const("Aha")],
                                [],
                                None,
                                None,
                            ),
                        ]),
                    ],
                    [],
                    [],
                ),
            ]),
        ],
    )

    for_loop = nodes.For(
        nodes.Name("item", "store"),
        nodes.Name("seq", "load"),
        [
            nodes.Output([
                nodes.TemplateData(u"\n    <li>"),
                nodes.Name("item", "load"),
                nodes.TemplateData(u"</li>\n    <span>"),
            ]),
            nodes.Include(nodes.Const("helper.html"), True, False),
            nodes.Output([nodes.TemplateData(u"</span>\n  ")]),
        ],
        [],
        None,
        False,
    )

    body_block = nodes.Block(
        "body",
        [
            nodes.Output([
                nodes.TemplateData(u"\n  "),
                nodes.Call(
                    nodes.Name("render_title", "load"),
                    [nodes.Name("item", "load")],
                    [],
                    None,
                    None,
                ),
                nodes.TemplateData(u"\n  <ul>\n  "),
            ]),
            for_loop,
            nodes.Output([nodes.TemplateData(u"\n  </ul>\n")]),
        ],
        False,
    )

    tmpl = nodes.Template([
        nodes.Extends(nodes.Const("layout.html")),
        title_block,
        render_title_macro,
        body_block,
    ])

    tmpl_sym = symbols_for_node(tmpl)
    assert tmpl_sym.refs == {
        "render_title": "l_0_render_title",
    }
    assert tmpl_sym.loads == {
        "l_0_render_title": ("undefined", None),
    }
    assert tmpl_sym.stores == set(["render_title"])
    assert tmpl_sym.dump_stores() == {
        "render_title": "l_0_render_title",
    }

    macro_sym = symbols_for_node(render_title_macro, tmpl_sym)
    assert macro_sym.refs == {
        "subtitle": "l_1_subtitle",
        "something": "l_1_something",
        "title": "l_1_title",
        "title_upper": "l_1_title_upper",
    }
    assert macro_sym.loads == {
        "l_1_subtitle": ("resolve", "subtitle"),
        "l_1_something": ("resolve", "something"),
        "l_1_title": ("param", None),
        "l_1_title_upper": ("resolve", "title_upper"),
    }
    assert macro_sym.stores == set(["title", "title_upper", "subtitle"])
    assert macro_sym.find_ref("render_title") == "l_0_render_title"
    assert macro_sym.dump_stores() == {
        "title": "l_1_title",
        "title_upper": "l_1_title_upper",
        "subtitle": "l_1_subtitle",
        "render_title": "l_0_render_title",
    }

    body_sym = symbols_for_node(body_block)
    assert body_sym.refs == {
        "item": "l_0_item",
        "seq": "l_0_seq",
        "render_title": "l_0_render_title",
    }
    assert body_sym.loads == {
        "l_0_item": ("resolve", "item"),
        "l_0_seq": ("resolve", "seq"),
        "l_0_render_title": ("resolve", "render_title"),
    }
    assert body_sym.stores == set([])

    for_sym = symbols_for_node(for_loop, body_sym)
    assert for_sym.refs == {
        "item": "l_1_item",
    }
    assert for_sym.loads == {
        "l_1_item": ("param", None),
    }
    assert for_sym.stores == set(["item"])
    assert for_sym.dump_stores() == {
        "item": "l_1_item",
    }
Ejemplo n.º 9
0
def test_complex():
    title_block = nodes.Block('title', [
        nodes.Output([nodes.TemplateData(u'Page Title')])
    ], False)

    render_title_macro = nodes.Macro('render_title', [nodes.Name('title', 'param')], [], [
        nodes.Output([
            nodes.TemplateData(u'\n  <div class="title">\n    <h1>'),
            nodes.Name('title', 'load'),
            nodes.TemplateData(u'</h1>\n    <p>'),
            nodes.Name('subtitle', 'load'),
            nodes.TemplateData(u'</p>\n    ')]),
        nodes.Assign(
            nodes.Name('subtitle', 'store'), nodes.Const('something else')),
        nodes.Output([
            nodes.TemplateData(u'\n    <p>'),
            nodes.Name('subtitle', 'load'),
            nodes.TemplateData(u'</p>\n  </div>\n'),
            nodes.If(
                nodes.Name('something', 'load'), [
                    nodes.Assign(nodes.Name('title_upper', 'store'),
                                 nodes.Filter(nodes.Name('title', 'load'),
                                              'upper', [], [], None, None)),
                    nodes.Output([
                        nodes.Name('title_upper', 'load'),
                        nodes.Call(nodes.Name('render_title', 'load'), [
                            nodes.Const('Aha')], [], None, None)])], [])])])

    for_loop = nodes.For(
        nodes.Name('item', 'store'),
        nodes.Name('seq', 'load'), [
            nodes.Output([
                nodes.TemplateData(u'\n    <li>'),
                nodes.Name('item', 'load'),
                nodes.TemplateData(u'</li>\n    <span>')]),
            nodes.Include(nodes.Const('helper.html'), True, False),
            nodes.Output([
                nodes.TemplateData(u'</span>\n  ')])], [], None, False)

    body_block = nodes.Block('body', [
        nodes.Output([
            nodes.TemplateData(u'\n  '),
            nodes.Call(nodes.Name('render_title', 'load'), [
                nodes.Name('item', 'load')], [], None, None),
            nodes.TemplateData(u'\n  <ul>\n  ')]),
        for_loop,
        nodes.Output([nodes.TemplateData(u'\n  </ul>\n')])],
        False)

    tmpl = nodes.Template([
        nodes.Extends(nodes.Const('layout.html')),
        title_block,
        render_title_macro,
        body_block,
    ])

    tmpl_sym = symbols_for_node(tmpl)
    assert tmpl_sym.refs == {
        'render_title': 'l_0_render_title',
    }
    assert tmpl_sym.loads == {
        'l_0_render_title': ('undefined', None),
    }
    assert tmpl_sym.stores == set(['render_title'])
    assert tmpl_sym.dump_stores() == {
        'render_title': 'l_0_render_title',
    }

    macro_sym = symbols_for_node(render_title_macro, tmpl_sym)
    assert macro_sym.refs == {
        'subtitle': 'l_1_subtitle',
        'something': 'l_1_something',
        'title': 'l_1_title',
        'title_upper': 'l_1_title_upper',
    }
    assert macro_sym.loads == {
        'l_1_subtitle': ('resolve', 'subtitle'),
        'l_1_something': ('resolve','something'),
        'l_1_title': ('param', None),
        'l_1_title_upper': ('resolve', 'title_upper'),
    }
    assert macro_sym.stores == set(['title', 'title_upper', 'subtitle'])
    assert macro_sym.find_ref('render_title') == 'l_0_render_title'
    assert macro_sym.dump_stores() == {
        'title': 'l_1_title',
        'title_upper': 'l_1_title_upper',
        'subtitle': 'l_1_subtitle',
        'render_title': 'l_0_render_title',
    }

    body_sym = symbols_for_node(body_block)
    assert body_sym.refs == {
        'item': 'l_0_item',
        'seq': 'l_0_seq',
        'render_title': 'l_0_render_title',
    }
    assert body_sym.loads == {
        'l_0_item': ('resolve', 'item'),
        'l_0_seq': ('resolve', 'seq'),
        'l_0_render_title': ('resolve', 'render_title'),
    }
    assert body_sym.stores == set([])

    for_sym = symbols_for_node(for_loop, body_sym)
    assert for_sym.refs == {
        'item': 'l_1_item',
    }
    assert for_sym.loads == {
        'l_1_item': ('param', None),
    }
    assert for_sym.stores == set(['item'])
    assert for_sym.dump_stores() == {
        'item': 'l_1_item',
    }
Ejemplo n.º 10
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,
    )