fixed an operator precedence error introduced in 2.5.2. 2.5.3
authorArmin Ronacher <armin.ronacher@active-4.com>
Sun, 17 Oct 2010 13:53:59 +0000 (15:53 +0200)
committerArmin Ronacher <armin.ronacher@active-4.com>
Sun, 17 Oct 2010 13:53:59 +0000 (15:53 +0200)
Statements like "-foo.bar" had their implicit parentheses applied around
the first part of the expression ("(-foo).bar") instead of the more
correct "-(foo.bar)".

CHANGES
jinja2/parser.py
jinja2/testsuite/lexnparse.py

diff --git a/CHANGES b/CHANGES
index e31a32a8d00030fcde8b40a74285043a8bd60d1a..2d658a2c4554b7467ee56567ba85bad17e5e701e 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,15 @@
 Jinja2 Changelog
 ================
 
+Version 2.5.3
+-------------
+(bugfix release, release date to be announced)
+
+- fixed an operator precedence error introduced in 2.5.2.  Statements
+  like "-foo.bar" had their implicit parentheses applied around the
+  first part of the expression ("(-foo).bar") instead of the more
+  correct "-(foo.bar)".
+
 Version 2.5.2
 -------------
 (bugfix release, released on August 18th 2010)
index 39713a1fe991af3e260841ba928476fef9432853..d44229ad0f09a562bbf67de4a5daf5d5730456ab 100644 (file)
@@ -525,7 +525,7 @@ class Parser(object):
             lineno = self.stream.current.lineno
         return left
 
-    def parse_unary(self, with_postfix=True):
+    def parse_unary(self, with_filter=True):
         token_type = self.stream.current.type
         lineno = self.stream.current.lineno
         if token_type == 'sub':
@@ -536,8 +536,9 @@ class Parser(object):
             node = nodes.Pos(self.parse_unary(False), lineno=lineno)
         else:
             node = self.parse_primary()
-        if with_postfix:
-            node = self.parse_postfix(node)
+        node = self.parse_postfix(node)
+        if with_filter:
+            node = self.parse_filter_expr(node)
         return node
 
     def parse_primary(self):
@@ -661,12 +662,25 @@ class Parser(object):
             token_type = self.stream.current.type
             if token_type == 'dot' or token_type == 'lbracket':
                 node = self.parse_subscript(node)
+            # calls are valid both after postfix expressions (getattr
+            # and getitem) as well as filters and tests
             elif token_type == 'lparen':
                 node = self.parse_call(node)
-            elif token_type == 'pipe':
+            else:
+                break
+        return node
+
+    def parse_filter_expr(self, node):
+        while 1:
+            token_type = self.stream.current.type
+            if token_type == 'pipe':
                 node = self.parse_filter(node)
             elif token_type == 'name' and self.stream.current.value == 'is':
                 node = self.parse_test(node)
+            # calls are valid both after postfix expressions (getattr
+            # and getitem) as well as filters and tests
+            elif token_type == 'lparen':
+                node = self.parse_call(node)
             else:
                 break
         return node
index 9afbca47d132dd47778a2d3c3efbd8845bc52520..008a0a914f4aebf17f4d8bb3dbf3c92aba43d3d5 100644 (file)
@@ -375,6 +375,12 @@ class SyntaxTestCase(JinjaTestCase):
 {{ foo }}''')
         assert tmpl.render() == '0'
 
+    def test_parse_unary(self):
+        tmpl = env.from_string('{{ -foo["bar"] }}')
+        assert tmpl.render(foo={'bar': 42}) == '-42'
+        tmpl = env.from_string('{{ -foo["bar"]|abs }}')
+        assert tmpl.render(foo={'bar': 42}) == '42'
+
 
 def suite():
     suite = unittest.TestSuite()