implicit tuple expressions can no longer be totally empty.
authorArmin Ronacher <armin.ronacher@active-4.com>
Sat, 6 Feb 2010 14:04:46 +0000 (15:04 +0100)
committerArmin Ronacher <armin.ronacher@active-4.com>
Sat, 6 Feb 2010 14:04:46 +0000 (15:04 +0100)
This change makes ``{% if %}...{% endif %}`` a syntax error
now. (#364)

--HG--
branch : trunk

CHANGES
jinja2/parser.py
tests/test_old_bugs.py

diff --git a/CHANGES b/CHANGES
index 2b3fbc5bd58b499a325c1857d7c86c9751d50c5c..787292146400ff707ad8687bf8595af3bf2b20d6 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -13,8 +13,11 @@ Version 2.3
   given.
 - fixed a problem with having call blocks in outer scopes that
   have an argument that is also used as local variable in an
-  inner frame [#360].
+  inner frame (#360).
 - greatly improved error message reporting (#339)
+- implicit tuple expressions can no longer be totally empty.
+  This change makes ``{% if %}...{% endif %}`` a syntax error
+  now. (#364)
 
 Version 2.2.1
 -------------
index fa1290c35a074a9ece104f6d42537a9c47ec969e..bc4925e4d445bbf2370310c122850f3aea3eae04 100644 (file)
@@ -548,7 +548,7 @@ class Parser(object):
             node = nodes.Const(token.value, lineno=token.lineno)
         elif token.type == 'lparen':
             next(self.stream)
-            node = self.parse_tuple()
+            node = self.parse_tuple(explicit_parentheses=True)
             self.stream.expect('rparen')
         elif token.type == 'lbracket':
             node = self.parse_list()
@@ -561,7 +561,7 @@ class Parser(object):
         return node
 
     def parse_tuple(self, simplified=False, with_condexpr=True,
-                    extra_end_rules=None):
+                    extra_end_rules=None, explicit_parentheses=False):
         """Works like `parse_expression` but if multiple expressions are
         delimited by a comma a :class:`~jinja2.nodes.Tuple` node is created.
         This method could also return a regular expression instead of a tuple
@@ -575,6 +575,10 @@ class Parser(object):
         an extra hint is needed that marks the end of a tuple.  For example
         for loops support tuples between `for` and `in`.  In that case the
         `extra_end_rules` is set to ``['name:in']``.
+
+        `explicit_parentheses` is true if the parsing was triggered by an
+        expression in parentheses.  This is used to figure out if an empty
+        tuple is a valid expression or not.
         """
         lineno = self.stream.current.lineno
         if simplified:
@@ -596,8 +600,19 @@ class Parser(object):
             else:
                 break
             lineno = self.stream.current.lineno
-        if not is_tuple and args:
-            return args[0]
+
+        if not is_tuple:
+            if args:
+                return args[0]
+
+            # if we don't have explicit parentheses, an empty tuple is
+            # not a valid expression.  This would mean nothing (literally
+            # nothing) in the spot of an expression would be an empty
+            # tuple.
+            if not explicit_parentheses:
+                self.fail('Expected an expression, got \'%s\'' %
+                          describe_token(self.stream.current))
+
         return nodes.Tuple(args, 'load', lineno=lineno)
 
     def parse_list(self):
index e3a403bdd5d075c935ab7ba2e969532bbe551a76..98db1b3b33cbb1cf675bb3f1e011b78c3362d2e7 100644 (file)
@@ -134,3 +134,9 @@ def test_call_with_args():
         u'</dl>',
         u'</li></ul>'
     ]
+
+
+def test_empty_if_condition_fails():
+    assert_raises(TemplateSyntaxError, Template, '{% if %}....{% endif %}')
+    assert_raises(TemplateSyntaxError, Template, '{% if foo %}...{% elif %}...{% endif %}')
+    assert_raises(TemplateSyntaxError, Template, '{% for x in %}..{% endfor %}')