summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArmin Ronacher <armin.ronacher@active-4.com>2010-10-17 15:53:59 +0200
committerArmin Ronacher <armin.ronacher@active-4.com>2010-10-17 15:53:59 +0200
commit613912d137bc4989f12d1964df97f79ab1e3be88 (patch)
treee5bd17cc03ed9d1c4407be06d27984e63a08a3bb
parent9dc0619d6528e9fbef328faf56a982d4af7379ba (diff)
downloadjinja2-613912d137bc4989f12d1964df97f79ab1e3be88.tar.gz
fixed an operator precedence error introduced in 2.5.2.2.5.3
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)".
-rw-r--r--CHANGES9
-rw-r--r--jinja2/parser.py22
-rw-r--r--jinja2/testsuite/lexnparse.py6
3 files changed, 33 insertions, 4 deletions
diff --git a/CHANGES b/CHANGES
index e31a32a..2d658a2 100644
--- 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)
diff --git a/jinja2/parser.py b/jinja2/parser.py
index 39713a1..d44229a 100644
--- a/jinja2/parser.py
+++ b/jinja2/parser.py
@@ -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
diff --git a/jinja2/testsuite/lexnparse.py b/jinja2/testsuite/lexnparse.py
index 9afbca4..008a0a9 100644
--- a/jinja2/testsuite/lexnparse.py
+++ b/jinja2/testsuite/lexnparse.py
@@ -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()