Hi Dan,
On 12/02/2010 03:43 PM, Dan Fairs wrote:
My gut feeling is that this boils down to this vastly simplified demonstration
of how list() works:
class Foo(object):
... def __len__(self):
... print 'len called'
... raise ValueError
... def __iter__(self):
... return iter([1,2,3])
...
a = Foo()
list(a)
len called
[1, 2, 3]
Here, you can see that when converting to a list, Python calls __len__, and if
that raises an exception, discards it and goes on to call __iter__.
So - my hypothesis (unproved, as I could benefit from someone with deeper ORM
knowledge) is that the call to list() in my original test case calls
QuerySet.__len__(), which ends up raising a DatabaseError (caused by an
underlying database lock, the behaviour I'm actually testing for). Python's
subsequent call to QuerySet.__iter__() succeeds, but ends up returning an empty
iterator due to some pre-existing state *handwaving here*.
It's the handwaving bit I'm not sure about :). Does that hypothesis sound
plausible? It seems to be borne out by the snippet below, where I've removed
the underlying table:
I ran into this issue, too. My workaround was to place a
if hasattr(self._iter, '__len__'):
len(self._iter)
and the same for self.generator in QuerySet.__len__.
Btw, there's a bug report for this from 2009:
http://bugs.python.org/issue1242657
I was wondering whether the bug still exists in Python 2.x because I
take it only AttributeError and TypeError should be ignored while
calling __len__ in list() -- if that's the case, the bug is definitely
still present.
Anyway, I propose to call len() on those iterators, if possible, before
calling list() because otherwise all bugs in backends will be swallowed.
Jonas
--
You received this message because you are subscribed to the Google Groups "Django
developers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/django-developers?hl=en.