#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 (13)
follow-up: 2 comment:1 by , 6 years ago
comment:2 by , 6 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 , 6 years ago
| Cc: | added |
|---|
comment:4 by , 6 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 , 6 years ago
| Has patch: | set |
|---|
comment:7 by , 6 years ago
| Owner: | changed from to |
|---|---|
| Status: | new → assigned |
comment:8 by , 6 years ago
| Triage Stage: | Accepted → Ready for checkin |
|---|
comment:11 by , 7 months ago
Hello,
I submitted a PR to add __class_getitem__ to Model, as it has been done for ForeignKey, Manager and QuerySet in the two previous PRs
https://github.com/django/django/pull/19390
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.typedfile, 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 intypingis 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.