-
Couldn't load subscription status.
- Fork 1.2k
Raise TypeError when __in-operator used with a Document
#1237
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Raise TypeError when __in-operator used with a Document
#1237
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @malthejorgensen, this is great! It's almost ready to merge except for a few tweaks/generalizations. Will you be able to address my comments any time soon? Also, sorry it took that long to get back to you!
| value = value['_id'] | ||
|
|
||
| elif op in ('in', 'nin', 'all', 'near') and not isinstance(value, dict): | ||
| if isinstance(value, BaseDocument): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If all of the above truly expect an iterable, then we should raise an error for any non-iterable, not just a BaseDocument.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, the problem is actually that BaseDocument is iterable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Both the checks mentioned in this StackOverflow thread will say that BaseDocument is iterable. (for k in user will iterate over each field of the document user)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh, I missed that, thanks for clearing that up! I think in such case we can change this condition to:
# Raise an error if the in/nin/all/near param is not iterable. We need a
# special check for BaseDocument, because - although it's iterable - using
# it as such in the context of this method is most definitely a mistake.
if not hasattr(value, '__iter__') or isinstance(value, BaseDocument):
raise TypeError(...)
The comment is crucial, too, given that this is a pretty unintuitive isinstance check.What do you think @malthejorgensen ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, I'll make the change
tests/queryset/queryset.py
Outdated
| BlogPost.objects(authors__in=author).count() | ||
|
|
||
| # Check correct usage | ||
| try: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This block is redundant - we already check it above.
| self.fail("Using __in-operator raised type error when it shouldn't have") | ||
|
|
||
| User.drop_collection() | ||
| BlogPost.drop_collection() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are redundant - by convention we should just take care of dropping existing collections at the beginning of each test (which you already do).
|
I'll take a look at it now :) |
There's a bunch of small commits so squashing would make sense, and I also have a version of the branch that is rebased on the latest |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for your contribution @malthejorgensen
|
@malthejorgensen you can now push the rebased version of the branch. Ping me when you do and I'll merge it. Thanks again! |
0266c21 to
1a01a1d
Compare
|
Absolutely no problem – I'm just glad to help! I'm only sorry that the process is turning out to be a bit of hassle for you. I'm now the getting the flake8 error I have a different branch (feature/in-operator-catch-no-list-flake-C901) which should pass, where I've moved the value preparation out into its own function, but if we trust flake8's analysis, it's really just hiding an overarching problem – namely that the We could also change the Ping @wojcikstefan |
|
@malthejorgensen I apologize for all the back and forth, but since I merged #1428 a) there are conflicts again, b) Also, please use |
Doing a query like `BlogPost.objects(authors__in=author).count()`, where
`author` is a single Document, will now raise a TypeError explaining
that you cannot use a single `Document` with the `in`-operator.
i.e. `BlogPost.objects(authors__in=[author]).count()`
Similarly using the `in`-operator with a non-iterable will also raise a
TypeError explaining that you need to use an iterable with the `in`-operator.
The same applies to the `nin`, `all`, and `near` operators.
Note:
The added code uses `_import_class('BaseDocument')` to break any circular
dependency.
`queryset/transform.py::query()` has complexity 47.
9fb9788 to
de8d65d
Compare
|
No problem @wojcikstefan – I'm just sorry to be taking your time for a small PR like mine |
|
Thank you very much @malthejorgensen ! |
|
FYI I made you tests a bit more concise while retaining all of the logic we want to test: 8e884fd |
Currently doing a query like
BlogPost.objects(authors__in=author).count(), whereauthoris a single MongoEngine-Document, raises an obscure error:This pull requests adds a "sanity" check, and raises a TypeError explaining that you need to use an iterable with the
in-operator.The correct thing to do is:
BlogPost.objects(authors__in=[author]).count(), but that's not obvious when you read theValidationErrorshown above.