def test_macro_call_2(): template = ''' {% macro user(login, name, is_active=True) %} {{ login }} {{ name.first }} {{ name.last }} {{ is_active }} {% endmacro %} {{ user(data.login, data.name, is_active=data.is_active) }} ''' struct = infer(template) assert struct['data'] == Dictionary( { 'login': Scalar(label='login', linenos=[2, 5]), 'is_active': Boolean(label='is_active', linenos=[2, 5]), 'name': Dictionary( { 'first': Scalar(label='first', linenos=[3]), 'last': Scalar(label='last', linenos=[3]), }, label='name', linenos=[2, 5]), }, label='data', linenos=[5])
def test_macro_visitor_1(): template = ''' {% macro input(name, value='', type='text', size=20) -%} <input type="{{ type }}" name="{{ name }}" value="{{value|e }}" size="{{ size }}"> {{ x }} {%- endmacro %} ''' ast = parse(template).find(nodes.Macro) macroses = {} struct = visit_macro(ast, macroses) expected_macro = Macro('input', [ ('name', Scalar(label='argument #1', linenos=[2])), ], [ ('value', String(label='argument "value"', linenos=[2])), ('type', String(label='argument "type"', linenos=[2])), ('size', Number(label='argument "size"', linenos=[2])), ]) macro = macroses['input'] assert macro.name == expected_macro.name assert macro.args == expected_macro.args assert macro.kwargs == expected_macro.kwargs expected_struct = Dictionary({'x': Scalar(label='x', linenos=[4])}) assert struct == expected_struct
def test_basics_13(): config = Config() config.TYPE_OF_VARIABLE_INDEXED_WITH_INTEGER_TYPE = 'tuple' template = ''' {% for x in xs %} {{ x[2] }} {{ x[3] }} {% endfor %} ''' struct = infer(template, config) expected_struct = Dictionary({ 'xs': List(Tuple(( Unknown(label=None, linenos=[]), Unknown(label=None, linenos=[]), Scalar(label=None, linenos=[3]), Scalar(label=None, linenos=[4]), ), label='x', linenos=[3, 4]), label='xs', linenos=[2]) }) assert struct == expected_struct
def test_1(): template = ''' {%- if x is undefined %} {{ test }} {%- endif %} {%- if y is undefined %} {% set y = 123 %} {%- endif %} {%- if y is defined %} {{ y }} {%- endif %} {%- if z is undefined %} {{ z }} {%- endif %} ''' struct = infer(template) expected_struct = Dictionary({ 'x': Unknown(label='x', checked_as_undefined=True, linenos=[2]), 'test': Scalar(label='test', linenos=[3]), 'y': Number(label='y', may_be_defined=True, linenos=[6, 7, 10, 11]), 'z': Scalar(label='z', linenos=[14, 15]), }) assert struct == expected_struct
def test_test_1(): template = '''{{ x is divisibleby (data.field) }}''' ast = parse(template).find(nodes.Test) rtype, struct = visit_test(ast, get_scalar_context(ast)) expected_struct = Dictionary({ 'x': Scalar(label='x', linenos=[1]), 'data': Dictionary({ 'field': Number(label='field', linenos=[1]), }, label='data', linenos=[1]) }) assert struct == expected_struct template = '''{{ x is divisibleby 3 }}''' ast = parse(template).find(nodes.Test) rtype, struct = visit_test(ast, get_scalar_context(ast)) expected_struct = Dictionary({ 'x': Scalar(label='x', linenos=[1]), }) assert struct == expected_struct
def test_basics_2(): template = ''' {% if test1 %} {% if test2 %} {% set d = {'x': 123, a: z.qwerty} %} {% else %} {% set d = {'x': 456, a: z.gsom} %} {% endif %} {% endif %} {% if d %} {{ d.x }} {% endif %} {{ z.gsom }} ''' struct = infer(template) expected_struct = Dictionary({ 'a': Scalar(label='a', linenos=[4, 6]), 'test1': Unknown(label='test1', linenos=[2]), 'test2': Unknown(label='test2', linenos=[3]), 'z': Dictionary(data={ 'qwerty': Unknown(label='qwerty', linenos=[4]), 'gsom': Scalar(label='gsom', linenos=[6, 12]), }, label='z', linenos=[4, 6, 12]), }) assert struct == expected_struct
def test_getitem_1(): template = '''{{ a['b']['c'][1]['d'][x] }}''' ast = parse(template).find(nodes.Getitem) config = Config() config.TYPE_OF_VARIABLE_INDEXED_WITH_VARIABLE_TYPE = 'list' rtype, struct = visit_getitem(ast, get_scalar_context(ast), {}, config) expected_struct = Dictionary({ 'a': Dictionary( { 'b': Dictionary( { 'c': List(Dictionary( { 'd': List(Scalar(linenos=[1]), label='d', linenos=[1]) }, linenos=[1]), label='c', linenos=[1]), }, label='b', linenos=[1]), }, label='a', linenos=[1]), 'x': Scalar(label='x', linenos=[1]), }) assert struct == expected_struct
def test_list_becomes_dict(): template = ''' {% for r in PrjList %} <tr><td><a class='btn btn-primary' href='/part/prj/{{ r[0] }}'>Select</a></td> <td> {{ r[1] }} [{{ r[0] }}] {{ ("<a href='mailto:"+r['email']+"'>") |safe if r['email'] }}</td> <td>{{ r['samplecount'] }}</td> </tr> {% endfor %} ''' struct = infer(template) expected_struct = Dictionary({ 'PrjList': List(Dictionary( { 0: Scalar(), 1: Scalar(), 'email': String(label="email", linenos=[4]), 'samplecount': Scalar(label="samplecount", linenos=[5]), }, label="r", linenos=[3, 4, 5]), label="PrjList", linenos=[2]), }) assert struct == expected_struct
def test_include_override_1(env, config): struct = infer( env.loader.get_source(env, 'inner_include_override_1.html')[0], config) expected_struct = Dictionary({ 'default_name': Scalar(label='default_name', linenos=[2]), 'name': Scalar(label='name', linenos=[3]), }) assert struct == expected_struct
def test_max_min_filter(): for filter in ('max', 'min'): template = '{{ values|' + filter + ' }}' ast = parse(template).find(nodes.Filter) rtype, struct = visit_filter(ast, get_scalar_context(ast)) assert rtype == Scalar(label='values', linenos=[1]) assert struct == Dictionary({ 'values': List(Scalar(linenos=[1]), label='values', linenos=[1]), })
def test_pprint_filter(): template = '{{ x|pprint }}' ast = parse(template).find(nodes.Filter) rtype, struct = visit_filter(ast, get_scalar_context(ast)) assert rtype == Scalar(label='x', linenos=[1]) expected_struct = Dictionary({ 'x': Scalar(label='x', linenos=[1]), }) assert struct == expected_struct
def test_extend_with_block_override_2(env, config): struct = infer( env.loader.get_source(env, 'inner_extend_override_2.html')[0], config) expected_struct = Dictionary({ 'name': Scalar(label='name', linenos=[3]), 'location': Scalar(label='location', linenos=[6]), 'default_mood': Scalar(label='default_mood', linenos=[8]), }) assert struct == expected_struct
def test_extend_1(env, config): struct = infer(env.loader.get_source(env, 'inner_extend.html')[0], config) expected_struct = Dictionary({ 'var': Dictionary({'a': Scalar(label='a', linenos=[1])}, label='var', linenos=[1]), 'some': Scalar(label='some', linenos=[2]), 'extended': Scalar(label='extended', linenos=[2]), }) assert struct == expected_struct
def test_extend_with_block_override_3(): env = Environment(loader=PackageLoader('tests', 'templates')) struct = infer( env.loader.get_source(env, 'inner_override_3.html')[0], Config(PACKAGE_NAME='tests')) expected_struct = Dictionary({ 'location': Scalar(label='location', linenos=[6]), 'mood': Scalar(label='mood', linenos=[9]), 'name': Scalar(label='name', linenos=[3]), }) assert struct == expected_struct
def test_block_1(): config = Config() template = ''' {% block test %} {{ x }} {{ y }} {% endblock %} ''' struct = infer(template, config) expected_struct = Dictionary({ 'x': Scalar(label='x', linenos=[3]), 'y': Scalar(label='y', linenos=[4]), }) assert struct == expected_struct
def test_cond_expr(): template = '''{{ queue if queue is defined else 'wizard' }}''', ast = parse(template).find(nodes.CondExpr) rtype, struct = visit_cond_expr(ast, get_scalar_context(ast)) expected_struct = Dictionary( {'queue': Scalar(label='queue', linenos=[1], checked_as_defined=True)}) assert struct == expected_struct template = '''{{ queue if queue is undefined else 'wizard' }}''' ast = parse(template).find(nodes.CondExpr) rtype, struct = visit_cond_expr(ast, get_scalar_context(ast)) expected_struct = Dictionary({'queue': Scalar(label='queue', linenos=[1])}) assert struct == expected_struct
def test_int_filter(): ast = parse('{{ x|int }}').find(nodes.Filter) rtype, struct = visit_filter(ast, get_scalar_context(ast)) assert rtype == Number(label='x', linenos=[1]) assert struct == Dictionary({ 'x': Scalar(label='x', linenos=[1]), })
def test_include_1(env, config): struct = infer( env.loader.get_source(env, 'inner_include_1.html')[0], config) expected_struct = Dictionary({ 'var': Dictionary( { 'x': Scalar(label='x', linenos=[1]), 'y': Scalar(label='y', linenos=[1]), }, label='var', linenos=[1]), 'more': Scalar(label='more', linenos=[2]), }) assert struct == expected_struct
def test_extend_1(): env = Environment(loader=PackageLoader('tests', 'templates')) struct = infer( env.loader.get_source(env, 'inner_extend.html')[0], Config(PACKAGE_NAME='tests')) expected_struct = Dictionary({ 'var': Dictionary({'a': Scalar(label='a', linenos=[1])}, label='var', linenos=[1]), 'some': Scalar(label='some', linenos=[2]), 'extended': Scalar(label='extended', linenos=[2]), }) assert struct == expected_struct
def test_filter_chaining(): template = '''{{ (xs|first|last).gsom|sort|length }}''' ast = parse(template).find(nodes.Filter) rtype, struct = visit_filter(ast, get_scalar_context(ast)) expected_struct = Dictionary({ 'xs': List(List(Dictionary( { 'gsom': List(Unknown(), label='gsom', linenos=[1]), }, linenos=[1]), linenos=[1]), label='xs', linenos=[1]), }) assert struct == expected_struct template = '''{{ x|list|sort|first }}''' ast = parse(template).find(nodes.Filter) rtype, struct = visit_filter(ast, get_scalar_context(ast)) expected_struct = Dictionary({ 'x': Scalar(label='x', linenos=[1]), }) assert struct == expected_struct template = '''{{ x|first|list }}''' ast = parse(template).find(nodes.Filter) with pytest.raises(UnexpectedExpression): visit_filter(ast, get_scalar_context(ast))
def test_getattr_1(): template = '{{ (x or y).field.subfield[2].a }}' ast = parse(template).find(nodes.Getattr) rtype, struct = visit_getattr(ast, get_scalar_context(ast)) x_or_y_dict = { 'field': Dictionary( { 'subfield': List(Dictionary({'a': Scalar(label='a', linenos=[1])}, linenos=[1]), label='subfield', linenos=[1]), }, label='field', linenos=[1]), } expected_struct = Dictionary({ 'x': Dictionary(x_or_y_dict, label='x', linenos=[1]), 'y': Dictionary(x_or_y_dict, label='y', linenos=[1]) }) assert struct == expected_struct
def test_basics_4(): template = ''' {% set xys = [ ('a', 0.3), ('b', 0.3), ] %} {% if configuration is undefined %} {% set configuration = 'prefix-' ~ timestamp %} {% endif %} queue: {{ queue if queue is defined else 'wizard' }} description: >- {% for x, y in xys %} {{ loop.index }}: {{ x }} {{ y }} {% endfor %} ''' struct = infer(template) expected_struct = Dictionary({ 'configuration': String(label='configuration', may_be_defined=True, checked_as_undefined=True, constant=False, linenos=[6, 7]), 'queue': Scalar(label='queue', checked_as_defined=True, constant=False, linenos=[9]), 'timestamp': String(label='timestamp', constant=False, linenos=[7]) }) assert struct == expected_struct
def test_basics_1(): template = ''' {% set d = {'x': 123, a: z.qwerty} %} {{ d.x }} ''' struct = infer(template) expected_struct = Dictionary({ 'a': Scalar(label='a', linenos=[2]), 'z': Dictionary(label='z', data={ 'qwerty': Unknown(label='qwerty', linenos=[2]), }, linenos=[2]), }) assert struct == expected_struct template = ''' {% set d = {'x': 123, a: z.qwerty} %} {{ d.x.field }} ''' with pytest.raises(MergeException): infer(template) template = ''' {% set x = '123' %} {{ x.test }} ''' with pytest.raises(MergeException): infer(template) template = ''' {% set a = {'x': 123} %} {% set b = {a: 'test'} %} ''' with pytest.raises(MergeException): infer(template)
def test_slice(): template = '''{{ xs[a:2:b] }}''' ast = parse(template).find(nodes.Getitem) rtype, struct = visit_getitem(ast, get_scalar_context(ast)) assert struct == Dictionary({ 'xs': List(Scalar(linenos=[1]), label='xs', linenos=[1]), 'a': Number(label='a', linenos=[1]), 'b': Number(label='b', linenos=[1]), })
def test_basics_14(): template = ''' {{ section.FILTERS.test }} {%- for f in section.FILTERS.keys() %} {{ section.GEO }} {{ loop.index }} {%- endfor %} ''' struct = infer(template) expected_struct = Dictionary({ 'section': Dictionary({ 'FILTERS': Dictionary({ 'test': Scalar(label='test', linenos=[2]) }, label='FILTERS', linenos=[2, 3]), 'GEO': Scalar(label='GEO', linenos=[4]), }, label='section', linenos=[2, 3, 4]) }) assert struct == expected_struct
def test_include_1(): env = Environment(loader=PackageLoader('tests', 'templates')) struct = infer( env.loader.get_source(env, 'inner_include.html')[0], Config(PACKAGE_NAME='tests')) expected_struct = Dictionary({ 'var': Dictionary( { 'x': Scalar(label='x', linenos=[1]), 'y': Scalar(label='y', linenos=[1]) }, label='var', linenos=[1]), 'more': Scalar(label='more', linenos=[2]), }) assert struct == expected_struct
def test_if_1(): template = ''' {% if (x or y) and not z %} {{ x }} {{ z.field }} {% endif %} ''' ast = parse(template).find(nodes.If) struct = visit_if(ast) expected_struct = Dictionary({ 'z': Dictionary({ 'field': Scalar(label='field', linenos=[4]), }, label='z', linenos=[2, 4]), 'x': Scalar(label='x', linenos=[2, 3]), 'y': Unknown(label='y', linenos=[2]), }) assert struct == expected_struct
def test_for_3(): template = ''' {% for a, b in list %} {{ a.field }} {{ b }} {% endfor %} ''' ast = parse(template).find(nodes.For) struct = visit_for(ast) expected_struct = Dictionary({ 'list': List(Tuple(( Dictionary({ 'field': Scalar(label='field', linenos=[3]) }, label='a', linenos=[3]), Scalar(label='b', linenos=[4]) ), linenos=[2]), label='list', linenos=[2]) }) assert struct == expected_struct
def test_include_extend_1(env, config): struct = infer( env.loader.get_source(env, 'include_extend.html')[0], config) expected_struct = Dictionary({ 'var': Dictionary( { 'x': Scalar(label='x', linenos=[1]), 'y': Scalar(label='y', linenos=[1]), 'a': Scalar(label='a', linenos=[1]), }, label='var', linenos=[1]), 'also': Scalar(label='also', linenos=[3]), 'extended': Scalar(label='extended', linenos=[2]), }) assert struct == expected_struct
def test_getitem_2(): template = '''{{ a[z] }}''' ast = parse(template).find(nodes.Getitem) config = Config() config.TYPE_OF_VARIABLE_INDEXED_WITH_VARIABLE_TYPE = 'dictionary' rtype, struct = visit_getitem(ast, get_scalar_context(ast), {}, config) expected_struct = Dictionary({ 'a': Dictionary(label='a', linenos=[1]), 'z': Scalar(label='z', linenos=[1]), }) assert struct == expected_struct
def test_string_filters(): for filter in ('striptags', 'capitalize', 'title', 'upper', 'urlize'): template = '{{ x|' + filter + ' }}' ast = parse(template).find(nodes.Filter) ctx = Context(return_struct_cls=Scalar, predicted_struct=Scalar.from_ast(ast)) rtype, struct = visit_filter(ast, ctx) expected_rtype = String(label='x', linenos=[1]) expected_struct = Dictionary({ 'x': String(label='x', linenos=[1]), }) assert rtype == expected_rtype assert struct == expected_struct
def test_batch_and_slice_filters(): for filter in ('batch', 'slice'): template = '{{ items|' + filter + '(3, " ") }}' ast = parse(template).find(nodes.Filter) unknown_ctx = Context(predicted_struct=Unknown.from_ast(ast)) rtype, struct = visit_filter(ast, unknown_ctx) expected_rtype = List(List(Unknown(), linenos=[1]), linenos=[1]) assert rtype == expected_rtype expected_struct = Dictionary({ 'items': List(Unknown(), label='items', linenos=[1]), }) assert struct == expected_struct scalar_ctx = Context(predicted_struct=Scalar.from_ast(ast)) with pytest.raises(UnexpectedExpression) as e: visit_filter(ast, scalar_ctx) assert str(e.value) == ('conflict on the line 1\n' 'got: AST node jinja2.nodes.Filter of structure [[<unknown>]]\n' 'expected structure: <scalar>')
def get_scalar_context(ast): return Context(return_struct_cls=Scalar, predicted_struct=Scalar.from_ast(ast))