52/model subtypes dont typecheck (#55)

* Fix problem where Model instancess are not considered subtypes of each other due to fallback_to_any = True. Fixes #52.

- Added a stub for __getstate__ to Model.
- Added a stub for clean() to Model.
- Correct arg type for sort_dependencies so they are covariant (Iterable rather than List).

Test ignores:
- 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.

* Address review comment.
This commit is contained in:
Seth Yastrov
2019-03-28 21:13:02 +01:00
committed by Maxim Kurnikov
parent 9288c34648
commit 71fb0432f3
7 changed files with 87 additions and 14 deletions

View File

@@ -21,7 +21,7 @@ from django.db import models
class MyModel(models.Model):
authors = models.Manager[MyModel]()
reveal_type(MyModel.authors) # E: Revealed type is 'django.db.models.manager.Manager[main.MyModel]'
reveal_type(MyModel.objects) # E: Revealed type is 'Any'
MyModel.objects # E: "Type[MyModel]" has no attribute "objects"
[out]
[CASE test_model_objects_attribute_present_in_case_of_model_cls_passed_as_generic_parameter]

View File

@@ -0,0 +1,28 @@
[CASE test_model_subtype_relationship_and_getting_and_setting_attributes]
from django.db import models
class A(models.Model):
pass
class B(models.Model):
b_attr = 1
pass
class C(A):
pass
def service(a: A) -> int:
pass
a_instance = A()
b_instance = B()
reveal_type(b_instance.b_attr) # E: Revealed type is 'builtins.int'
reveal_type(b_instance.non_existent_attribute) # E: Revealed type is 'Any'
b_instance.non_existent_attribute = 2
service(b_instance) # E: Argument 1 to "service" has incompatible type "B"; expected "A"
c_instance = C()
service(c_instance)

View File

@@ -27,12 +27,16 @@ class Parent1(models.Model):
class Parent2(models.Model):
id2 = models.AutoField(primary_key=True)
name2 = models.CharField(max_length=50)
# TODO: Remove the 2 expected errors on the next line once mypy issue https://github.com/python/mypy/issues/2619 is resolved:
class Child1(Parent1, Parent2):
value = models.IntegerField()
class Child4(Child1):
value4 = models.IntegerField()
Child4.objects.create(name1='n1', name2='n2', value=1, value4=4)
[out]
main:10: error: Definition of "objects" in base class "Parent1" is incompatible with definition in base class "Parent2"
main:10: error: Definition of "_default_manager" in base class "Parent1" is incompatible with definition in base class "Parent2"
[CASE optional_primary_key_for_create_is_error]
from django.db import models