lexnparse.py (10217B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\lib\jinja2\testsuite\lexnparse.py 2 import sys 3 import unittest 4 from jinja2.testsuite import JinjaTestCase 5 from jinja2 import Environment, Template, TemplateSyntaxError, UndefinedError, nodes 6 env = Environment() 7 if sys.version_info < (3, 0): 8 9 def jinja_string_repr(string): 10 return repr(string)[1:] 11 12 13 else: 14 jinja_string_repr = repr 15 16 class LexerTestCase(JinjaTestCase): 17 18 def test_raw1(self): 19 tmpl = env.from_string('{% raw %}foo{% endraw %}|{%raw%}{{ bar }}|{% baz %}{% endraw %}') 20 21 def test_raw2(self): 22 tmpl = env.from_string('1 {%- raw -%} 2 {%- endraw -%} 3') 23 24 def test_balancing(self): 25 env = Environment('{%', '%}', '${', '}') 26 tmpl = env.from_string("{% for item in seq\n %}${{'foo': item}|upper}{% endfor %}") 27 28 def test_comments(self): 29 env = Environment('<!--', '-->', '{', '}') 30 tmpl = env.from_string('<ul>\n<!--- for item in seq -->\n <li>{item}</li>\n<!--- endfor -->\n</ul>') 31 32 def test_string_escapes(self): 33 for char in (u'\x00', u'\u2668', u'\xe4', u'\t', u'\r', u'\n'): 34 tmpl = env.from_string('{{ %s }}' % jinja_string_repr(char)) 35 36 def test_bytefallback(self): 37 from pprint import pformat 38 tmpl = env.from_string(u"{{ 'foo'|pprint }}|{{ 'b\xe4r'|pprint }}") 39 40 def test_operators(self): 41 from jinja2.lexer import operators 42 for test, expect in operators.iteritems(): 43 if test in '([{}])': 44 continue 45 stream = env.lexer.tokenize('{{ %s }}' % test) 46 stream.next() 47 48 def test_normalizing(self): 49 for seq in ('\r', '\r\n', '\n'): 50 env = Environment(newline_sequence=seq) 51 tmpl = env.from_string('1\n2\r\n3\n4\n') 52 result = tmpl.render() 53 54 55 class ParserTestCase(JinjaTestCase): 56 57 def test_php_syntax(self): 58 env = Environment('<?', '?>', '<?=', '?>', '<!--', '-->') 59 tmpl = env.from_string("<!-- I'm a comment, I'm not interesting --><? for item in seq -?>\n <?= item ?>\n<?- endfor ?>") 60 61 def test_erb_syntax(self): 62 env = Environment('<%', '%>', '<%=', '%>', '<%#', '%>') 63 tmpl = env.from_string("<%# I'm a comment, I'm not interesting %><% for item in seq -%>\n <%= item %>\n<%- endfor %>") 64 65 def test_comment_syntax(self): 66 env = Environment('<!--', '-->', '${', '}', '<!--#', '-->') 67 tmpl = env.from_string("<!--# I'm a comment, I'm not interesting --><!-- for item in seq --->\n ${item}\n<!--- endfor -->") 68 69 def test_balancing(self): 70 tmpl = env.from_string("{{{'foo':'bar'}.foo}}") 71 72 def test_start_comment(self): 73 tmpl = env.from_string('{# foo comment\nand bar comment #}\n{% macro blub() %}foo{% endmacro %}\n{{ blub() }}') 74 75 def test_line_syntax(self): 76 env = Environment('<%', '%>', '${', '}', '<%#', '%>', '%') 77 tmpl = env.from_string('<%# regular comment %>\n% for item in seq:\n ${item}\n% endfor') 78 env = Environment('<%', '%>', '${', '}', '<%#', '%>', '%', '##') 79 tmpl = env.from_string('<%# regular comment %>\n% for item in seq:\n ${item} ## the rest of the stuff\n% endfor') 80 81 def test_line_syntax_priority(self): 82 env = Environment('{%', '%}', '${', '}', '/*', '*/', '##', '#') 83 tmpl = env.from_string("/* ignore me.\n I'm a multiline comment */\n## for item in seq:\n* ${item} # this is just extra stuff\n## endfor") 84 env = Environment('{%', '%}', '${', '}', '/*', '*/', '#', '##') 85 tmpl = env.from_string("/* ignore me.\n I'm a multiline comment */\n# for item in seq:\n* ${item} ## this is just extra stuff\n ## extra stuff i just want to ignore\n# endfor") 86 87 def test_error_messages(self): 88 89 def assert_error(code, expected): 90 try: 91 Template(code) 92 except TemplateSyntaxError as e: 93 pass 94 95 assert_error('{% for item in seq %}...{% endif %}', "Encountered unknown tag 'endif'. Jinja was looking for the following tags: 'endfor' or 'else'. The innermost block that needs to be closed is 'for'.") 96 assert_error('{% if foo %}{% for item in seq %}...{% endfor %}{% endfor %}', "Encountered unknown tag 'endfor'. Jinja was looking for the following tags: 'elif' or 'else' or 'endif'. The innermost block that needs to be closed is 'if'.") 97 assert_error('{% if foo %}', "Unexpected end of template. Jinja was looking for the following tags: 'elif' or 'else' or 'endif'. The innermost block that needs to be closed is 'if'.") 98 assert_error('{% for item in seq %}', "Unexpected end of template. Jinja was looking for the following tags: 'endfor' or 'else'. The innermost block that needs to be closed is 'for'.") 99 assert_error('{% block foo-bar-baz %}', 'Block names in Jinja have to be valid Python identifiers and may not contain hyphens, use an underscore instead.') 100 assert_error('{% unknown_tag %}', "Encountered unknown tag 'unknown_tag'.") 101 102 103 class SyntaxTestCase(JinjaTestCase): 104 105 def test_call(self): 106 env = Environment() 107 env.globals['foo'] = lambda a, b, c, e, g: a + b + c + e + g 108 tmpl = env.from_string("{{ foo('a', c='d', e='f', *['b'], **{'g': 'h'}) }}") 109 110 def test_slicing(self): 111 tmpl = env.from_string('{{ [1, 2, 3][:] }}|{{ [1, 2, 3][::-1] }}') 112 113 def test_attr(self): 114 tmpl = env.from_string("{{ foo.bar }}|{{ foo['bar'] }}") 115 116 def test_subscript(self): 117 tmpl = env.from_string('{{ foo[0] }}|{{ foo[-1] }}') 118 119 def test_tuple(self): 120 tmpl = env.from_string('{{ () }}|{{ (1,) }}|{{ (1, 2) }}') 121 122 def test_math(self): 123 tmpl = env.from_string('{{ (1 + 1 * 2) - 3 / 2 }}|{{ 2**3 }}') 124 125 def test_div(self): 126 tmpl = env.from_string('{{ 3 // 2 }}|{{ 3 / 2 }}|{{ 3 % 2 }}') 127 128 def test_unary(self): 129 tmpl = env.from_string('{{ +3 }}|{{ -3 }}') 130 131 def test_concat(self): 132 tmpl = env.from_string("{{ [1, 2] ~ 'foo' }}") 133 134 def test_compare(self): 135 tmpl = env.from_string('{{ 1 > 0 }}|{{ 1 >= 1 }}|{{ 2 < 3 }}|{{ 2 == 2 }}|{{ 1 <= 1 }}') 136 137 def test_inop(self): 138 tmpl = env.from_string('{{ 1 in [1, 2, 3] }}|{{ 1 not in [1, 2, 3] }}') 139 140 def test_literals(self): 141 tmpl = env.from_string('{{ [] }}|{{ {} }}|{{ () }}') 142 143 def test_bool(self): 144 tmpl = env.from_string('{{ true and false }}|{{ false or true }}|{{ not false }}') 145 146 def test_grouping(self): 147 tmpl = env.from_string('{{ (true and false) or (false and true) and not false }}') 148 149 def test_django_attr(self): 150 tmpl = env.from_string('{{ [1, 2, 3].0 }}|{{ [[1]].0.0 }}') 151 152 def test_conditional_expression(self): 153 tmpl = env.from_string('{{ 0 if true else 1 }}') 154 155 def test_short_conditional_expression(self): 156 tmpl = env.from_string('<{{ 1 if false }}>') 157 tmpl = env.from_string('<{{ (1 if false).bar }}>') 158 self.assert_raises(UndefinedError, tmpl.render) 159 160 def test_filter_priority(self): 161 tmpl = env.from_string('{{ "foo"|upper + "bar"|upper }}') 162 163 def test_function_calls(self): 164 tests = [(True, '*foo, bar'), 165 (True, '*foo, *bar'), 166 (True, '*foo, bar=42'), 167 (True, '**foo, *bar'), 168 (True, '**foo, bar'), 169 (False, 'foo, bar'), 170 (False, 'foo, bar=42'), 171 (False, 'foo, bar=23, *args'), 172 (False, 'a, b=c, *d, **e'), 173 (False, '*foo, **bar')] 174 for should_fail, sig in tests: 175 if should_fail: 176 self.assert_raises(TemplateSyntaxError, env.from_string, '{{ foo(%s) }}' % sig) 177 else: 178 env.from_string('foo(%s)' % sig) 179 180 def test_tuple_expr(self): 181 for tmpl in ['{{ () }}', 182 '{{ (1, 2) }}', 183 '{{ (1, 2,) }}', 184 '{{ 1, }}', 185 '{{ 1, 2 }}', 186 '{% for foo, bar in seq %}...{% endfor %}', 187 '{% for x in foo, bar %}...{% endfor %}', 188 '{% for x in foo, %}...{% endfor %}']: 189 pass 190 191 def test_trailing_comma(self): 192 tmpl = env.from_string('{{ (1, 2,) }}|{{ [1, 2,] }}|{{ {1: 2,} }}') 193 194 def test_block_end_name(self): 195 env.from_string('{% block foo %}...{% endblock foo %}') 196 self.assert_raises(TemplateSyntaxError, env.from_string, '{% block x %}{% endblock y %}') 197 198 def test_constant_casing(self): 199 for const in (True, False, None): 200 tmpl = env.from_string('{{ %s }}|{{ %s }}|{{ %s }}' % (str(const), str(const).lower(), str(const).upper())) 201 202 def test_test_chaining(self): 203 self.assert_raises(TemplateSyntaxError, env.from_string, '{{ foo is string is sequence }}') 204 205 def test_string_concatenation(self): 206 tmpl = env.from_string('{{ "foo" "bar" "baz" }}') 207 208 def test_notin(self): 209 bar = xrange(100) 210 tmpl = env.from_string('{{ not 42 in bar }}') 211 212 def test_implicit_subscribed_tuple(self): 213 214 class Foo(object): 215 216 def __getitem__(self, x): 217 return x 218 219 t = env.from_string('{{ foo[1, 2] }}') 220 221 def test_raw2(self): 222 tmpl = env.from_string('{% raw %}{{ FOO }} and {% BAR %}{% endraw %}') 223 224 def test_const(self): 225 tmpl = env.from_string('{{ true }}|{{ false }}|{{ none }}|{{ none is defined }}|{{ missing is defined }}') 226 227 def test_neg_filter_priority(self): 228 node = env.parse('{{ -1|foo }}') 229 230 def test_const_assign(self): 231 constass1 = '{% set true = 42 %}' 232 constass2 = '{% for none in seq %}{% endfor %}' 233 for tmpl in (constass1, constass2): 234 self.assert_raises(TemplateSyntaxError, env.from_string, tmpl) 235 236 def test_localset(self): 237 tmpl = env.from_string('{% set foo = 0 %}{% for item in [1, 2] %}{% set foo = 1 %}{% endfor %}{{ foo }}') 238 239 def test_parse_unary(self): 240 tmpl = env.from_string('{{ -foo["bar"] }}') 241 tmpl = env.from_string('{{ -foo["bar"]|abs }}') 242 243 244 def suite(): 245 suite = unittest.TestSuite() 246 suite.addTest(unittest.makeSuite(LexerTestCase)) 247 suite.addTest(unittest.makeSuite(ParserTestCase)) 248 suite.addTest(unittest.makeSuite(SyntaxTestCase)) 249 return suite