Exemplo n.º 1
0
def unless(token: "Token", parser: "Parser") -> nodes.Node:
    """The unless tag {% unless ... %} ... {% endunless %}

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

    Returns:
        The parsed node
    """
    node = result = nodes.If(lineno=token.lineno)
    while True:
        node.test = nodes.Not(
            parser.parse_tuple(with_condexpr=False),
            lineno=token.lineno,
        )
        node.body = parser.parse_statements(
            ("name:elif", "name:elsif", "name:else", "name:endunless")
        )
        node.elif_ = []
        node.else_ = []
        token = next(parser.stream)
        if token.test_any("name:elif", "name:elsif"):
            node = nodes.If(lineno=parser.stream.current.lineno)
            result.elif_.append(node)
            continue
        if token.test("name:else"):
            result.else_ = parser.parse_statements(
                ("name:endunless",), drop_needle=True
            )
        break
    return result
Exemplo n.º 2
0
 def parse(self, parser):
     tag = parser.stream.current
     lineno = next(parser.stream).lineno
     cond = parser.parse_expression()
     ### first, seek to the start of the "head" token
     parser.parse_statements(["name:head"], drop_needle=True)
     h_then = parser.parse_statements(["name:else", "name:body"])
     if parser.stream.current.value == "else":
         next(parser.stream)
         h_else = parser.parse_statements(["name:body"])
     else:
         h_else = None
     next(parser.stream)
     body = parser.parse_statements(["name:endonion", "name:tail"])
     result = [nodes.If(cond, h_then, h_else)]
     result.extend(body)
     if parser.stream.current.value == "tail":
         next(parser.stream)
         t_then = parser.parse_statements(["name:else", "name:endonion"])
         if parser.stream.current.value == "else":
             next(parser.stream)
             t_else = parser.parse_statements(["name:endonion"])
         else:
             t_else = None
         result.append(nodes.If(cond, t_then, t_else))
     next(parser.stream)
     return result
Exemplo n.º 3
0
    def parse(self, parser):
        lineno = next(parser.stream).lineno
        url = parser.parse_expression(with_condexpr=False)
        url_var = nodes.Name('checked_url', 'store')
        args = None
        if parser.stream.current.type != 'block_end':
            parser.stream.expect('comma')
            args = parser.parse_expression(with_condexpr=False)

        fun_var = parser.free_identifier()
        body = parser.parse_statements(('name:endauth', 'name:else'))
        token = next(parser.stream)
        if token.test('name:else'):
            else_ = parser.parse_statements(
                ('name:endauth', ), drop_needle=True)
        else:
            else_ = None
        url_fun_tuple = nodes.Tuple([url_var, fun_var], 'store')
        # The url goes in the dyn_args (its not visited otherwise).
        # To be in the dyn_args, it must be wrapped in a Tuple.
        assignment = nodes.Assign(url_fun_tuple,
                                  self.call_method(
                                      'template_if_auth_url_for',
                                      dyn_args=nodes.Tuple([url], 'load'),
                                      dyn_kwargs=args)).set_lineno(lineno)

        returned_ast = [assignment]
        if_node = nodes.If()
        if_node.test = nodes.Name('checked_url', 'load')
        if_node.body = body
        if_node.else_ = else_
        if_node.elif_ = []
        returned_ast.append(if_node.set_lineno(lineno))
        return returned_ast
Exemplo n.º 4
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"),
    }
Exemplo n.º 5
0
 def parse_if(self):
     """Parse an if construct."""
     node = result = nodes.If(lineno=self.stream.expect('name:if').lineno)
     while 1:
         node.test = self.parse_tuple(with_condexpr=False)
         node.body = self.parse_statements(
             ('name:elif', 'name:else', 'name:endif'))
         node.elif_ = []
         node.else_ = []
         token = next(self.stream)
         if token.test('name:elif'):
             node = nodes.If(lineno=self.stream.current.lineno)
             result.elif_.append(node)
             continue
         elif token.test('name:else'):
             result.else_ = self.parse_statements(('name:endif', ),
                                                  drop_needle=True)
         break
     return result
Exemplo n.º 6
0
    def parse_if(self):
        node = result = nodes.If(lineno=self.stream.expect('name:if').lineno)
        while 1:
            node.test = self.parse_tuple(with_condexpr=False)
            node.body = self.parse_statements(
                ('name:elif', 'name:else', 'name:endif'))
            token = next(self.stream)
            if token.test('name:elif'):
                new_node = nodes.If(lineno=self.stream.current.lineno)
                node.else_ = [new_node]
                node = new_node
                continue
            elif token.test('name:else'):
                node.else_ = self.parse_statements(('name:endif', ),
                                                   drop_needle=True)
            else:
                node.else_ = []
            break

        return result
Exemplo n.º 7
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.º 8
0
    def parse(self, parser):
        m = nodes.Macro(lineno=next(parser.stream).lineno)
        name = parser.parse_assign_target(name_only=True).name
        m.name = f"default_{name}"
        parser.parse_signature(m)
        m.body = parser.parse_statements(("name:enddefaultmacro",), drop_needle=True)

        if_stmt = nodes.If(
            nodes.Not(nodes.Name(name, "load")),
            [nodes.Macro(name, m.args, m.defaults, m.body)],
            [],
            [],
        )
        return [m, if_stmt]
Exemplo n.º 9
0
def test_if_branching_stores():
    tmpl = nodes.Template([
        nodes.If(nodes.Name('expression', 'load'), [
            nodes.Assign(nodes.Name('variable', 'store'),
                         nodes.Const(42))], [])])

    sym = symbols_for_node(tmpl)
    assert sym.refs == {
        'variable': 'l_0_variable',
        'expression': 'l_0_expression'
    }
    assert sym.stores == set(['variable'])
    assert sym.loads == {
        'l_0_variable': ('resolve', 'variable'),
        'l_0_expression': ('resolve', 'expression')
    }
    assert sym.dump_stores() == {
        'variable': 'l_0_variable',
    }
Exemplo n.º 10
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'),
    }
    def parse(self, parser):
        # Create a normal With node first
        # Borrowing the codes from parser.py,
        # the only difference is the end tag is `endrequired`
        # instead of `endwith`
        with_node = nodes.With(lineno=next(parser.stream).lineno)
        targets = []
        values = []
        while parser.stream.current.type != 'block_end':
            if targets:
                parser.stream.expect('comma')
            target = parser.parse_assign_target()
            target.set_ctx('param')
            targets.append(target)
            parser.stream.expect('assign')
            values.append(parser.parse_expression())
        with_node.targets = targets
        with_node.values = values
        with_node.body = parser.parse_statements(('name:endrequired', ),
                                                 drop_needle=True)

        # Manually create a If node
        if_node = nodes.If()
        # If only one variable is required, assigned that variable to test if it is empty
        if len(values) == 1:
            test = values[0]
        else:
            # If more than one variables are required, concat them into a And node
            test = nodes.And(left=values[0], right=values[1])
            for i in range(2, len(values)):
                test = nodes.And(left=test, right=values[i])

        if_node.test = test
        # Assign with_node as the body of the if_node, to nest them
        if_node.body = [with_node]
        # set other fields to empty list.
        for _f in nodes.If:
            if getattr(if_node, _f) is None:
                setattr(if_node, _f, [])
        return if_node
Exemplo n.º 12
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.º 13
0
def test_if_branching_stores():
    tmpl = nodes.Template([
        nodes.If(
            nodes.Name("expression", "load"),
            [nodes.Assign(nodes.Name("variable", "store"), nodes.Const(42))],
            [],
            [],
        )
    ])

    sym = symbols_for_node(tmpl)
    assert sym.refs == {
        "variable": "l_0_variable",
        "expression": "l_0_expression"
    }
    assert sym.stores == set(["variable"])
    assert sym.loads == {
        "l_0_variable": ("resolve", "variable"),
        "l_0_expression": ("resolve", "expression"),
    }
    assert sym.dump_stores() == {
        "variable": "l_0_variable",
    }
Exemplo n.º 14
0
class Builtin(object):
    def __init__(self, name):
        self.name = name

    def __repr__(self):
        return self.name


DJEDI_NODE_STORAGE_NODE = (
    nodes.If(
        # if not isinstance(DJEDI_NODE_STORAGE, dict):
        nodes.Not(
            nodes.Call(nodes.Const(Builtin('isinstance')), [
                nodes.Name(DJEDI_NODE_STORAGE, 'load'),
                nodes.Const(Builtin('dict')),
            ], [], None, None)),
        # DJEDI_NODE_STORAGE = {}
        [
            nodes.Assign(nodes.Name(DJEDI_NODE_STORAGE, 'store'), nodes.Dict(
                [])),
        ],
        # else: pass
        []))


class NodeExtension(Extension):
    tags = set([DJEDI_INIT_TAG, DJEDI_TAG, DJEDI_BLOCK_TAG])

    def create_node_id(self, uri, default):
        m = hashlib.sha256()
        m.update(uri.encode('utf8'))
        if default:
Exemplo n.º 15
0
    'body': [
        nodes.Assign(nodes.Name(DJEDI_NODE_STORAGE, 'store'), nodes.Dict([])),
    ],
}

# Construct the Jinja2 AST equivalent of:
#
#   if not isinstance(DJEDI_NODE_STORAGE, dict):
#       DJEDI_NODE_STORAGE = {}
#
if nodes.If.fields == ('test', 'body', 'elif_', 'else_'):
    # Jinja 2.10 added the "elif" field to If()
    DJEDI_NODE_STORAGE_NODE = (
        nodes.If(
            IF_NODE_FIELDS['test'],  # test
            IF_NODE_FIELDS['body'],  # body
            [],  # elif
            [],  # else
        ))
else:
    # nodes.If.fields is assumed to be ('test', 'body', 'else')
    DJEDI_NODE_STORAGE_NODE = (
        nodes.If(
            IF_NODE_FIELDS['test'],  # test
            IF_NODE_FIELDS['body'],  # body
            []  # else
        ))


class NodeExtension(Extension):
    tags = set([DJEDI_INIT_TAG, DJEDI_TAG, DJEDI_BLOCK_TAG])
Exemplo n.º 16
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
Exemplo n.º 17
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",
    }
Exemplo n.º 18
0
 def _if_node(self, cond, then_block, else_block):
     return nodes.If(cond, then_block, [], else_block)
Exemplo n.º 19
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',
    }