#31223 closed New feature (fixed)
Add __class_getitem__ to support runtime type parameters for some classes
Reported by: | Sobolev Nikita | Owned by: | Sobolev Nikita |
---|---|---|---|
Component: | Utilities | Version: | dev |
Severity: | Normal | Keywords: | types, mypy, django-stubs |
Cc: | David Foster | Triage Stage: | Ready for checkin |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
We (in django-stubs) treat several types as Generics. We provide type parameters to them like so: QuerySet[MyModel]
Currently it is impossible without a monkeypatch from our side, because these classes do not have __class_getitem__
method.
Suggested patch will address this problem for:
- cached_property
- Lookup
- Field
- QuerySet
- BaseManager
Implementation detail: __class_getitem__
will be a no-op for django runtime. Since types are only required during mypy
check.
django-stubs: https://github.com/typeddjango/django-stubs
monkey-patching: https://github.com/typeddjango/django-stubs/blob/5b3088a17a76a77cb56a9c2241c2ddc6ccc8153a/mypy_django_plugin/django/context.py#L60-L61
Related DEP: https://github.com/django/deps/pull/65
Change History (10)
follow-up: 2 comment:1 by , 5 years ago
comment:2 by , 5 years ago
Replying to Ran Benita:
Yes, this is a best-practice indeed. But.
Inheriting from Generic
will also modify __init_subclass__
and __new__
methods. And I am not sure about it.
I guess for now just __class_getitem__
is enough. It has zero possible problems and works for us.
Later (when working on next typing-related things) we would need to return to this question once again.
comment:3 by , 5 years ago
Cc: | added |
---|
comment:4 by , 5 years ago
Triage Stage: | Unreviewed → Accepted |
---|
Based on one +0 and 2 +1s for this change at https://github.com/django/deps/pull/65 , I'm marking it as Accepted.
comment:6 by , 5 years ago
Has patch: | set |
---|
comment:7 by , 5 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
comment:8 by , 5 years ago
Triage Stage: | Accepted → Ready for checkin |
---|
Instead of adding a custom dummy
__class_getitem__()
implementation, another approach is to actually inherit fromtyping.Generic
. As long as Django doesn't publish its types with apy.typed
file, it should not have an effect on type-checking, but it will add the necessary__class_getitem__
at runtime: https://github.com/python/cpython/blob/78c7183f470b60a39ac2dd0ad1a94d49d1e0b062/Lib/typing.py#L876The reason to do this is that presumably the
__class_getitem__
runtime implementation intyping
is more correct (certainly seems to do a lot) and more forward compatible than a custom implementation in Django would be.There might be repercussions I am not considering though, like performance, or side effects of importing
typing
.