]> git.ipfire.org Git - thirdparty/jinja.git/commitdiff
Fix loop context length calculation for iterators. Fixes #244 315/head
authorChristoph Reiter <reiter.christoph@gmail.com>
Sun, 30 Mar 2014 15:40:08 +0000 (17:40 +0200)
committerChristoph Reiter <reiter.christoph@gmail.com>
Sun, 30 Mar 2014 15:40:08 +0000 (17:40 +0200)
This resulted in wrong values for revindex and revindex0
while looping over an iterator.

jinja2/runtime.py
jinja2/testsuite/core_tags.py

index efd67e1a2b916e4352ffc36ebea510d8e5641d0d..7517cc54637b01ebc36b1c608255c84d435afe04 100644 (file)
@@ -339,10 +339,11 @@ class LoopContext(object):
             # if was not possible to get the length of the iterator when
             # the loop context was created (ie: iterating over a generator)
             # we have to convert the iterable into a sequence and use the
-            # length of that.
+            # length of that + the number of iterations so far.
             iterable = tuple(self._iterator)
             self._iterator = iter(iterable)
-            self._length = len(iterable) + self.index0 + 1
+            iterations_done = self.index0 + 2
+            self._length = len(iterable) + iterations_done
         return self._length
 
     def __repr__(self):
index f1a20fd44d60c6d43f3a85656d9cac529cae746b..d4c44c42217bc1aa1c7888d349b4dede89ee4504 100644 (file)
@@ -33,23 +33,25 @@ class ForLoopTestCase(JinjaTestCase):
         assert tmpl.render() == '<>'
 
     def test_context_vars(self):
-        tmpl = env.from_string('''{% for item in seq -%}
-        {{ loop.index }}|{{ loop.index0 }}|{{ loop.revindex }}|{{
-            loop.revindex0 }}|{{ loop.first }}|{{ loop.last }}|{{
-           loop.length }}###{% endfor %}''')
-        one, two, _ = tmpl.render(seq=[0, 1]).split('###')
-        (one_index, one_index0, one_revindex, one_revindex0, one_first,
-         one_last, one_length) = one.split('|')
-        (two_index, two_index0, two_revindex, two_revindex0, two_first,
-         two_last, two_length) = two.split('|')
-
-        assert int(one_index) == 1 and int(two_index) == 2
-        assert int(one_index0) == 0 and int(two_index0) == 1
-        assert int(one_revindex) == 2 and int(two_revindex) == 1
-        assert int(one_revindex0) == 1 and int(two_revindex0) == 0
-        assert one_first == 'True' and two_first == 'False'
-        assert one_last == 'False' and two_last == 'True'
-        assert one_length == two_length == '2'
+        slist = [42, 24]
+        for seq in [slist, iter(slist), reversed(slist), (_ for _ in slist)]:
+            tmpl = env.from_string('''{% for item in seq -%}
+            {{ loop.index }}|{{ loop.index0 }}|{{ loop.revindex }}|{{
+                loop.revindex0 }}|{{ loop.first }}|{{ loop.last }}|{{
+               loop.length }}###{% endfor %}''')
+            one, two, _ = tmpl.render(seq=seq).split('###')
+            (one_index, one_index0, one_revindex, one_revindex0, one_first,
+             one_last, one_length) = one.split('|')
+            (two_index, two_index0, two_revindex, two_revindex0, two_first,
+             two_last, two_length) = two.split('|')
+
+            assert int(one_index) == 1 and int(two_index) == 2
+            assert int(one_index0) == 0 and int(two_index0) == 1
+            assert int(one_revindex) == 2 and int(two_revindex) == 1
+            assert int(one_revindex0) == 1 and int(two_revindex0) == 0
+            assert one_first == 'True' and two_first == 'False'
+            assert one_last == 'False' and two_last == 'True'
+            assert one_length == two_length == '2'
 
     def test_cycling(self):
         tmpl = env.from_string('''{% for item in seq %}{{