我最近开始使用mymyy,并且遇到了一些奇怪的问题,我似乎一辈子也弄不清楚。
我使用的是mypy 0.950, django-stub 1.11.0, django 4.0.5和python 3.10.2.
通过命令行运行mypy返回如下:
project/suppliers/models.py:6: error: Name "Optional" is not defined
project/suppliers/models.py:6: note: Did you forget to import it from "typing"? (Suggestion: "from typing import Optional")
project/users/models.py:6: error: Name "Optional" is not defined
project/users/models.py:6: note: Did you forget to import it from "typing"? (Suggestion: "from typing import Optional")
project/products/models.py:6: error: Name "Optional" is not defined
project/products/models.py:6: note: Did you forget to import it from "typing"? (Suggestion: "from typing import Optional")(Suggestion: "from typing import Optional")
但是,project/suppliers/models.py
中的第6行是完全空的:
from django.contrib.sites.managers import CurrentSiteManager
from django.contrib.sites.models import Site
from django.db import models
from django.utils.text import slugify
from django.utils.translation import gettext_lazy as _
from django_countries.fields import CountryField
from project.core.models import BaseImageModel, BaseModel
from project.suppliers.managers import SupplierQuerySet
_SupplierManager = models.Manager.from_queryset(SupplierQuerySet)
class Supplier(BaseModel, BaseImageModel):
...
project/users/models.py
中的第6行是django导入from django.contrib.contenttypes.models import ContentType
:
import random
from typing import Any
from django.conf import settings
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
from django.contrib.contenttypes.models import ContentType
from django.contrib.sites.managers import CurrentSiteManager
from django.contrib.sites.models import Site
from django.core import signing
from django.core.mail import send_mail
from django.db import models
from django.forms import ValidationError
from django.http import HttpRequest
from django.template.loader import render_to_string
from django.utils import timezone
from django.utils.encoding import force_bytes, force_str
from django.utils.http import (
urlsafe_base64_decode as uid_decoder,
urlsafe_base64_encode as uid_encoder,
)
from django.utils.translation import gettext_lazy as _
import phonenumbers
from project.users.enums import AvatarColors
from project.users.managers import UserQuerySet
from project.users.schemas.records import (
UserAuditLogsRecord,
UserNotesRecord,
UserProfileRecord,
)
_UserManager = models.Manager.from_queryset(UserQuerySet)
class User(AbstractBaseUser, PermissionsMixin):
project/products/models.py中的第6行是另一个django导入from django.utils.text import slugify
:
from decimal import Decimal
from django.contrib.sites.managers import CurrentSiteManager
from django.contrib.sites.models import Site
from django.db import models
from django.utils.text import slugify
from django.utils.translation import gettext_lazy as _
from imagekit.models import ImageSpecField
from imagekit.processors import ResizeToFill
from mptt.models import TreeManyToManyField
...
我的mypy配置如下:
[tool.mypy]
plugins = ["mypy_django_plugin.main", "pydantic.mypy"]
follow_imports = "normal"
ignore_missing_imports = true
disallow_untyped_calls = true
disallow_untyped_defs = true
disallow_incomplete_defs = true
warn_unused_configs = true
warn_redundant_casts = true
warn_unused_ignores = true
warn_return_any = true
warn_unreachable = true
no_implicit_optional = true
no_implicit_reexport = true
check_untyped_defs = true
strict_equality = true
[tool.django-stubs]
django_settings_module = "project.settings"
[tool.pydantic-mypy]
init_forbid_extra = true
init_typed = true
warn_required_dynamic_aliases = true
warn_untyped_fields = true
# Admin files uses some patterns that are not easily typed
[[tool.mypy.overrides]]
module = "project.*.admin"
ignore_errors = true
[[tool.mypy.overrides]]
module = "project.*.tests.*"
ignore_errors = true
[[tool.mypy.overrides]]
module = "project.*.migrations.*"
ignore_errors = "true"
[[tool.mypy.overrides]]
module = "project.*.management.*"
disallow_untyped_defs = false
我试着在谷歌周围搜索,但似乎找不到任何其他人有过这样的经历。有什么明显的我没注意到的吗,或者它看起来像个bug吗?至少在我看来,如果我的/django存根有问题,这将会影响很多。
第一方快速修复
可以将from typing import Optional
添加到使用CurrentSiteManager
的文件中。它将解决这个问题(是的,# noqa: F401
是你的朋友)。
一次性修复了package作为一个快速的解决方案,您可以修改django-stubs/contrib/sites/managers.pyi
,使其具有以下内容:
from typing import Optional, TypeVar
from django.db import models
_T = TypeVar('_T', bound=models.Model)
class CurrentSiteManager(models.Manager[_T]):
def __init__(self, field_name: Optional[str] = ...) -> None: ...
问题根它是不是一个真正的解决方案,是mypy_django_plugin
的一个bug。我正在寻找解决办法。问题是helpers.copy_method_to_another_class
(以及transformers.models.AddManagers.create_new_model_parametrized_manager
)使用了模型类定义的上下文。我不明白现在如何获得和传递另一个上下文正确没有对称的问题,和合并绝对不是一个选择。我将在成功后更新此内容,并向维护者提供PR。如果你把问题提交给django-stubs
(并附上这个问题的链接),这样我就不用那么多解释了(或者如果我失败了,其他人可以帮助我)。
修复#1
这里可以添加original_module_name=base_manager_info.module_name
call参数。它将允许解析从第一个MRO父节点继承的所有内容。然而,对于较长的继承链,这种方法似乎不适用。我的错,我们实际上在这里只迭代最后一个祖先的方法,所以这似乎是最终的解决方案。
(我很抱歉使用这作为一个更改日志,但一旦开始…)
这个bug已经修复了。