Closed frmdstryr closed 4 years ago
This is quite tricky since even if we were re-reading each time you could still get bitten by doing attr my_items = reversed(range(10))
.
One thing we could do is test that the iterable is safe to iter multiple times using the following:
it1 = iter(self.iterable)
it2 = iter(self.iterable)
if next(it1) != next(it2):
raise ValueError("Iterable in Looper needs to be safe to iterate multiple times"
Testing this with range(10) works but fails with reversed(range(10))
Actually a better option would be to test that we get an iterable that is not an iterator using collections.abc.Iterator
, that would be cleaner. Care to do a PR for that ?
This took me several hours to debug in a large application...
If the
Looper
is given a generator as it's iterable, eg,reversed
orenumerate
and the items are refreshed multiple times without theiterable
actually being updated (and thus reset) the iterable reaches the end and removes all items added to the looper!This reproduces it:
It works fine if the combo is changed from
a
tob
thenc
(it shows all labels from 0 to 9) but if you go straight froma
toc
the Looper removes all the items because the multiple levels of conditionals cause the looper to be refreshed multiple times without resetting the iterable back to the start.I think to fix this iterable needs to be re-read from the expression engine every time it's refreshed.