diff --git a/mypy_django_plugin/lib/helpers.py b/mypy_django_plugin/lib/helpers.py index d6d7f9c67..ee0cf61d1 100644 --- a/mypy_django_plugin/lib/helpers.py +++ b/mypy_django_plugin/lib/helpers.py @@ -343,6 +343,7 @@ def copy_method_to_another_class(ctx: ClassDefContext, self_type: Instance, arguments = [] bound_return_type = semanal_api.anal_type(method_type.ret_type, allow_placeholder=True) + assert bound_return_type is not None if isinstance(bound_return_type, PlaceholderNode): @@ -352,6 +353,10 @@ def copy_method_to_another_class(ctx: ClassDefContext, self_type: Instance, method_type.arg_types[1:], method_node.arguments[1:]): bound_arg_type = semanal_api.anal_type(arg_type, allow_placeholder=True) + if bound_arg_type is None and not semanal_api.final_iteration: + semanal_api.defer() + return + assert bound_arg_type is not None if isinstance(bound_arg_type, PlaceholderNode): diff --git a/test-data/typecheck/managers/test_managers.yml b/test-data/typecheck/managers/test_managers.yml index 82206d645..6018938fa 100644 --- a/test-data/typecheck/managers/test_managers.yml +++ b/test-data/typecheck/managers/test_managers.yml @@ -335,3 +335,25 @@ objects = MyManager() class ChildUser(models.Model): objects = MyManager() + +- case: custom_manager_annotate_method_before_type_declaration + main: | + from myapp.models import ModelA, ModelB, ManagerA + reveal_type(ModelA.objects) # N: Revealed type is 'myapp.models.ModelA_ManagerA1[myapp.models.ModelA]' + reveal_type(ModelA.objects.do_something) # N: Revealed type is 'def (other_obj: myapp.models.ModelB) -> builtins.str' + installed_apps: + - myapp + files: + - path: myapp/__init__.py + - path: myapp/models.py + content: | + from django.db import models + class ManagerA(models.Manager): + def do_something(self, other_obj: "ModelB") -> str: + return 'test' + class ModelA(models.Model): + title = models.TextField() + objects = ManagerA() + class ModelB(models.Model): + movie = models.TextField() +