# pallets/jinja

Fixed loop.last to not consume the entire iterator to determine if th…

```…is is

the last iteration of the loop.```
1 parent 5145401 commit 776567cc4e87f26ad57b52bb16c5462a281b4ca3 Jason Kotenko committed Jan 24, 2012
Showing with 14 additions and 2 deletions.
1. +14 −2 jinja2/runtime.py
 @@ -266,10 +266,12 @@ def __call__(self): class LoopContext(object): """A loop context for dynamic iteration.""" + End = object() def __init__(self, iterable, recurse=None): self._iterator = iter(iterable) self._recurse = recurse + self._after = self._safe_next() self.index0 = -1 # try to get the length of the iterable early. This must be done @@ -288,7 +290,7 @@ def cycle(self, *args): return args[self.index0 % len(args)] first = property(lambda x: x.index0 == 0) - last = property(lambda x: x.index0 + 1 == x.length) + last = property(lambda x: x._after is LoopContext.End) index = property(lambda x: x.index0 + 1) revindex = property(lambda x: x.length - x.index0) revindex0 = property(lambda x: x.length - x.index) @@ -299,6 +301,12 @@ def __len__(self): def __iter__(self): return LoopContextIterator(self) + def _safe_next(self): + try: + return next(self._iterator) + except StopIteration: + return self.End + @internalcode def loop(self, iterable): if self._recurse is None: @@ -344,7 +352,11 @@ def __iter__(self): def next(self): ctx = self.context ctx.index0 += 1 - return next(ctx._iterator), ctx + if ctx._after is LoopContext.End: + raise StopIteration + next_elem = ctx._after + ctx._after = ctx._safe_next() + return next_elem, ctx class Macro(object):