factory_boy icon indicating copy to clipboard operation
factory_boy copied to clipboard

Helpful message when Iterator has empty iterator

Open 0ge opened this issue 3 years ago • 2 comments

The problem

If you pass in an empty iterator to Iterator, you get a (for me) cryptic StopIteration. It took quite a while for me to figure out that a) it was the iterator that was raising the exception and that b) it was due to an empty QuerySet.

Proposed solution

When the Iterator encounters an empty iterator, raise a more helpful error message

Extra notes

Maybe this is intended, but I found it confusing since the Iterator is supposed (?) to reset the iterator after the last element. Thus, there shouldn't be any StopIteration occurring. Providing an empty iterator is breaking the contract and should instead raise a different/more descriptive error.

I'll be happy to attempt a PR if you think this would be an improvement.

0ge avatar Nov 02 '21 20:11 0ge

Hey, that's indeed some unexpected behaviour!

A quick reproducing bug is:

class EmptyIteratorFactory(factory.Factory):
  class Meta:
    model = dict
  x = models.Iterator([])

What kind of behaviour would you expect?

  • A fallback can be provided (defaulting to None) — here leading to EmptyIteratorFactory() == dict(x=None)
  • A specific exception — EmptyIteratorFactory() raises ValueError("The provided iterator is empty");
  • The declaration is skipped if the iterator is empty — EmptyIteratorFactory() == dict()

rbarrois avatar Nov 03 '21 13:11 rbarrois

Good question! In my case I expected the iterator to be non-empty, so I would want an error. But I also recognise that there might be cases where it doesn't matter. Maybe it can default to raise an exception, but it's configurable? It would be neat if you could specify a factory as fallback value.

0ge avatar Nov 03 '21 14:11 0ge