mirror of
https://github.com/davidhalter/django-stubs.git
synced 2025-12-08 13:04:47 +08:00
Fix type errors on other models' managers when using objects = models.Manager() in Model. (#34)
* Fix bug where models with a class variable using a manager defined would interfere with other managers. - Fill in the type argument for that particular instance of the manager, rather than modifying the bases of the Manager type. - Instantiate a new Instance from determine_proper_manager_type so The code doesn't crash under mypy-mypyc. * Use helpers.reparametrize_instance per review comment. * Updated ignored errors in Django test for get_objects_or_404. - For some reason, `Manager[nothing]` is now removed from expected types. However, I think this makes sense anyway, as Manager is a subclass of QuerySet.
This commit is contained in:
committed by
Maxim Kurnikov
parent
050c1b8887
commit
86c63d790b
@@ -64,12 +64,19 @@ def determine_proper_manager_type(ctx: FunctionContext) -> Type:
|
|||||||
if not isinstance(ret, Instance):
|
if not isinstance(ret, Instance):
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
has_manager_base = False
|
||||||
for i, base in enumerate(ret.type.bases):
|
for i, base in enumerate(ret.type.bases):
|
||||||
if base.type.fullname() in {helpers.MANAGER_CLASS_FULLNAME,
|
if base.type.fullname() in {helpers.MANAGER_CLASS_FULLNAME,
|
||||||
helpers.RELATED_MANAGER_CLASS_FULLNAME,
|
helpers.RELATED_MANAGER_CLASS_FULLNAME,
|
||||||
helpers.BASE_MANAGER_CLASS_FULLNAME}:
|
helpers.BASE_MANAGER_CLASS_FULLNAME}:
|
||||||
ret.type.bases[i] = Instance(base.type, [Instance(outer_model_info, [])])
|
has_manager_base = True
|
||||||
return ret
|
break
|
||||||
|
|
||||||
|
if has_manager_base:
|
||||||
|
# Fill in the manager's type argument from the outer model
|
||||||
|
new_type_args = [Instance(outer_model_info, [])]
|
||||||
|
return helpers.reparametrize_instance(ret, new_type_args)
|
||||||
|
else:
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -199,9 +199,9 @@ IGNORED_ERRORS = {
|
|||||||
],
|
],
|
||||||
'get_object_or_404': [
|
'get_object_or_404': [
|
||||||
'Argument 1 to "get_object_or_404" has incompatible type "str"; '
|
'Argument 1 to "get_object_or_404" has incompatible type "str"; '
|
||||||
+ 'expected "Union[Type[<nothing>], Manager[<nothing>], QuerySet[<nothing>]]"',
|
+ 'expected "Union[Type[<nothing>], QuerySet[<nothing>]]"',
|
||||||
'Argument 1 to "get_list_or_404" has incompatible type "List[Type[Article]]"; '
|
'Argument 1 to "get_list_or_404" has incompatible type "List[Type[Article]]"; '
|
||||||
+ 'expected "Union[Type[<nothing>], Manager[<nothing>], QuerySet[<nothing>]]"',
|
+ 'expected "Union[Type[<nothing>], QuerySet[<nothing>]]"',
|
||||||
'CustomClass'
|
'CustomClass'
|
||||||
],
|
],
|
||||||
'get_or_create': [
|
'get_or_create': [
|
||||||
|
|||||||
@@ -137,3 +137,65 @@ class AbstractBase2(models.Model):
|
|||||||
class Child(AbstractBase1, AbstractBase2):
|
class Child(AbstractBase1, AbstractBase2):
|
||||||
pass
|
pass
|
||||||
[out]
|
[out]
|
||||||
|
|
||||||
|
[CASE managers_from_unrelated_models_dont_interfere]
|
||||||
|
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
# Normal scenario where one model has a manager with an annotation of the same type as the model
|
||||||
|
class UnrelatedModel(models.Model):
|
||||||
|
objects = models.Manager[UnrelatedModel]()
|
||||||
|
|
||||||
|
class MyModel(models.Model):
|
||||||
|
pass
|
||||||
|
|
||||||
|
reveal_type(UnrelatedModel.objects) # E: Revealed type is 'django.db.models.manager.Manager[main.UnrelatedModel]'
|
||||||
|
reveal_type(UnrelatedModel.objects.first()) # E: Revealed type is 'Union[main.UnrelatedModel*, None]'
|
||||||
|
|
||||||
|
reveal_type(MyModel.objects) # E: Revealed type is 'django.db.models.manager.Manager[main.MyModel]'
|
||||||
|
reveal_type(MyModel.objects.first()) # E: Revealed type is 'Union[main.MyModel*, None]'
|
||||||
|
|
||||||
|
# Possible to specify objects without explicit annotation of models.Manager()
|
||||||
|
class UnrelatedModel2(models.Model):
|
||||||
|
objects = models.Manager()
|
||||||
|
|
||||||
|
class MyModel2(models.Model):
|
||||||
|
pass
|
||||||
|
|
||||||
|
reveal_type(UnrelatedModel2.objects) # E: Revealed type is 'django.db.models.manager.Manager[main.UnrelatedModel2]'
|
||||||
|
reveal_type(UnrelatedModel2.objects.first()) # E: Revealed type is 'Union[main.UnrelatedModel2*, None]'
|
||||||
|
|
||||||
|
reveal_type(MyModel2.objects) # E: Revealed type is 'django.db.models.manager.Manager[main.MyModel2]'
|
||||||
|
reveal_type(MyModel2.objects.first()) # E: Revealed type is 'Union[main.MyModel2*, None]'
|
||||||
|
|
||||||
|
|
||||||
|
# Inheritance works
|
||||||
|
class ParentOfMyModel3(models.Model):
|
||||||
|
objects = models.Manager()
|
||||||
|
|
||||||
|
class MyModel3(ParentOfMyModel3):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
reveal_type(ParentOfMyModel3.objects) # E: Revealed type is 'django.db.models.manager.Manager[main.ParentOfMyModel3]'
|
||||||
|
reveal_type(ParentOfMyModel3.objects.first()) # E: Revealed type is 'Union[main.ParentOfMyModel3*, None]'
|
||||||
|
|
||||||
|
reveal_type(MyModel3.objects) # E: Revealed type is 'django.db.models.manager.Manager[main.MyModel3]'
|
||||||
|
reveal_type(MyModel3.objects.first()) # E: Revealed type is 'Union[main.MyModel3*, None]'
|
||||||
|
|
||||||
|
|
||||||
|
# Inheritance works with explicit objects in child
|
||||||
|
class ParentOfMyModel4(models.Model):
|
||||||
|
objects = models.Manager()
|
||||||
|
|
||||||
|
class MyModel4(ParentOfMyModel4):
|
||||||
|
objects = models.Manager[MyModel4]()
|
||||||
|
|
||||||
|
reveal_type(ParentOfMyModel4.objects) # E: Revealed type is 'django.db.models.manager.Manager[main.ParentOfMyModel4]'
|
||||||
|
reveal_type(ParentOfMyModel4.objects.first()) # E: Revealed type is 'Union[main.ParentOfMyModel4*, None]'
|
||||||
|
|
||||||
|
reveal_type(MyModel4.objects) # E: Revealed type is 'django.db.models.manager.Manager[main.MyModel4]'
|
||||||
|
reveal_type(MyModel4.objects.first()) # E: Revealed type is 'Union[main.MyModel4*, None]'
|
||||||
|
|
||||||
|
|
||||||
|
[out]
|
||||||
Reference in New Issue
Block a user