-
-
Notifications
You must be signed in to change notification settings - Fork 500
Manager
with generic QuerySet
using TypeVar
defaults
#2776
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
base: master
Are you sure you want to change the base?
Changes from all commits
519ea77
274ca0b
24e970f
176f2f3
13850f1
44176ee
911f922
0579b7d
499f315
aba2a80
450cea7
da3bcf3
68bc3a2
bdcdc60
00ae6fe
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,13 +8,15 @@ from django.db.models.query import QuerySet, RawQuerySet | |
from typing_extensions import Self | ||
|
||
_T = TypeVar("_T", bound=Model, covariant=True) | ||
_QS = TypeVar("_QS", bound=QuerySet[Any], covariant=True, default=QuerySet[_T]) | ||
|
||
class BaseManager(Generic[_T]): | ||
class BaseManager(Generic[_T, _QS]): | ||
creation_counter: int | ||
auto_created: bool | ||
use_in_migrations: bool | ||
name: str | ||
model: type[_T] | ||
_queryset_class: type[_QS] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I needed to expose this symbol because I use it in the plugin. |
||
_db: str | None | ||
def __new__(cls, *args: Any, **kwargs: Any) -> Self: ... | ||
def __init__(self) -> None: ... | ||
|
@@ -24,17 +26,25 @@ class BaseManager(Generic[_T]): | |
) -> tuple[bool, str | None, str | None, Sequence[Any] | None, dict[str, Any] | None]: ... | ||
def check(self, **kwargs: Any) -> list[Any]: ... | ||
@classmethod | ||
def from_queryset(cls, queryset_class: type[QuerySet[_T]], class_name: str | None = None) -> type[Self]: ... | ||
def from_queryset( | ||
cls, queryset_class: type[QuerySet[_T]], class_name: str | None = None | ||
) -> type[BaseManager[_T, _QS]]: ... | ||
@classmethod | ||
def _get_queryset_methods(cls, queryset_class: type) -> dict[str, Any]: ... | ||
def contribute_to_class(self, cls: type[Model], name: str) -> None: ... | ||
def db_manager(self, using: str | None = None, hints: dict[str, Model] | None = None) -> Self: ... | ||
@property | ||
def db(self) -> str: ... | ||
def get_queryset(self) -> QuerySet[_T]: ... | ||
def all(self) -> QuerySet[_T]: ... | ||
def get_queryset(self) -> _QS: ... | ||
def all(self) -> _QS: ... | ||
|
||
class Manager(BaseManager[_T]): | ||
class Manager(BaseManager[_T, _QS]): | ||
# `from_queryset` is redeclared here because Self cannot have type arguments | ||
# ie `def from_queryset(...) -> type[Self[_T, _QS]]` is not valid (mypy raises an error, but resolves type correctly) | ||
@classmethod | ||
def from_queryset( | ||
cls, queryset_class: type[QuerySet[_T]], class_name: str | None = None | ||
) -> type[Manager[_T, _QS]]: ... | ||
# NOTE: The following methods are in common with QuerySet, but note that the use of QuerySet as a return type | ||
# rather than a self-type (_QS), since Manager's QuerySet-like methods return QuerySets and not Managers. | ||
def iterator(self, chunk_size: int | None = ...) -> Iterator[_T]: ... | ||
|
@@ -112,24 +122,24 @@ class Manager(BaseManager[_T]): | |
def datetimes( | ||
self, field_name: str, kind: str, order: str = ..., tzinfo: datetime.tzinfo | None = ... | ||
) -> QuerySet[_T, datetime.datetime]: ... | ||
def none(self) -> QuerySet[_T]: ... | ||
def filter(self, *args: Any, **kwargs: Any) -> QuerySet[_T]: ... | ||
def exclude(self, *args: Any, **kwargs: Any) -> QuerySet[_T]: ... | ||
def complex_filter(self, filter_obj: Any) -> QuerySet[_T]: ... | ||
def none(self) -> _QS: ... | ||
def filter(self, *args: Any, **kwargs: Any) -> _QS: ... | ||
def exclude(self, *args: Any, **kwargs: Any) -> _QS: ... | ||
def complex_filter(self, filter_obj: Any) -> _QS: ... | ||
def count(self) -> int: ... | ||
async def acount(self) -> int: ... | ||
def union(self, *other_qs: Any, all: bool = ...) -> QuerySet[_T]: ... | ||
def intersection(self, *other_qs: Any) -> QuerySet[_T]: ... | ||
def difference(self, *other_qs: Any) -> QuerySet[_T]: ... | ||
def select_for_update( | ||
self, nowait: bool = ..., skip_locked: bool = ..., of: Sequence[str] = ..., no_key: bool = ... | ||
) -> QuerySet[_T]: ... | ||
def select_related(self, *fields: Any) -> QuerySet[_T]: ... | ||
def prefetch_related(self, *lookups: Any) -> QuerySet[_T]: ... | ||
def annotate(self, *args: Any, **kwargs: Any) -> QuerySet[_T]: ... | ||
def alias(self, *args: Any, **kwargs: Any) -> QuerySet[_T]: ... | ||
def order_by(self, *field_names: Any) -> QuerySet[_T]: ... | ||
def distinct(self, *field_names: Any) -> QuerySet[_T]: ... | ||
) -> _QS: ... | ||
def select_related(self, *fields: Any) -> _QS: ... | ||
def prefetch_related(self, *lookups: Any) -> _QS: ... | ||
def annotate(self, *args: Any, **kwargs: Any) -> _QS: ... | ||
def alias(self, *args: Any, **kwargs: Any) -> _QS: ... | ||
def order_by(self, *field_names: Any) -> _QS: ... | ||
def distinct(self, *field_names: Any) -> _QS: ... | ||
# extra() return type won't be supported any time soon | ||
def extra( | ||
self, | ||
|
@@ -141,9 +151,9 @@ class Manager(BaseManager[_T]): | |
select_params: Sequence[Any] | None = ..., | ||
) -> QuerySet[Any]: ... | ||
def reverse(self) -> QuerySet[_T]: ... | ||
def defer(self, *fields: Any) -> QuerySet[_T]: ... | ||
def only(self, *fields: Any) -> QuerySet[_T]: ... | ||
def using(self, alias: str | None) -> QuerySet[_T]: ... | ||
def defer(self, *fields: Any) -> _QS: ... | ||
def only(self, *fields: Any) -> _QS: ... | ||
def using(self, alias: str | None) -> _QS: ... | ||
|
||
class ManagerDescriptor: | ||
manager: BaseManager | ||
|
@@ -153,5 +163,9 @@ class ManagerDescriptor: | |
@overload | ||
def __get__(self, instance: Model, cls: type[Model] | None = None) -> NoReturn: ... | ||
|
||
class EmptyManager(Manager[_T]): | ||
def __init__(self, model: type[_T]) -> None: ... | ||
# We have to define different typevars here otherwise it conflicts with the ones above | ||
_T2 = TypeVar("_T2", bound=Model, covariant=True) | ||
_QS2 = TypeVar("_QS2", bound=QuerySet[Any], covariant=True, default=QuerySet[_T2]) | ||
|
||
class EmptyManager(Manager[_T2, _QS2]): | ||
def __init__(self, model: type[_T2]) -> None: ... | ||
Comment on lines
+166
to
+171
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm really not quite sure why but If I reuse the reveal_type(models.Manager[MyModel])
-note: Revealed type is "django.db.models.manager.Manager[django.db.models.base.Model, django.db.models.query.QuerySet[_T`1, _T`1]]"
+note: Revealed type is "django.db.models.manager.Manager[django.db.models.base.Model, django.db.models.query.QuerySet[django.db.models.base.Model, django.db.models.base.Model]] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wanted to return
Self[_To, _To_QS
] but it's not supported. It's probably fine because I don't expect people to subclass this ?