django-stubs icon indicating copy to clipboard operation
django-stubs copied to clipboard

fix: #1924 remove `__contains__` from `QuerySet`

Open fidoriel opened this issue 1 year ago • 1 comments

I have made things!

Related issues

Please see fixes https://github.com/typeddjango/django-stubs/issues/1924

fidoriel avatar Jan 30 '24 06:01 fidoriel

Imho there should be an abstract base type which will make it possible to use this. Currently, Mypy allows passing a QS into a Collection. Merging this will break this behavior.

class DjangoContainer(Reversible[_Row], Iterable[_Row], Sized):
    pass

should be added. It behaves like a container but isnt one.

def myFunc(some_tings: DjangoContainer): ...

would allow to pass in a list with Model instances and a queryset.

fidoriel avatar Jan 30 '24 08:01 fidoriel

You are entirely correct, QuerySet is not a Collection. In fact, it's not Reversible either!

In [16]: isinstance(qs, Collection)   # ✅
Out[16]: False
In [17]: isinstance(qs, Iterable)
Out[17]: True
In [18]: isinstance(qs, Sized)
Out[18]: True
In [19]: isinstance(qs, Reversible)  # ⚠️
Out[19]: False

We keep discovering significant inaccuracies that have been in django-stubs from nearly the beginning. 😅 Both of these date back to 2019.

  • https://github.com/typeddjango/django-stubs/commit/f02050911fc5ec4125f9034d79f338329ca7cf75#diff-389fe7d7dcfb77ddaac87c1f3bdc196f3ef0ca33b8047c6638a15f3a3db21b56L124-R125
  • https://github.com/typeddjango/django-stubs/commit/324b961d7464d7419e5886da9401a3f35481218d#diff-389fe7d7dcfb77ddaac87c1f3bdc196f3ef0ca33b8047c6638a15f3a3db21b56L49-R53

intgr avatar Mar 21 '24 10:03 intgr

I tested this out. I'm downcasting QuerySet[x] to Collection[x] in lots of places in my projects. Typically in places where I want to accept both QuerySet[model] and list[model] as some parameter. So this causes a fair amount of churn.

Most places work fine with Iterable[x] as well, but in some places I want to use len() on the iterable. AFAIK there's currently no straightforward way to say Iterable[T] & Sized in the type sytem. I guess that may have been the motivation in making QuerySets Collection.

But there are other solutions:

  • Define a custom class SizedIterable(Iterable[T_co], Sized, Protocol) for those use cases.
  • Instead of Collection[T], use the more explicit list[T] | QuerySet[T]

Not a big deal.

intgr avatar Mar 21 '24 10:03 intgr

Are you interested in creating another PR to remove Reversible too?

intgr avatar Mar 21 '24 10:03 intgr