If jinja2 is iterating over a generator rather than a simple list, weird things happen. #555 is an example of this, but a simpler one I just ran in to is using the loop.revindex[0] special variables for length-1 lists. For example, in Python 3, if a list is reversed (using a filter in the template or a function in the script) then the loop indices are off-by-1.
Any other function/filter that yields a generator appears to be similarly affected, which is practically everything in Python 3 (e.g. map, zip).
My suggestion is for jinja to evaluate loop arguments once to form a list, iterate over that and hang the memory usage (which is default Python 2 behaviour), but that's not ideal..
import jinja2, sys
t = jinja2.Template(
"""
{%- for _ in l -%}
{{ loop.revindex }}, {{ loop.revindex0 }}, {{ loop.index }}, {{ loop.index0 }}
{%- endfor -%}
""")
print(t.render({'l' : [0]}))
print(t.render({'l' : reversed([0])}))
print(t.render({'l' : list(reversed([0]))}))
print(jinja2.__version__)
print(sys.version)
Python 3:
1, 0, 1, 0
2, 1, 1, 0
1, 0, 1, 0
2.9.6
3.5.2 (default, Nov 17 2016, 17:05:23)
[GCC 5.4.0 20160609]
Python 2:
1, 0, 1, 0
1, 0, 1, 0
1, 0, 1, 0
2.9.6
2.7.12 (default, Nov 19 2016, 06:48:10)
[GCC 5.4.0 20160609]
If jinja2 is iterating over a generator rather than a simple list, weird things happen. #555 is an example of this, but a simpler one I just ran in to is using the loop.revindex[0] special variables for length-1 lists. For example, in Python 3, if a list is reversed (using a filter in the template or a function in the script) then the loop indices are off-by-1.
Any other function/filter that yields a generator appears to be similarly affected, which is practically everything in Python 3 (e.g. map, zip).
My suggestion is for jinja to evaluate loop arguments once to form a list, iterate over that and hang the memory usage (which is default Python 2 behaviour), but that's not ideal..
Python 3:
Python 2: