blob: 759af6a90b68732ae523fabb7890e1e676b2e559 [file] [log] [blame]
Armin Ronacherecc051b2007-06-01 18:25:28 +02001# -*- coding: utf-8 -*-
2"""
3 unit test for expression syntax
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
Armin Ronacher62ccd1b2009-01-04 14:26:19 +01006 :copyright: (c) 2009 by the Jinja Team.
Armin Ronacherecc051b2007-06-01 18:25:28 +02007 :license: BSD, see LICENSE for more details.
8"""
Armin Ronacher42979eb2009-07-26 11:08:50 +02009from jinja2 import Environment
Armin Ronacher547d0b62008-07-04 16:35:10 +020010from jinja2.exceptions import TemplateSyntaxError, UndefinedError
Armin Ronacher1cc232c2007-09-07 17:52:41 +020011
Armin Ronacher42979eb2009-07-26 11:08:50 +020012from nose.tools import assert_raises
13
14env = Environment()
Rene Leonhardtc7e6c6d2009-04-20 23:08:53 +020015
Armin Ronacherecc051b2007-06-01 18:25:28 +020016
17CALL = '''{{ foo('a', c='d', e='f', *['b'], **{'g': 'h'}) }}'''
18SLICING = '''{{ [1, 2, 3][:] }}|{{ [1, 2, 3][::-1] }}'''
19ATTR = '''{{ foo.bar }}|{{ foo['bar'] }}'''
20SUBSCRIPT = '''{{ foo[0] }}|{{ foo[-1] }}'''
Armin Ronacher1cc232c2007-09-07 17:52:41 +020021TUPLE = '''{{ () }}|{{ (1,) }}|{{ (1, 2) }}'''
Armin Ronacherecc051b2007-06-01 18:25:28 +020022MATH = '''{{ (1 + 1 * 2) - 3 / 2 }}|{{ 2**3 }}'''
23DIV = '''{{ 3 // 2 }}|{{ 3 / 2 }}|{{ 3 % 2 }}'''
24UNARY = '''{{ +3 }}|{{ -3 }}'''
Armin Ronacher1cc232c2007-09-07 17:52:41 +020025CONCAT = '''{{ [1, 2] ~ 'foo' }}'''
Armin Ronacherecc051b2007-06-01 18:25:28 +020026COMPARE = '''{{ 1 > 0 }}|{{ 1 >= 1 }}|{{ 2 < 3 }}|{{ 2 == 2 }}|{{ 1 <= 1 }}'''
Armin Ronacher1cc232c2007-09-07 17:52:41 +020027INOP = '''{{ 1 in [1, 2, 3] }}|{{ 1 not in [1, 2, 3] }}'''
Armin Ronacher203bfcb2008-04-24 21:54:44 +020028LITERALS = '''{{ [] }}|{{ {} }}|{{ () }}'''
Armin Ronacherecc051b2007-06-01 18:25:28 +020029BOOL = '''{{ true and false }}|{{ false or true }}|{{ not false }}'''
Armin Ronacherdb69d0a2007-06-02 01:35:53 +020030GROUPING = '''{{ (true and false) or (false and true) and not false }}'''
Armin Ronacher1cc232c2007-09-07 17:52:41 +020031CONDEXPR = '''{{ 0 if true else 1 }}'''
Armin Ronachercb1b97f2008-09-10 14:03:53 +020032DJANGOATTR = '''{{ [1, 2, 3].0 }}|{{ [[1]].0.0 }}'''
Armin Ronacher1cc232c2007-09-07 17:52:41 +020033FILTERPRIORITY = '''{{ "foo"|upper + "bar"|upper }}'''
Armin Ronacher1cc232c2007-09-07 17:52:41 +020034TUPLETEMPLATES = [
35 '{{ () }}',
36 '{{ (1, 2) }}',
37 '{{ (1, 2,) }}',
38 '{{ 1, }}',
39 '{{ 1, 2 }}',
40 '{% for foo, bar in seq %}...{% endfor %}',
41 '{% for x in foo, bar %}...{% endfor %}',
Armin Ronacherb5124e62008-04-25 00:36:14 +020042 '{% for x in foo, %}...{% endfor %}'
Armin Ronacher1cc232c2007-09-07 17:52:41 +020043]
Armin Ronacher203bfcb2008-04-24 21:54:44 +020044TRAILINGCOMMA = '''{{ (1, 2,) }}|{{ [1, 2,] }}|{{ {1: 2,} }}'''
Armin Ronacherecc051b2007-06-01 18:25:28 +020045
46
47def test_call():
Armin Ronacherecc051b2007-06-01 18:25:28 +020048 env = Environment()
49 env.globals['foo'] = lambda a, b, c, e, g: a + b + c + e + g
50 tmpl = env.from_string(CALL)
51 assert tmpl.render() == 'abdfh'
52
53
Armin Ronacher42979eb2009-07-26 11:08:50 +020054def test_slicing():
Armin Ronacherecc051b2007-06-01 18:25:28 +020055 tmpl = env.from_string(SLICING)
56 assert tmpl.render() == '[1, 2, 3]|[3, 2, 1]'
57
58
Armin Ronacher42979eb2009-07-26 11:08:50 +020059def test_attr():
Armin Ronacherecc051b2007-06-01 18:25:28 +020060 tmpl = env.from_string(ATTR)
61 assert tmpl.render(foo={'bar': 42}) == '42|42'
62
63
Armin Ronacher42979eb2009-07-26 11:08:50 +020064def test_subscript():
Armin Ronacherecc051b2007-06-01 18:25:28 +020065 tmpl = env.from_string(SUBSCRIPT)
66 assert tmpl.render(foo=[0, 1, 2]) == '0|2'
67
68
Armin Ronacher42979eb2009-07-26 11:08:50 +020069def test_tuple():
Armin Ronacherecc051b2007-06-01 18:25:28 +020070 tmpl = env.from_string(TUPLE)
Armin Ronacher1cc232c2007-09-07 17:52:41 +020071 assert tmpl.render() == '()|(1,)|(1, 2)'
Armin Ronacherecc051b2007-06-01 18:25:28 +020072
73
Armin Ronacher42979eb2009-07-26 11:08:50 +020074def test_math():
Armin Ronacherecc051b2007-06-01 18:25:28 +020075 tmpl = env.from_string(MATH)
76 assert tmpl.render() == '1.5|8'
77
78
Armin Ronacher42979eb2009-07-26 11:08:50 +020079def test_div():
Armin Ronacherecc051b2007-06-01 18:25:28 +020080 tmpl = env.from_string(DIV)
81 assert tmpl.render() == '1|1.5|1'
82
83
Armin Ronacher42979eb2009-07-26 11:08:50 +020084def test_unary():
Armin Ronacherecc051b2007-06-01 18:25:28 +020085 tmpl = env.from_string(UNARY)
86 assert tmpl.render() == '3|-3'
87
88
Armin Ronacher42979eb2009-07-26 11:08:50 +020089def test_concat():
Armin Ronacher1cc232c2007-09-07 17:52:41 +020090 tmpl = env.from_string(CONCAT)
91 assert tmpl.render() == '[1, 2]foo'
92
93
Armin Ronacher42979eb2009-07-26 11:08:50 +020094def test_compare():
Armin Ronacherecc051b2007-06-01 18:25:28 +020095 tmpl = env.from_string(COMPARE)
96 assert tmpl.render() == 'True|True|True|True|True'
97
98
Armin Ronacher42979eb2009-07-26 11:08:50 +020099def test_inop():
Armin Ronacher1cc232c2007-09-07 17:52:41 +0200100 tmpl = env.from_string(INOP)
101 assert tmpl.render() == 'True|False'
102
103
Armin Ronacher42979eb2009-07-26 11:08:50 +0200104def test_literals():
Armin Ronacherecc051b2007-06-01 18:25:28 +0200105 tmpl = env.from_string(LITERALS)
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200106 assert tmpl.render().lower() == '[]|{}|()'
Armin Ronacherecc051b2007-06-01 18:25:28 +0200107
108
Armin Ronacher42979eb2009-07-26 11:08:50 +0200109def test_bool():
Armin Ronacherecc051b2007-06-01 18:25:28 +0200110 tmpl = env.from_string(BOOL)
111 assert tmpl.render() == 'False|True|True'
Armin Ronacherdb69d0a2007-06-02 01:35:53 +0200112
113
Armin Ronacher42979eb2009-07-26 11:08:50 +0200114def test_grouping():
Armin Ronacherdb69d0a2007-06-02 01:35:53 +0200115 tmpl = env.from_string(GROUPING)
116 assert tmpl.render() == 'False'
Armin Ronacher1cc232c2007-09-07 17:52:41 +0200117
118
Armin Ronacher42979eb2009-07-26 11:08:50 +0200119def test_django_attr():
Armin Ronacher1cc232c2007-09-07 17:52:41 +0200120 tmpl = env.from_string(DJANGOATTR)
Armin Ronachercb1b97f2008-09-10 14:03:53 +0200121 assert tmpl.render() == '1|1'
Armin Ronacher1cc232c2007-09-07 17:52:41 +0200122
123
Armin Ronacher42979eb2009-07-26 11:08:50 +0200124def test_conditional_expression():
Armin Ronacher1cc232c2007-09-07 17:52:41 +0200125 tmpl = env.from_string(CONDEXPR)
126 assert tmpl.render() == '0'
127
128
Armin Ronacher42979eb2009-07-26 11:08:50 +0200129def test_short_conditional_expression():
Armin Ronacher547d0b62008-07-04 16:35:10 +0200130 tmpl = env.from_string('<{{ 1 if false }}>')
131 assert tmpl.render() == '<>'
132
133 tmpl = env.from_string('<{{ (1 if false).bar }}>')
Armin Ronacher42979eb2009-07-26 11:08:50 +0200134 assert_raises(UndefinedError, tmpl.render)
Armin Ronacher547d0b62008-07-04 16:35:10 +0200135
136
Armin Ronacher42979eb2009-07-26 11:08:50 +0200137def test_filter_priority():
Armin Ronacher1cc232c2007-09-07 17:52:41 +0200138 tmpl = env.from_string(FILTERPRIORITY)
139 assert tmpl.render() == 'FOOBAR'
140
141
Armin Ronacher42979eb2009-07-26 11:08:50 +0200142def test_function_calls():
Armin Ronacher1cc232c2007-09-07 17:52:41 +0200143 tests = [
144 (True, '*foo, bar'),
145 (True, '*foo, *bar'),
146 (True, '*foo, bar=42'),
147 (True, '**foo, *bar'),
148 (True, '**foo, bar'),
149 (False, 'foo, bar'),
150 (False, 'foo, bar=42'),
151 (False, 'foo, bar=23, *args'),
152 (False, 'a, b=c, *d, **e'),
153 (False, '*foo, **bar')
154 ]
155 for should_fail, sig in tests:
156 if should_fail:
Armin Ronacher42979eb2009-07-26 11:08:50 +0200157 assert_raises(TemplateSyntaxError, env.from_string, '{{ foo(%s) }}' % sig)
Armin Ronacher1cc232c2007-09-07 17:52:41 +0200158 else:
159 env.from_string('foo(%s)' % sig)
160
161
Armin Ronacher42979eb2009-07-26 11:08:50 +0200162def test_tuple_expr():
Armin Ronacher1cc232c2007-09-07 17:52:41 +0200163 for tmpl in TUPLETEMPLATES:
Armin Ronacher115de2e2008-05-01 22:20:05 +0200164 print tmpl
Armin Ronacher1cc232c2007-09-07 17:52:41 +0200165 assert env.from_string(tmpl)
166
167
Armin Ronacher42979eb2009-07-26 11:08:50 +0200168def test_trailing_comma():
Armin Ronacher1cc232c2007-09-07 17:52:41 +0200169 tmpl = env.from_string(TRAILINGCOMMA)
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200170 assert tmpl.render().lower() == '(1, 2)|[1, 2]|{1: 2}'
Armin Ronacherfd310492008-05-25 00:16:51 +0200171
172
Armin Ronacher42979eb2009-07-26 11:08:50 +0200173def test_block_end_name():
Armin Ronacherfd310492008-05-25 00:16:51 +0200174 env.from_string('{% block foo %}...{% endblock foo %}')
Armin Ronacher42979eb2009-07-26 11:08:50 +0200175 assert_raises(TemplateSyntaxError, env.from_string, '{% block x %}{% endblock y %}')
Armin Ronacher9bb7e472008-05-28 11:26:59 +0200176
177
Armin Ronacher42979eb2009-07-26 11:08:50 +0200178def test_contant_casing():
Armin Ronacher9bb7e472008-05-28 11:26:59 +0200179 for const in True, False, None:
180 tmpl = env.from_string('{{ %s }}|{{ %s }}|{{ %s }}' % (
181 str(const), str(const).lower(), str(const).upper()
182 ))
183 assert tmpl.render() == '%s|%s|' % (const, const)
Armin Ronachere3290ea2008-06-12 10:30:01 +0200184
185
Armin Ronacher42979eb2009-07-26 11:08:50 +0200186def test_test_chaining():
187 assert_raises(TemplateSyntaxError, env.from_string, '{{ foo is string is sequence }}')
Armin Ronachere3290ea2008-06-12 10:30:01 +0200188 env.from_string('{{ 42 is string or 42 is number }}').render() == 'True'
Armin Ronacher4778bda2008-06-22 12:48:37 +0200189
190
Armin Ronacher42979eb2009-07-26 11:08:50 +0200191def test_string_concatenation():
Armin Ronacher4778bda2008-06-22 12:48:37 +0200192 tmpl = env.from_string('{{ "foo" "bar" "baz" }}')
193 assert tmpl.render() == 'foobarbaz'
Armin Ronacherd89f0f32009-02-04 18:57:27 +0100194
195
Armin Ronacher42979eb2009-07-26 11:08:50 +0200196def test_notin():
Armin Ronacherd89f0f32009-02-04 18:57:27 +0100197 bar = xrange(100)
198 tmpl = env.from_string('''{{ not 42 in bar }}''')
199 assert tmpl.render(bar=bar) == unicode(not 42 in bar)
Armin Ronacheree2d3c42009-02-05 23:13:15 +0100200
201
Armin Ronacher42979eb2009-07-26 11:08:50 +0200202def test_implicit_subscribed_tuple():
Armin Ronacheree2d3c42009-02-05 23:13:15 +0100203 class Foo(object):
204 def __getitem__(self, x):
205 return x
206 t = env.from_string('{{ foo[1, 2] }}')
207 assert t.render(foo=Foo()) == u'(1, 2)'