Author: lukeplant
Date: 2010-03-08 17:25:37 -0600 (Mon, 08 Mar 2010)
New Revision: 12732

Modified:
   django/trunk/django/template/defaulttags.py
   django/trunk/django/template/smartif.py
   django/trunk/docs/ref/templates/builtins.txt
   django/trunk/docs/releases/1.2.txt
   django/trunk/tests/regressiontests/templates/smartif.py
   django/trunk/tests/regressiontests/templates/tests.py
Log:
Fixed #13058 - "smart if" template tag doesn't support "if not in ..." 
condition                                                                       
                                                  

Thanks to ramusus for the report.



Modified: django/trunk/django/template/defaulttags.py
===================================================================
--- django/trunk/django/template/defaulttags.py 2010-03-08 20:53:51 UTC (rev 
12731)
+++ django/trunk/django/template/defaulttags.py 2010-03-08 23:25:37 UTC (rev 
12732)
@@ -806,8 +806,8 @@
     Arguments and operators _must_ have a space between them, so
     ``{% if 1>2 %}`` is not a valid if tag.
 
-    All supported operators are: ``or``, ``and``, ``in``, ``==`` (or ``=``),
-    ``!=``, ``>``, ``>=``, ``<`` and ``<=``.
+    All supported operators are: ``or``, ``and``, ``in``, ``not in``
+    ``==`` (or ``=``), ``!=``, ``>``, ``>=``, ``<`` and ``<=``.
 
     Operator precedence follows Python.
     """

Modified: django/trunk/django/template/smartif.py
===================================================================
--- django/trunk/django/template/smartif.py     2010-03-08 20:53:51 UTC (rev 
12731)
+++ django/trunk/django/template/smartif.py     2010-03-08 23:25:37 UTC (rev 
12732)
@@ -97,6 +97,7 @@
     'and': infix(7, lambda x, y: x and y),
     'not': prefix(8, operator.not_),
     'in': infix(9, lambda x, y: x in y),
+    'not in': infix(9, lambda x, y: x not in y),
     '=': infix(10, operator.eq),
     '==': infix(10, operator.eq),
     '!=': infix(10, operator.ne),
@@ -150,11 +151,23 @@
     error_class = ValueError
 
     def __init__(self, tokens):
-        self.tokens = map(self.translate_tokens, tokens)
+        # pre-pass necessary to turn  'not','in' into single token 
+        l = len(tokens)
+        mapped_tokens = []
+        i = 0
+        while i < l:
+            token = tokens[i]
+            if token == "not" and i + 1 < l and tokens[i+1] == "in":
+                token = "not in"
+                i += 1 # skip 'in'
+            mapped_tokens.append(self.translate_token(token))
+            i += 1
+
+        self.tokens = mapped_tokens
         self.pos = 0
         self.current_token = self.next()
 
-    def translate_tokens(self, token):
+    def translate_token(self, token):
         try:
             op = OPERATORS[token]
         except (KeyError, TypeError):

Modified: django/trunk/docs/ref/templates/builtins.txt
===================================================================
--- django/trunk/docs/ref/templates/builtins.txt        2010-03-08 20:53:51 UTC 
(rev 12731)
+++ django/trunk/docs/ref/templates/builtins.txt        2010-03-08 23:25:37 UTC 
(rev 12732)
@@ -440,7 +440,12 @@
       instance that belongs to the QuerySet.
     {% endif %}
 
+``not in`` operator
+~~~~~~~~~~~~~~~~~~~~
 
+Not contained within.  This is the negation of the ``in`` operator.
+
+
 The comparison operators cannot be 'chained' like in Python or in mathematical
 notation. For example, instead of using::
 

Modified: django/trunk/docs/releases/1.2.txt
===================================================================
--- django/trunk/docs/releases/1.2.txt  2010-03-08 20:53:51 UTC (rev 12731)
+++ django/trunk/docs/releases/1.2.txt  2010-03-08 23:25:37 UTC (rev 12732)
@@ -636,9 +636,9 @@
 There's really no reason to use ``{% ifequal %}`` or ``{% ifnotequal %}``
 anymore, unless you're the nostalgic type.
 
-The operators supported are ``==``, ``!=``, ``<``, ``>``, ``<=``, ``>=`` and
-``in``, all of which work like the Python operators, in addition to ``and``,
-``or`` and ``not``, which were already supported.
+The operators supported are ``==``, ``!=``, ``<``, ``>``, ``<=``, ``>=``,
+``in`` and ``not in``, all of which work like the Python operators, in addition
+ to ``and``, ``or`` and ``not``, which were already supported.
 
 Also, filters may now be used in the ``if`` expression. For example:
 

Modified: django/trunk/tests/regressiontests/templates/smartif.py
===================================================================
--- django/trunk/tests/regressiontests/templates/smartif.py     2010-03-08 
20:53:51 UTC (rev 12731)
+++ django/trunk/tests/regressiontests/templates/smartif.py     2010-03-08 
23:25:37 UTC (rev 12732)
@@ -27,6 +27,13 @@
         self.assertCalcEqual(False, [1, 'in', None])
         self.assertCalcEqual(False, [None, 'in', list_])
 
+    def test_not_in(self):
+        list_ = [1,2,3]
+        self.assertCalcEqual(False, [1, 'not', 'in', list_])
+        self.assertCalcEqual(True, [4, 'not', 'in', list_])
+        self.assertCalcEqual(False, [1, 'not', 'in', None])
+        self.assertCalcEqual(True, [None, 'not', 'in', list_])
+
     def test_precedence(self):
         # (False and False) or True == True   <- we want this one, like Python
         # False and (False or True) == False

Modified: django/trunk/tests/regressiontests/templates/tests.py
===================================================================
--- django/trunk/tests/regressiontests/templates/tests.py       2010-03-08 
20:53:51 UTC (rev 12731)
+++ django/trunk/tests/regressiontests/templates/tests.py       2010-03-08 
23:25:37 UTC (rev 12732)
@@ -611,6 +611,12 @@
             'if-tag-lte-01': ("{% if 1 <= 1 %}yes{% else %}no{% endif %}", {}, 
"yes"),
             'if-tag-lte-02': ("{% if 2 <= 1 %}yes{% else %}no{% endif %}", {}, 
"no"),
 
+            # Contains
+            'if-tag-in-01': ("{% if 1 in x %}yes{% else %}no{% endif %}", 
{'x':[1]}, "yes"),
+            'if-tag-in-02': ("{% if 2 in x %}yes{% else %}no{% endif %}", 
{'x':[1]}, "no"),
+            'if-tag-not-in-01': ("{% if 1 not in x %}yes{% else %}no{% endif 
%}", {'x':[1]}, "no"),
+            'if-tag-not-in-02': ("{% if 2 not in x %}yes{% else %}no{% endif 
%}", {'x':[1]}, "yes"),
+
             # AND
             'if-tag-and01': ("{% if foo and bar %}yes{% else %}no{% endif %}", 
{'foo': True, 'bar': True}, 'yes'),
             'if-tag-and02': ("{% if foo and bar %}yes{% else %}no{% endif %}", 
{'foo': True, 'bar': False}, 'no'),

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to django-upda...@googlegroups.com.
To unsubscribe from this group, send email to 
django-updates+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en.

Reply via email to