|
15 | 15 | content: |
|
16 | 16 | from django.db import models
|
17 | 17 | from django.db.models.manager import BaseManager
|
18 |
| - from typing import List, Dict |
| 18 | + from typing import List, Dict, TypeVar |
19 | 19 | from typing_extensions import Self
|
20 | 20 |
|
21 |
| - class CustomManager(BaseManager): |
| 21 | + M = TypeVar("M", covariant=True, bound=models.Model) |
| 22 | +
|
| 23 | + class CustomManager(BaseManager[M]): |
22 | 24 | def test_custom_manager(self) -> Self: ...
|
23 | 25 |
|
24 |
| - class BaseQuerySet(models.QuerySet): |
| 26 | + class BaseQuerySet(models.QuerySet[M]): |
25 | 27 | def example_dict(self) -> Dict[str, Self]: ...
|
26 | 28 |
|
27 |
| - class MyQuerySet(BaseQuerySet): |
| 29 | + class MyQuerySet(BaseQuerySet[M]): |
28 | 30 | def example_simple(self) -> Self: ...
|
29 | 31 | def example_list(self) -> List[Self]: ...
|
30 | 32 | def just_int(self) -> int: ...
|
|
82 | 84 | - path: myapp/__init__.py
|
83 | 85 | - path: myapp/models.py
|
84 | 86 | content: |
|
| 87 | + from typing import TypeVar |
85 | 88 | from django.db import models
|
86 | 89 | from django.db.models.manager import BaseManager
|
87 | 90 |
|
88 |
| - class ModelQuerySet(models.QuerySet): |
| 91 | + M = TypeVar("M", bound=models.Model, covariant=True) |
| 92 | +
|
| 93 | + class ModelQuerySet(models.QuerySet[M]): |
89 | 94 | def queryset_method(self) -> str:
|
90 | 95 | return 'hello'
|
91 | 96 | NewManager = BaseManager.from_queryset(ModelQuerySet)
|
|
103 | 108 | reveal_type(MyModel.objects.queryset_method_3()) # N: Revealed type is "builtins.str"
|
104 | 109 | reveal_type(MyModel.objects.queryset_method_4([])) # N: Revealed type is "None"
|
105 | 110 | reveal_type(MyModel.objects.filter(id=1).queryset_method()) # N: Revealed type is "myapp.querysets.ModelQuerySet"
|
106 |
| - reveal_type(MyModel.objects.filter(id=1)) # N: Revealed type is "myapp.querysets.ModelQuerySet[myapp.models.MyModel]" |
| 111 | + reveal_type(MyModel.objects.filter(id=1)) # N: Revealed type is "myapp.querysets.ModelQuerySet" |
107 | 112 | installed_apps:
|
108 | 113 | - myapp
|
109 | 114 | files:
|
|
223 | 228 | reveal_type(MyModel.objects.queryset_method_3()) # N: Revealed type is "builtins.str"
|
224 | 229 | reveal_type(MyModel.objects.queryset_method_4([])) # N: Revealed type is "None"
|
225 | 230 | reveal_type(MyModel.objects.filter(id=1).queryset_method()) # N: Revealed type is "myapp.querysets.ModelQuerySet"
|
226 |
| - reveal_type(MyModel.objects.filter(id=1)) # N: Revealed type is "myapp.querysets.ModelQuerySet[myapp.models.MyModel]" |
| 231 | + reveal_type(MyModel.objects.filter(id=1)) # N: Revealed type is "myapp.querysets.ModelQuerySet" |
227 | 232 | installed_apps:
|
228 | 233 | - myapp
|
229 | 234 | files:
|
|
307 | 312 | import typing
|
308 | 313 | kls: typing.Type[typing.Union[MyModel1, MyModel2]] = MyModel1
|
309 | 314 | reveal_type(kls.objects) # N: Revealed type is "Union[myapp.models.ManagerFromModelQuerySet1[myapp.models.MyModel1], myapp.models.ManagerFromModelQuerySet2[myapp.models.MyModel2]]"
|
310 |
| - reveal_type(kls.objects.all()) # N: Revealed type is "Union[myapp.models.ModelQuerySet1[myapp.models.MyModel1], myapp.models.ModelQuerySet2[myapp.models.MyModel2]]" |
| 315 | + reveal_type(kls.objects.all()) # N: Revealed type is "Union[myapp.models.ModelQuerySet1, myapp.models.ModelQuerySet2]" |
311 | 316 | reveal_type(kls.objects.get()) # N: Revealed type is "Union[myapp.models.MyModel1, myapp.models.MyModel2]"
|
312 | 317 | reveal_type(kls.objects.queryset_method()) # N: Revealed type is "Union[builtins.int, builtins.str]"
|
313 | 318 | installed_apps:
|
|
580 | 585 | from myapp.models import MyModel
|
581 | 586 | reveal_type(MyModel.objects) # N: Revealed type is "myapp.models.MyManagerFromMyQuerySet[myapp.models.MyModel]"
|
582 | 587 | reveal_type(MyModel._default_manager) # N: Revealed type is "myapp.models.MyManagerFromMyQuerySet[myapp.models.MyModel]"
|
583 |
| - reveal_type(MyModel.objects.all) # N: Revealed type is "def () -> myapp.models.MyQuerySet[myapp.models.MyModel]" |
| 588 | + reveal_type(MyModel.objects.all) # N: Revealed type is "def () -> myapp.models.MyQuerySet" |
584 | 589 | reveal_type(MyModel.objects.custom) # N: Revealed type is "def () -> myapp.models.MyQuerySet"
|
585 |
| - reveal_type(MyModel.objects.all().filter) # N: Revealed type is "def (*args: Any, **kwargs: Any) -> myapp.models.MyQuerySet[myapp.models.MyModel]" |
| 590 | + reveal_type(MyModel.objects.all().filter) # N: Revealed type is "def (*args: Any, **kwargs: Any) -> myapp.models.MyQuerySet" |
586 | 591 | reveal_type(MyModel.objects.custom().filter) # N: Revealed type is "def (*args: Any, **kwargs: Any) -> myapp.models.MyQuerySet"
|
587 | 592 | reveal_type(MyModel.objects2) # N: Revealed type is "myapp.models.MyManagerFromMyQuerySet[myapp.models.MyModel]"
|
588 | 593 | reveal_type(MyModel._default_manager) # N: Revealed type is "myapp.models.MyManagerFromMyQuerySet[myapp.models.MyModel]"
|
|
633 | 638 | - case: from_queryset_includes_methods_returning_queryset
|
634 | 639 | main: |
|
635 | 640 | from myapp.models import MyModel
|
636 |
| - reveal_type(MyModel.objects.alias) # N: Revealed type is "def (*args: Any, **kwargs: Any) -> myapp.models.MyQuerySet[myapp.models.MyModel]" |
637 |
| - reveal_type(MyModel.objects.all) # N: Revealed type is "def () -> myapp.models.MyQuerySet[myapp.models.MyModel]" |
638 |
| - reveal_type(MyModel.objects.annotate) # N: Revealed type is "def (*args: Any, **kwargs: Any) -> myapp.models.MyQuerySet[myapp.models.MyModel]" |
639 |
| - reveal_type(MyModel.objects.complex_filter) # N: Revealed type is "def (filter_obj: Any) -> myapp.models.MyQuerySet[myapp.models.MyModel]" |
640 |
| - reveal_type(MyModel.objects.defer) # N: Revealed type is "def (*fields: Any) -> myapp.models.MyQuerySet[myapp.models.MyModel]" |
641 |
| - reveal_type(MyModel.objects.difference) # N: Revealed type is "def (*other_qs: Any) -> myapp.models.MyQuerySet[myapp.models.MyModel]" |
642 |
| - reveal_type(MyModel.objects.distinct) # N: Revealed type is "def (*field_names: Any) -> myapp.models.MyQuerySet[myapp.models.MyModel]" |
643 |
| - reveal_type(MyModel.objects.exclude) # N: Revealed type is "def (*args: Any, **kwargs: Any) -> myapp.models.MyQuerySet[myapp.models.MyModel]" |
644 |
| - reveal_type(MyModel.objects.extra) # N: Revealed type is "def (select: Union[builtins.dict[builtins.str, Any], None] =, where: Union[typing.Sequence[builtins.str], None] =, params: Union[typing.Sequence[Any], None] =, tables: Union[typing.Sequence[builtins.str], None] =, order_by: Union[typing.Sequence[builtins.str], None] =, select_params: Union[typing.Sequence[Any], None] =) -> myapp.models.MyQuerySet[myapp.models.MyModel]" |
645 |
| - reveal_type(MyModel.objects.filter) # N: Revealed type is "def (*args: Any, **kwargs: Any) -> myapp.models.MyQuerySet[myapp.models.MyModel]" |
646 |
| - reveal_type(MyModel.objects.intersection) # N: Revealed type is "def (*other_qs: Any) -> myapp.models.MyQuerySet[myapp.models.MyModel]" |
647 |
| - reveal_type(MyModel.objects.none) # N: Revealed type is "def () -> myapp.models.MyQuerySet[myapp.models.MyModel]" |
648 |
| - reveal_type(MyModel.objects.only) # N: Revealed type is "def (*fields: Any) -> myapp.models.MyQuerySet[myapp.models.MyModel]" |
649 |
| - reveal_type(MyModel.objects.order_by) # N: Revealed type is "def (*field_names: Any) -> myapp.models.MyQuerySet[myapp.models.MyModel]" |
650 |
| - reveal_type(MyModel.objects.prefetch_related) # N: Revealed type is "def (*lookups: Any) -> myapp.models.MyQuerySet[myapp.models.MyModel]" |
651 |
| - reveal_type(MyModel.objects.reverse) # N: Revealed type is "def () -> myapp.models.MyQuerySet[myapp.models.MyModel]" |
652 |
| - reveal_type(MyModel.objects.select_for_update) # N: Revealed type is "def (nowait: builtins.bool =, skip_locked: builtins.bool =, of: typing.Sequence[builtins.str] =, no_key: builtins.bool =) -> myapp.models.MyQuerySet[myapp.models.MyModel]" |
653 |
| - reveal_type(MyModel.objects.select_related) # N: Revealed type is "def (*fields: Any) -> myapp.models.MyQuerySet[myapp.models.MyModel]" |
654 |
| - reveal_type(MyModel.objects.union) # N: Revealed type is "def (*other_qs: Any, all: builtins.bool =) -> myapp.models.MyQuerySet[myapp.models.MyModel]" |
655 |
| - reveal_type(MyModel.objects.using) # N: Revealed type is "def (alias: Union[builtins.str, None]) -> myapp.models.MyQuerySet[myapp.models.MyModel]" |
| 641 | + reveal_type(MyModel.objects.alias) # N: Revealed type is "def (*args: Any, **kwargs: Any) -> myapp.models.MyQuerySet" |
| 642 | + reveal_type(MyModel.objects.all) # N: Revealed type is "def () -> myapp.models.MyQuerySet" |
| 643 | + reveal_type(MyModel.objects.annotate) # N: Revealed type is "def (*args: Any, **kwargs: Any) -> myapp.models.MyQuerySet" |
| 644 | + reveal_type(MyModel.objects.complex_filter) # N: Revealed type is "def (filter_obj: Any) -> myapp.models.MyQuerySet" |
| 645 | + reveal_type(MyModel.objects.defer) # N: Revealed type is "def (*fields: Any) -> myapp.models.MyQuerySet" |
| 646 | + reveal_type(MyModel.objects.difference) # N: Revealed type is "def (*other_qs: Any) -> myapp.models.MyQuerySet" |
| 647 | + reveal_type(MyModel.objects.distinct) # N: Revealed type is "def (*field_names: Any) -> myapp.models.MyQuerySet" |
| 648 | + reveal_type(MyModel.objects.exclude) # N: Revealed type is "def (*args: Any, **kwargs: Any) -> myapp.models.MyQuerySet" |
| 649 | + reveal_type(MyModel.objects.extra) # N: Revealed type is "def (select: Union[builtins.dict[builtins.str, Any], None] =, where: Union[typing.Sequence[builtins.str], None] =, params: Union[typing.Sequence[Any], None] =, tables: Union[typing.Sequence[builtins.str], None] =, order_by: Union[typing.Sequence[builtins.str], None] =, select_params: Union[typing.Sequence[Any], None] =) -> myapp.models.MyQuerySet" |
| 650 | + reveal_type(MyModel.objects.filter) # N: Revealed type is "def (*args: Any, **kwargs: Any) -> myapp.models.MyQuerySet" |
| 651 | + reveal_type(MyModel.objects.intersection) # N: Revealed type is "def (*other_qs: Any) -> myapp.models.MyQuerySet" |
| 652 | + reveal_type(MyModel.objects.none) # N: Revealed type is "def () -> myapp.models.MyQuerySet" |
| 653 | + reveal_type(MyModel.objects.only) # N: Revealed type is "def (*fields: Any) -> myapp.models.MyQuerySet" |
| 654 | + reveal_type(MyModel.objects.order_by) # N: Revealed type is "def (*field_names: Any) -> myapp.models.MyQuerySet" |
| 655 | + reveal_type(MyModel.objects.prefetch_related) # N: Revealed type is "def (*lookups: Any) -> myapp.models.MyQuerySet" |
| 656 | + reveal_type(MyModel.objects.reverse) # N: Revealed type is "def () -> myapp.models.MyQuerySet" |
| 657 | + reveal_type(MyModel.objects.select_for_update) # N: Revealed type is "def (nowait: builtins.bool =, skip_locked: builtins.bool =, of: typing.Sequence[builtins.str] =, no_key: builtins.bool =) -> myapp.models.MyQuerySet" |
| 658 | + reveal_type(MyModel.objects.select_related) # N: Revealed type is "def (*fields: Any) -> myapp.models.MyQuerySet" |
| 659 | + reveal_type(MyModel.objects.union) # N: Revealed type is "def (*other_qs: Any, all: builtins.bool =) -> myapp.models.MyQuerySet" |
| 660 | + reveal_type(MyModel.objects.using) # N: Revealed type is "def (alias: Union[builtins.str, None]) -> myapp.models.MyQuerySet" |
656 | 661 | installed_apps:
|
657 | 662 | - myapp
|
658 | 663 | files:
|
|
882 | 887 |
|
883 | 888 | class MCS(type): pass
|
884 | 889 |
|
| 890 | +- case: test_from_queryset_with_concrete_subclass |
| 891 | + main: | |
| 892 | + from myapp.models import Concrete |
| 893 | + reveal_type(Concrete.objects) # N: Revealed type is "myapp.models.ConcreteManager" |
| 894 | + reveal_type(Concrete.objects.get()) # N: Revealed type is "myapp.models.Concrete" |
| 895 | + reveal_type(Concrete.objects.all()) # N: Revealed type is "myapp.models.CustomQuerySet[myapp.models.Concrete, myapp.models.Concrete]" |
| 896 | + reveal_type(Concrete.objects.all().get()) # N: Revealed type is "myapp.models.Concrete" |
| 897 | + installed_apps: |
| 898 | + - myapp |
| 899 | + files: |
| 900 | + - path: myapp/__init__.py |
| 901 | + - path: myapp/models.py |
| 902 | + content: | |
| 903 | + from typing import ClassVar |
| 904 | + from typing_extensions import Self, TypeVar |
| 905 | + from django.db.models import Model, QuerySet |
| 906 | + from django.db.models.manager import Manager |
| 907 | +
|
| 908 | + M = TypeVar("M", bound=Model, covariant=True) |
| 909 | + D = TypeVar("D", covariant=True, default=M) |
| 910 | +
|
| 911 | + class CustomQuerySet(QuerySet[M, D]): pass |
| 912 | +
|
| 913 | + _base = Manager.from_queryset(CustomQuerySet) |
| 914 | +
|
| 915 | + class CustomBase(_base[M]): ... |
| 916 | +
|
| 917 | + class BaseModel(Model): |
| 918 | + objects: ClassVar[CustomBase[Self]] = CustomBase() |
| 919 | +
|
| 920 | + class ConcreteManager(CustomBase["Concrete"]): ... |
| 921 | +
|
| 922 | + class Concrete(BaseModel): |
| 923 | + objects: ClassVar[ConcreteManager] = ConcreteManager() |
| 924 | +
|
885 | 925 | - case: test_queryset_arg_as_unsupported_expressions
|
886 | 926 | main: |
|
887 | 927 | from typing import Union, Generic, TypeVar
|
|
0 commit comments