Skip to content

Commit 5ad4d1c

Browse files
Alexersonintgr
andauthored
Various fixes for Django 4.2 (#1536)
* Add new postgres lookups * New encoder parameter for django.utils.html.json_script * `F` expression that output `BooleanField` can now be negated * django.forms.ModelForm now accepts a new Meta option formfield_callback * New KT expression for django.db.models.JSONField * Fix `json.KeyTextTransform.from_lookup` * Fix NegatedExpression typing * Fix NegatedExpression related types * Adding generics to monkeypatch * Fix NegatedExpression typevar * Removed NegatedExpression from monkeypatching, see comments --------- Co-authored-by: Marti Raudsepp <[email protected]>
1 parent f4649af commit 5ad4d1c

File tree

7 files changed

+35
-6
lines changed

7 files changed

+35
-6
lines changed

django-stubs/contrib/postgres/lookups.pyi

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,5 @@ class HasAnyKeys(HasKeys): ...
1212
class Unaccent(Transform): ...
1313
class SearchLookup(SearchVectorExact): ...
1414
class TrigramSimilar(PostgresOperatorLookup): ...
15+
class TrigramWordSimilar(PostgresOperatorLookup): ...
16+
class TrigramStrictWordSimilar(PostgresOperatorLookup): ...

django-stubs/contrib/postgres/search.pyi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ class SearchQuery(SearchQueryCombinable, Func): # type: ignore
5959
invert: bool = ...,
6060
search_type: str = ...,
6161
) -> None: ...
62-
def __invert__(self: Self) -> Self: ...
62+
def __invert__(self: Self) -> Self: ... # type: ignore[override]
6363

6464
class CombinedSearchQuery(SearchQueryCombinable, CombinedExpression): # type: ignore
6565
def __init__(

django-stubs/db/models/expressions.pyi

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import datetime
22
from collections.abc import Callable, Iterable, Iterator, Sequence
33
from decimal import Decimal
4-
from typing import Any, Literal
4+
from typing import Any, Generic, Literal, TypeVar
55

66
from _typeshed import Self
77
from django.db.backends.base.base import BaseDatabaseWrapper
@@ -41,6 +41,7 @@ class Combinable:
4141
def bitand(self, other: int) -> CombinedExpression: ...
4242
def bitleftshift(self, other: int) -> CombinedExpression: ...
4343
def bitrightshift(self, other: int) -> CombinedExpression: ...
44+
def __xor__(self, other: Combinable | Q) -> Q: ...
4445
def bitxor(self, other: int) -> CombinedExpression: ...
4546
def __or__(self, other: Combinable | Q) -> Q: ...
4647
def bitor(self, other: int) -> CombinedExpression: ...
@@ -52,6 +53,8 @@ class Combinable:
5253
def __rpow__(self, other: _Numeric | Combinable) -> CombinedExpression: ...
5354
def __rand__(self, other: Any) -> Combinable: ...
5455
def __ror__(self, other: Any) -> Combinable: ...
56+
def __rxor__(self, other: Any) -> Combinable: ...
57+
def __invert__(self) -> NegatedExpression[Combinable]: ...
5558

5659
class BaseExpression:
5760
is_summary: bool
@@ -199,8 +202,15 @@ class ExpressionList(Func):
199202

200203
class OrderByList(Func): ...
201204

202-
class ExpressionWrapper(Expression):
203-
def __init__(self, expression: Q | Combinable, output_field: Field) -> None: ...
205+
_E = TypeVar("_E", bound=Q | Combinable)
206+
207+
class ExpressionWrapper(Expression, Generic[_E]):
208+
def __init__(self, expression: _E, output_field: Field) -> None: ...
209+
expression: _E
210+
211+
class NegatedExpression(ExpressionWrapper[_E]):
212+
def __init__(self, expression: _E) -> None: ...
213+
def __invert__(self) -> _E: ... # type: ignore[override]
204214

205215
class When(Expression):
206216
template: str
@@ -226,7 +236,6 @@ class Subquery(BaseExpression, Combinable):
226236

227237
class Exists(Subquery):
228238
def __init__(self, queryset: Query | QuerySet, **kwargs: Any) -> None: ...
229-
def __invert__(self) -> Exists: ...
230239

231240
class OrderBy(Expression):
232241
template: str

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import json
2+
from collections.abc import Callable
23
from typing import Any
34

5+
from _typeshed import Self
46
from django.db.backends.base.base import BaseDatabaseWrapper
57
from django.db.models import lookups
68
from django.db.models.lookups import PostgresOperatorLookup, Transform
@@ -27,6 +29,7 @@ class ContainedBy(PostgresOperatorLookup): ...
2729

2830
class HasKeyLookup(PostgresOperatorLookup):
2931
logical_operator: str | None
32+
def compile_json_path_final_key(self, key_transform: Any) -> str: ...
3033

3134
class HasKey(HasKeyLookup):
3235
postgres_operator: str
@@ -39,7 +42,9 @@ class HasAnyKeys(HasKeys):
3942
postgres_operator: str
4043
logical_operator: str
4144

45+
class HasKeyOrArrayIndex(HasKey): ...
4246
class JSONExact(lookups.Exact): ...
47+
class JSONIContains(CaseInsensitiveMixin, lookups.IContains): ...
4348

4449
class KeyTransform(Transform):
4550
key_name: str
@@ -51,6 +56,10 @@ class KeyTransform(Transform):
5156
class KeyTextTransform(KeyTransform):
5257
postgres_operator: str
5358
postgres_nested_operator: str
59+
@classmethod
60+
def from_lookup(cls: type[Self], lookup: str) -> Self: ...
61+
62+
KT: Callable[[str], KeyTextTransform]
5463

5564
class KeyTransformTextLookupMixin:
5665
def __init__(self, key_transform: Any, *args: Any, **kwargs: Any) -> None: ...

django-stubs/forms/models.pyi

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ class ModelFormOptions(Generic[_M]):
7070
help_texts: _HelpTexts | None
7171
error_messages: _ErrorMessages | None
7272
field_classes: dict[str, type[Field]] | None
73+
formfield_callback: _FormFieldCallback | None
7374
def __init__(self, options: type | None = ...) -> None: ...
7475

7576
class ModelFormMetaclass(DeclarativeFieldsMetaclass): ...
@@ -116,6 +117,7 @@ _ModelFormT = TypeVar("_ModelFormT", bound=ModelForm)
116117

117118
class BaseModelFormSet(Generic[_M, _ModelFormT], BaseFormSet[_ModelFormT]):
118119
model: type[_M]
120+
edit_only: bool
119121
unique_fields: Collection[str]
120122
queryset: QuerySet[_M] | None
121123
initial_extra: Sequence[dict[str, Any]] | None
@@ -172,6 +174,8 @@ def modelformset_factory(
172174
field_classes: Mapping[str, type[Field]] | None = ...,
173175
absolute_max: int | None = ...,
174176
can_delete_extra: bool = ...,
177+
renderer: BaseRenderer | None = ...,
178+
edit_only: bool = ...,
175179
) -> type[BaseModelFormSet[_M, _ModelFormT]]: ...
176180

177181
class BaseInlineFormSet(Generic[_M, _ParentM, _ModelFormT], BaseModelFormSet[_M, _ModelFormT]):
@@ -220,6 +224,8 @@ def inlineformset_factory(
220224
field_classes: Mapping[str, type[Field]] | None = ...,
221225
absolute_max: int | None = ...,
222226
can_delete_extra: bool = ...,
227+
renderer: BaseRenderer | None = ...,
228+
edit_only: bool = ...,
223229
) -> type[BaseInlineFormSet[_M, _ParentM, _ModelFormT]]: ...
224230

225231
class InlineForeignKeyField(Field):

django-stubs/utils/html.pyi

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from collections.abc import Iterable
22
from html.parser import HTMLParser
3+
from json import JSONEncoder
34
from re import Pattern
45
from typing import Any
56

@@ -14,7 +15,7 @@ simple_url_2_re: Pattern[str]
1415

1516
def escape(text: Any) -> SafeString: ...
1617
def escapejs(value: Any) -> SafeString: ...
17-
def json_script(value: Any, element_id: str) -> SafeString: ...
18+
def json_script(value: Any, element_id: str | None = ..., encoder: type[JSONEncoder] | None = ...) -> SafeString: ...
1819
def conditional_escape(text: Any) -> str: ...
1920
def format_html(format_string: str, *args: Any, **kwargs: Any) -> SafeString: ...
2021
def format_html_join(sep: str, format_string: str, args_generator: Iterable[Iterable[Any]]) -> SafeString: ...

django_stubs_ext/django_stubs_ext/patch.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from django.contrib.syndication.views import Feed
99
from django.core.files.utils import FileProxyMixin
1010
from django.core.paginator import Paginator
11+
from django.db.models.expressions import ExpressionWrapper
1112
from django.db.models.fields import Field
1213
from django.db.models.fields.related import ForeignKey
1314
from django.db.models.lookups import Lookup
@@ -66,6 +67,7 @@ def __repr__(self) -> str:
6667
MPGeneric(FileProxyMixin),
6768
MPGeneric(Lookup),
6869
MPGeneric(BaseConnectionHandler),
70+
MPGeneric(ExpressionWrapper),
6971
# These types do have native `__class_getitem__` method since django 3.1:
7072
MPGeneric(QuerySet, (3, 1)),
7173
MPGeneric(BaseManager, (3, 1)),

0 commit comments

Comments
 (0)