import pytest from jinja2 import nodes from jinja2.idtracking import symbols_for_node 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 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
\n

'), nodes.Name('title', 'load'), nodes.TemplateData(u'

\n

'), nodes.Name('subtitle', 'load'), nodes.TemplateData(u'

\n ')]), nodes.Assign( nodes.Name('subtitle', 'store'), nodes.Const('something else')), nodes.Output([ nodes.TemplateData(u'\n

'), nodes.Name('subtitle', 'load'), nodes.TemplateData(u'

\n
\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
  • '), nodes.Name('item', 'load'), nodes.TemplateData(u'
  • \n ')]), nodes.Include(nodes.Const('helper.html'), True, False), nodes.Output([ nodes.TemplateData(u'\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 \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', } 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', } def test_if_branching_stores_undefined(): tmpl = nodes.Template([ nodes.Assign(nodes.Name('variable', 'store'), nodes.Const(23)), 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': ('undefined', None), 'l_0_expression': ('resolve', 'expression') } assert sym.dump_stores() == { 'variable': 'l_0_variable', } 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'), }