Skip to content

Commit 59aa6e4

Browse files
committed
Fix type-checking of Django tests after removing fallback_to_any on Model.
- Correct arg type for sort_dependencies so they are covariant (Iterable rather than List). - Added a stub for __getstate__ to Model. - Added a stub for clean() to Model. - Added some test ignores in cases where a model inherits from 2 different base models. - Added some test ignores for cases that MyPy flags as errors due to variable redefinitions or imports that are incompatible types.
1 parent 4749a88 commit 59aa6e4

File tree

3 files changed

+35
-9
lines changed

3 files changed

+35
-9
lines changed

django-stubs/core/serializers/__init__.pyi

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
from collections import OrderedDict
2-
from typing import Any, Callable, Dict, Iterator, List, Optional, Tuple, Type, Union
1+
from typing import Any, Callable, Dict, Iterator, List, Optional, Tuple, Type, Union, Iterable
32

43
from django.apps.config import AppConfig
54
from django.db.models.base import Model
@@ -33,5 +32,5 @@ def serialize(
3332
) -> Optional[Union[bytes, str]]: ...
3433
def deserialize(format: str, stream_or_string: Any, **options: Any) -> Union[Iterator[Any], Deserializer]: ...
3534
def sort_dependencies(
36-
app_list: Union[List[Tuple[AppConfig, None]], List[Tuple[str, List[Type[Model]]]]]
35+
app_list: Union[Iterable[Tuple[AppConfig, None]], Iterable[Tuple[str, Iterable[Type[Model]]]]]
3736
) -> List[Type[Model]]: ...

django-stubs/db/models/base.pyi

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ class Model(metaclass=ModelBase):
1616
def __init__(self: _Self, *args, **kwargs) -> None: ...
1717
def delete(self, using: Any = ..., keep_parents: bool = ...) -> Tuple[int, Dict[str, int]]: ...
1818
def full_clean(self, exclude: Optional[List[str]] = ..., validate_unique: bool = ...) -> None: ...
19+
def clean(self) -> None: ...
1920
def clean_fields(self, exclude: List[str] = ...) -> None: ...
2021
def validate_unique(self, exclude: List[str] = ...) -> None: ...
2122
def save(
@@ -35,6 +36,8 @@ class Model(metaclass=ModelBase):
3536
): ...
3637
def refresh_from_db(self: _Self, using: Optional[str] = ..., fields: Optional[List[str]] = ...) -> _Self: ...
3738
def get_deferred_fields(self) -> Set[str]: ...
39+
def __getstate__(self) -> dict: ...
40+
3841

3942
class ModelStateFieldsCacheDescriptor: ...
4043

scripts/typecheck_tests.py

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -213,11 +213,13 @@
213213
'Unexpected keyword argument "headline__startswith" for "in_bulk" of "QuerySet"',
214214
],
215215
'many_to_one': [
216-
'Incompatible type for "parent" of "Child" (got "None", expected "Union[Parent, Combinable]")'
216+
'Incompatible type for "parent" of "Child" (got "None", expected "Union[Parent, Combinable]")',
217+
'Incompatible type for "parent" of "Child" (got "Child", expected "Union[Parent, Combinable]")'
217218
],
218219
'model_meta': [
219220
'"object" has no attribute "items"',
220-
'"Field" has no attribute "many_to_many"'
221+
'"Field" has no attribute "many_to_many"',
222+
re.compile(r'Definition of "(objects|_default_manager)" in base class "FirstParent" is incompatible with definition in base class "SecondParent"'),
221223
],
222224
'model_forms': [
223225
'Argument "instance" to "InvalidModelForm" has incompatible type "Type[Category]"; expected "Optional[Model]"',
@@ -229,14 +231,22 @@
229231
'Cannot assign multiple types to name "PersonTwoImages" without an explicit "Type[...]" annotation',
230232
'Incompatible types in assignment (expression has type "Type[Person]", '
231233
+ 'base class "ImageFieldTestMixin" defined the type as "Type[PersonWithHeightAndWidth]")',
232-
],
234+
re.compile(
235+
r'Incompatible types in assignment \(expression has type "Type\[.+?\]", base class "IntegerFieldTests" defined the type as "Type\[IntegerModel\]"\)'),
236+
re.compile(r'Incompatible types in assignment \(expression has type "Type\[.+?\]", base class "ImageFieldTestMixin" defined the type as "Type\[PersonWithHeightAndWidth\]"\)'),
237+
'Incompatible import of "Person"',
238+
'Incompatible types in assignment (expression has type "FloatModel", variable has type "Union[float, int, str, Combinable]")',
239+
],
233240
'model_formsets': [
234241
'Incompatible types in string interpolation (expression has type "object", '
235242
+ 'placeholder has type "Union[int, float]")'
236243
],
237244
'model_formsets_regress': [
238245
'Incompatible types in assignment (expression has type "Model", variable has type "User")'
239246
],
247+
'model_inheritance_regress': [
248+
re.compile(r'Definition of "(objects|_default_manager)" in base class "Person" is incompatible with definition in base class "Politician"'),
249+
],
240250
'model_regress': [
241251
'Too many arguments for "Worker"',
242252
re.compile(r'Incompatible type for "[a-z]+" of "Worker" \(got "int", expected')
@@ -261,7 +271,8 @@
261271
'Argument 1 to "RunPython" has incompatible type "str"; expected "Callable[..., Any]"',
262272
'FakeLoader',
263273
'Argument 1 to "append" of "list" has incompatible type "AddIndex"; expected "CreateModel"',
264-
'Unsupported operand types for - ("Set[Any]" and "None")'
274+
'Unsupported operand types for - ("Set[Any]" and "None")',
275+
re.compile(r'Definition of "(objects|_default_manager)" in base class "Foo" is incompatible with definition in base class "Bar"'),
265276
],
266277
'middleware_exceptions': [
267278
'Argument 1 to "append" of "list" has incompatible type "Tuple[Any, Any]"; expected "str"'
@@ -282,7 +293,9 @@
282293
+ 'expected "Optional[Type[JSONEncoder]]"',
283294
'for model "CITestModel"',
284295
'Incompatible type for "field" of "IntegerArrayModel" (got "None", '
285-
+ 'expected "Union[Sequence[int], Combinable]")'
296+
+ 'expected "Union[Sequence[int], Combinable]")',
297+
re.compile(r'Incompatible types in assignment \(expression has type "Type\[.+?\]", base class "UnaccentTest" defined the type as "Type\[CharFieldModel\]"\)'),
298+
'Incompatible types in assignment (expression has type "Type[TextFieldModel]", base class "TrigramTest" defined the type as "Type[CharFieldModel]")',
286299
],
287300
'properties': [
288301
re.compile('Unexpected attribute "(full_name|full_name_2)" for model "Person"')
@@ -291,6 +304,11 @@
291304
'Incompatible types in assignment (expression has type "None", variable has type "str")',
292305
'Invalid index type "Optional[str]" for "Dict[str, int]"; expected type "str"',
293306
'No overload variant of "values_list" of "QuerySet" matches argument types "str", "bool", "bool"',
307+
'Unsupported operand types for & ("QuerySet[Author, Author]" and "QuerySet[Tag, Tag]")',
308+
'Unsupported operand types for | ("QuerySet[Author, Author]" and "QuerySet[Tag, Tag]")',
309+
'Incompatible types in assignment (expression has type "ObjectB", variable has type "ObjectA")',
310+
'Incompatible types in assignment (expression has type "ObjectC", variable has type "ObjectA")',
311+
'Incompatible type for "objectb" of "ObjectC" (got "ObjectA", expected "Union[ObjectB, Combinable, None, None]")',
294312
],
295313
'requests': [
296314
'Incompatible types in assignment (expression has type "Dict[str, str]", variable has type "QueryDict")'
@@ -303,6 +321,9 @@
303321
'"None" has no attribute "__iter__"',
304322
'has no attribute "read_by"'
305323
],
324+
'proxy_model_inheritance': [
325+
'Incompatible import of "ProxyModel"'
326+
],
306327
'signals': [
307328
'Argument 1 to "append" of "list" has incompatible type "Tuple[Any, Any, Optional[Any], Any]"; '
308329
+ 'expected "Tuple[Any, Any, Any]"'
@@ -387,7 +408,10 @@
387408
'Incompatible types in assignment (expression has type "None", variable has type "int")',
388409
],
389410
'select_related_onetoone': [
390-
'"None" has no attribute'
411+
'"None" has no attribute',
412+
'Incompatible types in assignment (expression has type "Parent2", variable has type "Parent1")',
413+
'Definition of "objects" in base class "Parent1" is incompatible with definition in base class "Parent2"',
414+
'Definition of "_default_manager" in base class "Parent1" is incompatible with definition in base class "Parent2"',
391415
],
392416
'servers': [
393417
re.compile('Argument [0-9] to "WSGIRequestHandler"')

0 commit comments

Comments
 (0)