Skip to content

Commit

Permalink
Add fallback related manager in final iteration of AddRelatedManagers
Browse files Browse the repository at this point in the history
If a django model has a Manager class that cannot be resolved on runtime
(like django-money monkeypatches all default managers after models
already have been declared, and generates this manager as the return
value of a function, so it cannot be imported when we try to set up the
default related managers in AddDefaultManagerAttribute), we fallback to
a default related manager, so you at least get a base level of working
type checking.
  • Loading branch information
aleksanb committed Jun 14, 2022
1 parent ae5b1a4 commit eb3fae5
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 0 deletions.
1 change: 1 addition & 0 deletions mypy_django_plugin/errorcodes.py
@@ -1,3 +1,4 @@
from mypy.errorcodes import ErrorCode

MANAGER_UNTYPED = ErrorCode("django-manager", "Untyped manager disallowed", "Django")
MANAGER_MISSING = ErrorCode("django-manager-missing", "Couldn't resolve manager for model", "Django")
11 changes: 11 additions & 0 deletions mypy_django_plugin/transformers/models.py
Expand Up @@ -14,6 +14,7 @@
from mypy.types import TypedDictType, TypeOfAny

from mypy_django_plugin.django.context import DjangoContext
from mypy_django_plugin.errorcodes import MANAGER_MISSING
from mypy_django_plugin.lib import fullnames, helpers
from mypy_django_plugin.lib.fullnames import ANNOTATIONS_FULLNAME, ANY_ATTR_ALLOWED_CLASS_FULLNAME, MODEL_CLASS_FULLNAME
from mypy_django_plugin.lib.helpers import add_new_class_for_module
Expand Down Expand Up @@ -341,6 +342,7 @@ def run_with_model_cls(self, model_cls: Type[Model]) -> None:
continue

if isinstance(relation, (ManyToOneRel, ManyToManyRel)):
related_manager_info = None
try:
related_manager_info = self.lookup_typeinfo_or_incomplete_defn_error(
fullnames.RELATED_MANAGER_CLASS
Expand All @@ -352,6 +354,15 @@ def run_with_model_cls(self, model_cls: Type[Model]) -> None:
if not self.api.final_iteration:
raise exc
else:
if related_manager_info:
self.add_new_node_to_model_class(
attname, Instance(related_manager_info, [Instance(related_model_info, [])])
)
self.ctx.api.fail(
f"Couldn't resolve related manager for {model_cls}",
self.ctx.cls,
code=MANAGER_MISSING,
)
continue

# Check if the related model has a related manager subclassed from the default manager
Expand Down

0 comments on commit eb3fae5

Please sign in to comment.