Skip to content

Commit f5135da

Browse files
committed
expressions
1 parent 2a6a012 commit f5135da

File tree

5 files changed

+61
-30
lines changed

5 files changed

+61
-30
lines changed

django-stubs/db/models/__init__.pyi

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,12 @@ from .expressions import (
8282
Value as Value,
8383
Func as Func,
8484
ExpressionWrapper as ExpressionWrapper,
85+
Combinable as Combinable,
86+
Col as Col,
87+
CombinedExpression as CombinedExpression,
88+
ExpressionList as ExpressionList,
89+
Random as Random,
90+
Ref as Ref,
8591
)
8692

8793
from .manager import BaseManager as BaseManager, Manager as Manager

django-stubs/db/models/expressions.pyi

Lines changed: 47 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
11
from collections import OrderedDict
22
from datetime import datetime, timedelta
3-
from typing import Any, Callable, Dict, Iterator, List, Optional, Sequence, Set, Tuple, Type, Union
3+
from typing import Any, Callable, Dict, Iterator, List, Optional, Sequence, Set, Tuple, Type, Union, TypeVar
44

55
from django.db.models.lookups import Lookup
66
from django.db.models.sql.compiler import SQLCompiler
77

88
from django.db.models import Q, QuerySet
9-
from django.db.models.fields import Field
9+
from django.db.models.fields import Field, FloatField
1010
from django.db.models.sql import Query
1111

1212
_OutputField = Union[Field, str]
1313

1414
class SQLiteNumericMixin:
1515
def as_sqlite(self, compiler: SQLCompiler, connection: Any, **extra_context: Any) -> Tuple[str, List[float]]: ...
1616

17+
_SelfCombinable = TypeVar("_SelfCombinable", bound="Combinable")
18+
1719
class Combinable:
1820
ADD: str = ...
1921
SUB: str = ...
@@ -25,28 +27,32 @@ class Combinable:
2527
BITOR: str = ...
2628
BITLEFTSHIFT: str = ...
2729
BITRIGHTSHIFT: str = ...
28-
def __neg__(self) -> CombinedExpression: ...
29-
def __add__(self, other: Optional[Union[timedelta, Combinable, float, str]]) -> CombinedExpression: ...
30-
def __sub__(self, other: Union[timedelta, Combinable, float]) -> CombinedExpression: ...
31-
def __mul__(self, other: Union[timedelta, Combinable, float]) -> CombinedExpression: ...
32-
def __truediv__(self, other: Union[Combinable, float]) -> Combinable: ...
33-
def __itruediv__(self, other: Union[Combinable, float]) -> Combinable: ...
34-
def __mod__(self, other: int) -> Combinable: ...
35-
def __pow__(self, other: float) -> Combinable: ...
36-
def __and__(self, other: Combinable) -> Any: ...
37-
def bitand(self, other: int) -> CombinedExpression: ...
38-
def bitleftshift(self, other: int) -> CombinedExpression: ...
39-
def bitrightshift(self, other: int) -> CombinedExpression: ...
40-
def __or__(self, other: Combinable) -> Any: ...
41-
def bitor(self, other: int) -> CombinedExpression: ...
42-
def __radd__(self, other: Optional[Union[datetime, float]]) -> CombinedExpression: ...
43-
def __rsub__(self, other: float) -> CombinedExpression: ...
44-
def __rmul__(self, other: float) -> CombinedExpression: ...
45-
def __rtruediv__(self, other: float) -> CombinedExpression: ...
46-
def __rmod__(self, other: int) -> CombinedExpression: ...
47-
def __rpow__(self, other: float) -> CombinedExpression: ...
48-
def __rand__(self, other: Any) -> Any: ...
49-
def __ror__(self, other: Any) -> Any: ...
30+
def __neg__(self: _SelfCombinable) -> _SelfCombinable: ...
31+
def __add__(
32+
self: _SelfCombinable, other: Optional[Union[timedelta, Combinable, float, str]]
33+
) -> _SelfCombinable: ...
34+
def __sub__(self: _SelfCombinable, other: Union[timedelta, Combinable, float]) -> _SelfCombinable: ...
35+
def __mul__(self: _SelfCombinable, other: Union[timedelta, Combinable, float]) -> _SelfCombinable: ...
36+
def __truediv__(self: _SelfCombinable, other: Union[Combinable, float]) -> _SelfCombinable: ...
37+
def __itruediv__(self: _SelfCombinable, other: Union[Combinable, float]) -> _SelfCombinable: ...
38+
def __mod__(self: _SelfCombinable, other: Union[int, Combinable]) -> _SelfCombinable: ...
39+
def __pow__(self: _SelfCombinable, other: Union[float, Combinable]) -> _SelfCombinable: ...
40+
def __and__(self: _SelfCombinable, other: Combinable) -> _SelfCombinable: ...
41+
def bitand(self: _SelfCombinable, other: int) -> _SelfCombinable: ...
42+
def bitleftshift(self: _SelfCombinable, other: int) -> _SelfCombinable: ...
43+
def bitrightshift(self: _SelfCombinable, other: int) -> _SelfCombinable: ...
44+
def __or__(self: _SelfCombinable, other: Combinable) -> _SelfCombinable: ...
45+
def bitor(self: _SelfCombinable, other: int) -> _SelfCombinable: ...
46+
def __radd__(self, other: Optional[Union[datetime, float, Combinable]]) -> Combinable: ...
47+
def __rsub__(self, other: Union[float, Combinable]) -> Combinable: ...
48+
def __rmul__(self, other: Union[float, Combinable]) -> Combinable: ...
49+
def __rtruediv__(self, other: Union[float, Combinable]) -> Combinable: ...
50+
def __rmod__(self, other: Union[int, Combinable]) -> Combinable: ...
51+
def __rpow__(self, other: Union[float, Combinable]) -> Combinable: ...
52+
def __rand__(self, other: Any) -> Combinable: ...
53+
def __ror__(self, other: Any) -> Combinable: ...
54+
55+
_SelfBaseExpression = TypeVar("_SelfBaseExpression", bound="BaseExpression")
5056

5157
class BaseExpression:
5258
is_summary: bool = ...
@@ -74,9 +80,9 @@ class BaseExpression:
7480
def convert_value(self) -> Callable: ...
7581
def get_lookup(self, lookup: str) -> Optional[Type[Lookup]]: ...
7682
def get_transform(self, name: str) -> Optional[Type[Expression]]: ...
77-
def relabeled_clone(self, change_map: Union[Dict[Optional[str], str], OrderedDict]) -> Expression: ...
83+
def relabeled_clone(self, change_map: Dict[Optional[str], str]) -> Expression: ...
7884
def copy(self) -> BaseExpression: ...
79-
def get_group_by_cols(self) -> List[Expression]: ...
85+
def get_group_by_cols(self: _SelfBaseExpression) -> List[_SelfBaseExpression]: ...
8086
def get_source_fields(self) -> List[Optional[Field]]: ...
8187
def asc(self, **kwargs: Any) -> Expression: ...
8288
def desc(self, **kwargs: Any) -> Expression: ...
@@ -125,7 +131,8 @@ class F(Combinable):
125131
def desc(self, **kwargs) -> OrderBy: ...
126132
def deconstruct(self) -> Any: ...
127133

128-
class OuterRef(F): ...
134+
class OuterRef(F):
135+
def __init__(self, name: Union[str, OuterRef]): ...
129136

130137
class Subquery(Expression):
131138
template: str = ...
@@ -197,6 +204,18 @@ class Case(Expression):
197204
) -> None: ...
198205

199206
class ExpressionWrapper(Expression):
200-
def __init__(self, expression: Union[Expression, Q], output_field: _OutputField): ...
207+
def __init__(self, expression: Union[Q, Combinable], output_field: _OutputField): ...
201208
def set_source_expressions(self, exprs: Sequence[Expression]) -> None: ...
202209
def get_source_expressions(self) -> List[Expression]: ...
210+
211+
class Col(Expression):
212+
def __init__(self, alias: str, target: str, output_field: Optional[_OutputField] = ...): ...
213+
214+
class ExpressionList(Func):
215+
def __init__(self, *expressions: Union[BaseExpression, Combinable], **extra: Any) -> None: ...
216+
217+
class Random(Expression):
218+
output_field: FloatField
219+
220+
class Ref(Expression):
221+
def __init__(self, refs: str, source: Expression): ...

django-stubs/db/models/fields/__init__.pyi

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ from typing import Any, Optional, Tuple, Iterable, Callable, Dict, Union, Type
22

33
from django.db.models import Model
44
from django.db.models.query_utils import RegisterLookupMixin
5+
6+
from django.db.models.expressions import F, Combinable
57
from django.forms import Widget, Field as FormField
68

79
_Choice = Tuple[Any, str]
@@ -52,6 +54,7 @@ class Field(RegisterLookupMixin):
5254
def contribute_to_class(self, cls: Type[Model], name: str, private_only: bool = ...) -> None: ...
5355

5456
class IntegerField(Field):
57+
def __set__(self, instance, value: Union[int, F]) -> None: ...
5558
def __get__(self, instance, owner) -> int: ...
5659

5760
class PositiveIntegerRelDbTypeMixin:
@@ -115,7 +118,7 @@ class CharField(Field):
115118
validators: Iterable[_ValidatorCallable] = ...,
116119
error_messages: Optional[_ErrorMessagesToOverride] = ...,
117120
): ...
118-
def __set__(self, instance, value: str) -> None: ...
121+
def __set__(self, instance, value: Union[str, Combinable]) -> None: ...
119122
def __get__(self, instance, owner) -> str: ...
120123

121124
class SlugField(CharField):

django-stubs/db/models/fields/related.pyi

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ from django.db.models.fields.reverse_related import (
3232
)
3333
from django.db.models.query_utils import PathInfo, Q
3434

35+
from django.db.models.expressions import F
36+
3537
if TYPE_CHECKING:
3638
from django.db.models.manager import RelatedManager
3739

@@ -102,6 +104,7 @@ class ForeignObject(RelatedField):
102104

103105
class ForeignKey(RelatedField, Generic[_T]):
104106
def __init__(self, to: Union[Type[_T], str], on_delete: Any, related_name: str = ..., **kwargs): ...
107+
def __set__(self, instance, value: Union[Model, F]) -> None: ...
105108
def __get__(self, instance, owner) -> _T: ...
106109

107110
class OneToOneField(RelatedField, Generic[_T]):

scripts/typecheck_tests.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@
201201
# TODO: 'dispatch',
202202
'distinct_on_fields',
203203
'empty',
204-
# TODO: 'expressions',
204+
'expressions',
205205
'expressions_case',
206206
# TODO: 'expressions_window',
207207
# TODO: 'extra_regress',

0 commit comments

Comments
 (0)