From: Christoph Reiter Date: Sun, 30 Mar 2014 15:40:08 +0000 (+0200) Subject: Fix loop context length calculation for iterators. Fixes #244 X-Git-Tag: 2.8~83^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F315%2Fhead;p=thirdparty%2Fjinja.git Fix loop context length calculation for iterators. Fixes #244 This resulted in wrong values for revindex and revindex0 while looping over an iterator. --- diff --git a/jinja2/runtime.py b/jinja2/runtime.py index efd67e1a..7517cc54 100644 --- a/jinja2/runtime.py +++ b/jinja2/runtime.py @@ -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): diff --git a/jinja2/testsuite/core_tags.py b/jinja2/testsuite/core_tags.py index f1a20fd4..d4c44c42 100644 --- a/jinja2/testsuite/core_tags.py +++ b/jinja2/testsuite/core_tags.py @@ -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 %}{{