Priority of `not` raised. It's now possible to write `not foo in bar`
as an alias to `foo not in bar` like in python. Previously the grammar
required parentheses (`not (foo in bar)`) which was odd.
--HG--
branch : trunk
diff --git a/.hgignore b/.hgignore
index 0aa46ee..eebc869 100644
--- a/.hgignore
+++ b/.hgignore
@@ -5,3 +5,4 @@
^(build|dist|Jinja2\.egg-info)/
\.py[co]$
\.DS_Store$
+^env/
diff --git a/CHANGES b/CHANGES
index ab75555..9911301 100644
--- a/CHANGES
+++ b/CHANGES
@@ -7,6 +7,9 @@
- Include statements can now be marked with ``ignore missing`` to skip
non existing templates.
+- Priority of `not` raised. It's now possible to write `not foo in bar`
+ as an alias to `foo not in bar` like in python. Previously the grammar
+ required parentheses (`not (foo in bar)`) which was odd.
Version 2.1.1
-------------
diff --git a/docs/_static/style.css b/docs/_static/style.css
index e6238d5..a1c4d59 100644
--- a/docs/_static/style.css
+++ b/docs/_static/style.css
@@ -253,6 +253,7 @@
h4:hover > a.headerlink,
h5:hover > a.headerlink,
h6:hover > a.headerlink,
+dt:hover > a.headerlink,
dt:hover > a.headerlink {
visibility: visible;
}
diff --git a/docs/cache_extension.py b/docs/cache_extension.py
index ec0067b..c736a65 100644
--- a/docs/cache_extension.py
+++ b/docs/cache_extension.py
@@ -51,6 +51,6 @@
rv = self.environment.fragment_cache.get(key)
if rv is None:
return rv
- rv = caller()
- self.environment.fragment_cache.add(key, rv, timeout)
+ rv = caller()
+ self.environment.fragment_cache.add(key, rv, timeout)
return rv
diff --git a/jinja2/parser.py b/jinja2/parser.py
index c607540..b6e23df 100644
--- a/jinja2/parser.py
+++ b/jinja2/parser.py
@@ -333,13 +333,19 @@
def parse_and(self):
lineno = self.stream.current.lineno
- left = self.parse_compare()
+ left = self.parse_not()
while self.stream.skip_if('name:and'):
- right = self.parse_compare()
+ right = self.parse_not()
left = nodes.And(left, right, lineno=lineno)
lineno = self.stream.current.lineno
return left
+ def parse_not(self):
+ if self.stream.current.test('name:not'):
+ lineno = self.stream.next().lineno
+ return nodes.Not(self.parse_not(), lineno=lineno)
+ return self.parse_compare()
+
def parse_compare(self):
lineno = self.stream.current.lineno
expr = self.parse_add()
@@ -445,10 +451,6 @@
def parse_unary(self):
token_type = self.stream.current.type
lineno = self.stream.current.lineno
- if token_type == 'name' and self.stream.current.value == 'not':
- self.stream.next()
- node = self.parse_unary()
- return nodes.Not(node, lineno=lineno)
if token_type == 'sub':
self.stream.next()
node = self.parse_unary()
diff --git a/tests/test_syntax.py b/tests/test_syntax.py
index 8d14c66..2a8e46f 100644
--- a/tests/test_syntax.py
+++ b/tests/test_syntax.py
@@ -189,3 +189,9 @@
def test_string_concatenation(env):
tmpl = env.from_string('{{ "foo" "bar" "baz" }}')
assert tmpl.render() == 'foobarbaz'
+
+
+def test_notin(env):
+ bar = xrange(100)
+ tmpl = env.from_string('''{{ not 42 in bar }}''')
+ assert tmpl.render(bar=bar) == unicode(not 42 in bar)