Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

var-annotated error with imported BaseModel, related to namespace module #658

Closed
blueyed opened this issue Jul 2, 2021 · 4 comments · Fixed by #2263
Closed

var-annotated error with imported BaseModel, related to namespace module #658

blueyed opened this issue Jul 2, 2021 · 4 comments · Fixed by #2263
Labels
bug Something isn't working

Comments

@blueyed
Copy link
Contributor

blueyed commented Jul 2, 2021

As a followup to #68 I've noticed that it would not work with:

from django.db import models
from ...base.models import BaseModelMixin


# class BaseModelMixin(models.Model):
#     class Meta:
#         abstract = True


class TestModel(BaseModelMixin):
    foo = models.CharField(max_length=123)

error: Need type annotation for "foo" [var-annotated]

The imported model is the same as the commented one.

If not importing it, but defining it there (uncommenting it), it works:

from django.db import models
# from ...base.models import BaseModelMixin


class BaseModelMixin(models.Model):
    class Meta:
        abstract = True


class TestModel(BaseModelMixin):
    foo = models.CharField(max_length=123)

Note that it also fails when overwriting the import:

from django.db import models
# from ...base.models import BaseModelMixin


class BaseModelMixin(models.Model):
    class Meta:
        abstract = True


class TestModel(BaseModelMixin):
    foo = models.CharField(max_length=123)
…/models.py:5: error: Name "BaseModelMixin" already defined (possibly by an import)  [no-redef]                                                                                                    
…/models.py:11: error: Need type annotation for "foo"  [var-annotated]                                                                                                                             

I've not investigated much yet, but it appears to be caused by the models fullname not containing the first part of the (namespaced) module name: app.models.TestModel vs project.app.models.TestModel (via django_context.all_registered_model_class_fullnames)..!

This results in the is_model_subclass_info check only working if it is defined in the same file (via info.has_base check - shouldn't that work better maybe in general?):

def is_model_subclass_info(info: TypeInfo, django_context: "DjangoContext") -> bool:
return info.fullname in django_context.all_registered_model_class_fullnames or info.has_base(
fullnames.MODEL_CLASS_FULLNAME
)

Note that the namespace ("project") is added/used via AppConfig:

class MyAppConfig(AppConfig):
    name = "project.app"

project/__init__.py does not exist, but creating it and/or changing ProductConfig.name to not include the namespace changes the behavior.

System information

  • OS: Arch Linux
  • python version: 3.9.5
  • django version: 4.0.dev20210602105309
  • mypy version: 0.910
  • django-stubs version: 1.8.0
  • django-stubs-ext version: 0.2.0
@blueyed blueyed added the bug Something isn't working label Jul 2, 2021
@sobolevn
Copy link
Member

sobolevn commented Jul 2, 2021

@blueyed thanks for the report! Do you have a solution in mind?
I would love to merge a fix for this.

@nrbnlulu
Copy link

Any updates on this one?

@Leghart
Copy link

Leghart commented Nov 17, 2023

Any updates?

@realsuayip
Copy link
Contributor

Monkey-patching as following seems to be fixing the issue:

import mypy_django_plugin.lib.helpers
from mypy_django_plugin.lib.helpers import is_model_subclass_info as patch

PREFIX = "project."  # name of your namespace module


def is_model_subclass_info(info, django_context):
    if info.fullname.startswith(PREFIX):
        name = info.fullname[len(PREFIX) :]  # use removeprefix if py>=39
        if name in django_context.all_registered_model_class_fullnames:
            return True
    return patch(info, django_context)


mypy_django_plugin.lib.helpers.is_model_subclass_info = is_model_subclass_info

running mypy like so:

mypy -p project

@sobolevn I'm guessing we need to prefix namespace modules in all_registered_model_class_fullnames property? I'm not sure if how would we fetch that information in that context.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Development

Successfully merging a pull request may close this issue.

5 participants