Skip to content
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

Django QuerySet does not implement __contains__ but Stubs does #1924

Closed
fidoriel opened this issue Jan 29, 2024 · 1 comment · Fixed by #1925
Closed

Django QuerySet does not implement __contains__ but Stubs does #1924

fidoriel opened this issue Jan 29, 2024 · 1 comment · Fixed by #1925
Labels
bug Something isn't working

Comments

@fidoriel
Copy link
Contributor

What's wrong

Stubs implement __contains__ for QuerySet but Django does not.

How is that should be

Django does not implement __contains__ for QuerySet. It relies on the fallback described in the docs at https://docs.python.org/3/reference/expressions.html#membership-test-details. I do not know why this was introduced in #33. It is not mentioned there.

class Example:
    def __iter__(self):
        return self

    def __next__(self):
        raise StopIteration

print(42 in Example())

This Minimal example proves that this is not necessary to type it that way.
Example does not implement __contains__ but in is usable. So 42 in myQuerySet will work but myQuerySet.__contains__(42) not, because it is not defined (you can check with dir).
QuerySet will be type checked correctly by mypy but will not have the same behavior at Runtime because QuerySet does not implement __contains__. A Django QuerySet is not a container because it does not implement __contains__ as described at
https://docs.python.org/3/library/collections.abc.html#collections-abstract-base-classes and https://mypy.readthedocs.io/en/stable/protocols.html#container-t. The docs are clear there. No __contains__ no Container. A static type checker will think that a Django Stubs QuerySet is a Container but a runtime type checker will not recognize a Django QuerySet as a Container. Also, using __contains__(42) will be allowed by Django Stubs but fail on Django at runtime.

Why __contains__ is not implemented with contains for QuerySet in Django, I do not know. But since this project is for typing Django, this is on their site to do. I am planning to open an issue there as well.

System information

  • OS:
  • python: 3.10
  • django: 4.2.7
  • mypy: 1.8
  • django-stubs: 4.2.6
  • django-stubs-ext: None
@fidoriel fidoriel added the bug Something isn't working label Jan 29, 2024
@sobolevn
Copy link
Member

PR is welcome!

fidoriel added a commit to fidoriel/django-stubs that referenced this issue Jan 30, 2024
intgr pushed a commit that referenced this issue Mar 21, 2024
…om `QuerySet` (#1925)

* fix: #1924
* change collection to iterable
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Development

Successfully merging a pull request may close this issue.

2 participants