Opened 13 years ago
Last modified 13 years ago
#19616 closed Bug
QuerySet.__contains__ tries to check the length of a None — at Version 3
| Reported by: | Owned by: | nobody | |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | 1.4 |
| Severity: | Normal | Keywords: | |
| Cc: | Triage Stage: | Unreviewed | |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | yes | UI/UX: | no |
Description (last modified by )
This is the code from QuerySet (version 1.42).
As you can see by the lines I've bolded, although _result_cache might be None, it is still being checked for len()
def __contains__(self, val):
# The 'in' operator works without this method, due to __iter__. This
# implementation exists only to shortcut the creation of Model
# instances, by bailing out early if we find a matching element.
pos = 0
if self._result_cache is not None:
if val in self._result_cache:
return True
elif self._iter is None:
# iterator is exhausted, so we have our answer
return False
# remember not to check these again:
pos = len(self._result_cache)
else:
# We need to start filling the result cache out. The following
# ensures that self._iter is not None and self._result_cache is not
# None
it = iter(self)
# Carry on, one result at a time.
while True:
if len(self._result_cache) <= pos:
self._fill_cache(num=1)
Change History (3)
follow-up: 2 comment:1 by , 13 years ago
comment:2 by , 13 years ago
Replying to Alex:
Can you actually reproduce this in any way? Calling
iter(self)should cause_result_cacheto start being a list.
Yes, I noticed this because it happened to me.
The reproduction is a bit complex, though.
I used this snippet:
http://djangosnippets.org/snippets/1034/
And it happened when trying to iterate an empty QuerySet.
I naturally thought that this is a bug with me or the snippet, but looking at the code it is pretty obvious that although the function expects that _result_cache might be None it still tries to len() it.
comment:3 by , 13 years ago
| Description: | modified (diff) |
|---|
Looking at the code and the comments in the else branch, it actually seems very obvious that the function has covered it's bases about whether self._result_cache is None or not. We need either some further analysis as to why it is wrong, or a simple test case that ought to work.
Can you actually reproduce this in any way? Calling
iter(self)should cause_result_cacheto start being a list.