Skip to content

Commit b20807d

Browse files
authored
Improve types for multiple methods of QuerySet (#1822)
Also includes some methods on `Manager` as that propagates due to how they're related in the stubs/plugin.
1 parent f216047 commit b20807d

File tree

3 files changed

+19
-39
lines changed

3 files changed

+19
-39
lines changed

django-stubs/db/models/manager.pyi

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ from typing import Any, Generic, NoReturn, TypeVar, overload
44

55
from django.db.models import Combinable
66
from django.db.models.base import Model
7+
from django.db.models.expressions import OrderBy
78
from django.db.models.query import QuerySet, RawQuerySet
89
from typing_extensions import Self
910

@@ -18,7 +19,9 @@ class BaseManager(Generic[_T]):
1819
name: str
1920
model: type[_T]
2021
_db: str | None
22+
def __new__(cls, *args: Any, **kwargs: Any) -> Self: ...
2123
def __init__(self) -> None: ...
24+
def __class_getitem__(cls, *args: Any, **kwargs: Any) -> type[Self]: ...
2225
def deconstruct(
2326
self,
2427
) -> tuple[bool, str | None, str | None, Sequence[Any] | None, dict[str, Any] | None]: ...
@@ -34,7 +37,7 @@ class BaseManager(Generic[_T]):
3437
def get_queryset(self) -> QuerySet[_T]: ...
3538
# NOTE: The following methods are in common with QuerySet, but note that the use of QuerySet as a return type
3639
# rather than a self-type (_QS), since Manager's QuerySet-like methods return QuerySets and not Managers.
37-
def iterator(self, chunk_size: int = ...) -> Iterator[_T]: ...
40+
def iterator(self, chunk_size: int | None = ...) -> Iterator[_T]: ...
3841
def aiterator(self, chunk_size: int = ...) -> AsyncIterator[_T]: ...
3942
def aggregate(self, *args: Any, **kwargs: Any) -> dict[str, Any]: ...
4043
async def aaggregate(self, *args: Any, **kwargs: Any) -> dict[str, Any]: ...
@@ -70,16 +73,16 @@ class BaseManager(Generic[_T]):
7073
async def aupdate_or_create(
7174
self, defaults: MutableMapping[str, Any] | None = ..., **kwargs: Any
7275
) -> tuple[_T, bool]: ...
73-
def earliest(self, *fields: Any, field_name: Any | None = ...) -> _T: ...
74-
async def aearliest(self, *fields: Any, field_name: Any | None = ...) -> _T: ...
75-
def latest(self, *fields: Any, field_name: Any | None = ...) -> _T: ...
76-
async def alatest(self, *fields: Any, field_name: Any | None = ...) -> _T: ...
76+
def earliest(self, *fields: str | OrderBy) -> _T: ...
77+
async def aearliest(self, *fields: str | OrderBy) -> _T: ...
78+
def latest(self, *fields: str | OrderBy) -> _T: ...
79+
async def alatest(self, *fields: str | OrderBy) -> _T: ...
7780
def first(self) -> _T | None: ...
7881
async def afirst(self) -> _T | None: ...
7982
def last(self) -> _T | None: ...
8083
async def alast(self) -> _T | None: ...
81-
def in_bulk(self, id_list: Iterable[Any] = ..., *, field_name: str = ...) -> dict[Any, _T]: ...
82-
async def ain_bulk(self, id_list: Iterable[Any] = ..., *, field_name: str = ...) -> dict[Any, _T]: ...
84+
def in_bulk(self, id_list: Iterable[Any] | None = ..., *, field_name: str = ...) -> dict[Any, _T]: ...
85+
async def ain_bulk(self, id_list: Iterable[Any] | None = ..., *, field_name: str = ...) -> dict[Any, _T]: ...
8386
def update(self, **kwargs: Any) -> int: ...
8487
async def aupdate(self, **kwargs: Any) -> int: ...
8588
def exists(self) -> bool: ...

django-stubs/db/models/query.pyi

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ from typing import Any, Generic, NamedTuple, TypeVar, overload
55
from django.db.backends.utils import _ExecuteQuery
66
from django.db.models import Manager
77
from django.db.models.base import Model
8-
from django.db.models.expressions import Combinable
8+
from django.db.models.expressions import Combinable, OrderBy
99
from django.db.models.sql.query import Query, RawQuery
1010
from django.utils.functional import cached_property
1111
from typing_extensions import Self, TypeAlias
@@ -23,6 +23,7 @@ class BaseIterable(Generic[_Row]):
2323
chunked_fetch: bool
2424
chunk_size: int
2525
def __init__(self, queryset: QuerySet[Model], chunked_fetch: bool = ..., chunk_size: int = ...) -> None: ...
26+
def __aiter__(self) -> AsyncIterator[_Row]: ...
2627

2728
class ModelIterable(Generic[_T], BaseIterable[_T]):
2829
def __iter__(self) -> Iterator[_T]: ...
@@ -65,7 +66,7 @@ class _QuerySet(Generic[_T, _Row], Collection[_Row], Reversible[_Row], Sized):
6566
def __or__(self, other: _QuerySet[_T, _Row]) -> Self: ...
6667
# IMPORTANT: When updating any of the following methods' signatures, please ALSO modify
6768
# the corresponding method in BaseManager.
68-
def iterator(self, chunk_size: int = ...) -> Iterator[_Row]: ...
69+
def iterator(self, chunk_size: int | None = ...) -> Iterator[_Row]: ...
6970
def aiterator(self, chunk_size: int = ...) -> AsyncIterator[_Row]: ...
7071
def aggregate(self, *args: Any, **kwargs: Any) -> dict[str, Any]: ...
7172
async def aaggregate(self, *args: Any, **kwargs: Any) -> dict[str, Any]: ...
@@ -101,16 +102,16 @@ class _QuerySet(Generic[_T, _Row], Collection[_Row], Reversible[_Row], Sized):
101102
async def aupdate_or_create(
102103
self, defaults: MutableMapping[str, Any] | None = ..., **kwargs: Any
103104
) -> tuple[_T, bool]: ...
104-
def earliest(self, *fields: Any, field_name: Any | None = ...) -> _Row: ...
105-
async def aearliest(self, *fields: Any, field_name: Any | None = ...) -> _Row: ...
106-
def latest(self, *fields: Any, field_name: Any | None = ...) -> _Row: ...
107-
async def alatest(self, *fields: Any, field_name: Any | None = ...) -> _Row: ...
105+
def earliest(self, *fields: str | OrderBy) -> _Row: ...
106+
async def aearliest(self, *fields: str | OrderBy) -> _Row: ...
107+
def latest(self, *fields: str | OrderBy) -> _Row: ...
108+
async def alatest(self, *fields: str | OrderBy) -> _Row: ...
108109
def first(self) -> _Row | None: ...
109110
async def afirst(self) -> _Row | None: ...
110111
def last(self) -> _Row | None: ...
111112
async def alast(self) -> _Row | None: ...
112-
def in_bulk(self, id_list: Iterable[Any] = ..., *, field_name: str = ...) -> dict[Any, _T]: ...
113-
async def ain_bulk(self, id_list: Iterable[Any] = ..., *, field_name: str = ...) -> dict[Any, _T]: ...
113+
def in_bulk(self, id_list: Iterable[Any] | None = ..., *, field_name: str = ...) -> dict[Any, _T]: ...
114+
async def ain_bulk(self, id_list: Iterable[Any] | None = ..., *, field_name: str = ...) -> dict[Any, _T]: ...
114115
def delete(self) -> tuple[int, dict[str, int]]: ...
115116
async def adelete(self) -> tuple[int, dict[str, int]]: ...
116117
def update(self, **kwargs: Any) -> int: ...

scripts/stubtest/allowlist_todo.txt

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -461,14 +461,7 @@ django.contrib.gis.db.models.QuerySet.__contains__
461461
django.contrib.gis.db.models.QuerySet.__deepcopy__
462462
django.contrib.gis.db.models.QuerySet.__reversed__
463463
django.contrib.gis.db.models.QuerySet.__xor__
464-
django.contrib.gis.db.models.QuerySet.aearliest
465-
django.contrib.gis.db.models.QuerySet.ain_bulk
466-
django.contrib.gis.db.models.QuerySet.alatest
467464
django.contrib.gis.db.models.QuerySet.datetimes
468-
django.contrib.gis.db.models.QuerySet.earliest
469-
django.contrib.gis.db.models.QuerySet.in_bulk
470-
django.contrib.gis.db.models.QuerySet.iterator
471-
django.contrib.gis.db.models.QuerySet.latest
472465
django.contrib.gis.db.models.RasterField.contribute_to_class
473466
django.contrib.gis.db.models.RawQuerySet
474467
django.contrib.gis.db.models.RawSQL
@@ -1122,14 +1115,7 @@ django.db.models.QuerySet.__contains__
11221115
django.db.models.QuerySet.__deepcopy__
11231116
django.db.models.QuerySet.__reversed__
11241117
django.db.models.QuerySet.__xor__
1125-
django.db.models.QuerySet.aearliest
1126-
django.db.models.QuerySet.ain_bulk
1127-
django.db.models.QuerySet.alatest
11281118
django.db.models.QuerySet.datetimes
1129-
django.db.models.QuerySet.earliest
1130-
django.db.models.QuerySet.in_bulk
1131-
django.db.models.QuerySet.iterator
1132-
django.db.models.QuerySet.latest
11331119
django.db.models.RawQuerySet
11341120
django.db.models.RawSQL
11351121
django.db.models.Ref
@@ -1463,8 +1449,6 @@ django.db.models.lookups.Lookup.resolve_expression
14631449
django.db.models.lookups.Lookup.select_format
14641450
django.db.models.lookups.PatternLookup.process_rhs
14651451
django.db.models.lookups.PostgresOperatorLookup.postgres_operator
1466-
django.db.models.manager.BaseManager.__class_getitem__
1467-
django.db.models.manager.BaseManager.__new__
14681452
django.db.models.manager.BaseManager.aaggregate
14691453
django.db.models.manager.BaseManager.abulk_create
14701454
django.db.models.manager.BaseManager.abulk_update
@@ -1532,20 +1516,12 @@ django.db.models.options.Options.installed
15321516
django.db.models.options.Options.local_concrete_fields
15331517
django.db.models.options.Options.many_to_many
15341518
django.db.models.options.Options.related_objects
1535-
django.db.models.query.BaseIterable.__aiter__
15361519
django.db.models.query.EmptyQuerySet.__init__
15371520
django.db.models.query.QuerySet.__contains__
15381521
django.db.models.query.QuerySet.__deepcopy__
15391522
django.db.models.query.QuerySet.__reversed__
15401523
django.db.models.query.QuerySet.__xor__
1541-
django.db.models.query.QuerySet.aearliest
1542-
django.db.models.query.QuerySet.ain_bulk
1543-
django.db.models.query.QuerySet.alatest
15441524
django.db.models.query.QuerySet.datetimes
1545-
django.db.models.query.QuerySet.earliest
1546-
django.db.models.query.QuerySet.in_bulk
1547-
django.db.models.query.QuerySet.iterator
1548-
django.db.models.query.QuerySet.latest
15491525
django.db.models.query.RawQuerySet.__aiter__
15501526
django.db.models.query.RawQuerySet.__init__
15511527
django.db.models.query.RelatedPopulator

0 commit comments

Comments
 (0)