Mypy抱怨名称“可选”没有使用可选的未定义

发布于 2025-02-06 12:57:29 字数 4409 浏览 2 评论 0 原文

我最近开始使用Mypy,并遇到了一些我一生中无法找到的奇怪问题。

我使用MyPy 0.950,Django-stubs 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/供应商/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> project> project> project/users/models.py 的第6行django import 来自django.contrib.contenttypes.models导入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):

and project/product/products/models.py中的第6行是另一个django import from django.utils.texts.texts.text代码>:

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

我尝试过搜索搜索,但似乎找不到其他经历过的人。我错过了什么明显的,还是看起来像一个错误?至少在我看来,如果Mypy/Django Stubs出现问题,这将影响很大。

I've recently started using mypy, and have run into some weird problems that i cannot for the life of me seem to figure out.

I'm using mypy 0.950, django-stubs 1.11.0, django 4.0.5 and python 3.10.2.

Running mypy through the command line returns this:

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")

However, line 6 in project/suppliers/models.py is completely empty:

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):
    ...

Line 6 in project/users/models.py is a django import 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):

And line 6 in project/products/models.py is yet another django import 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
...

My mypy config is as follows:

[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

I've tried googling around, but can not seem to find anyone else that has experienced this. Anything obvious that I've missed, or does it look like a bug? Seems to me at least that this would affect quite a lot if it was something wrong with mypy/django stubs.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

删除→记忆 2025-02-13 12:57:29

快速第一方修复程序

您可以将从键入 currentsitemanager 的文件中添加。它将解决此问题(是,#noqa:f401 是您的朋友)。

一项快速解决方法的一次性修复程序

,您可以修改 django-stubs/conter/conter/stites/stite.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 中的错误。我现在正在寻找解决方案。问题是 helpers.copy_method_to_another_class (因此 transformers.models.models.models.create_new_model_model_parametrized_manager )是使用模型类定义的上下文。我现在不明白如何在没有对称问题的情况下正确地和通过另一个上下文,并且合并绝对不是一个选择。我将以成功的方式更新此信息,并为维护者提出公关。如果您将问题提交给 django-stubs (并将链接附加到此问题),这样我就可以解释较少(或者如果我失败了,其他人可以帮助)。

更好的修复#1

ointer_module_name = base_manager_info.module_name 调用参数。 它将允许从第一个MRO父母那里解决所有继承的一切。但是,似乎这应该失败,因为我的不好,我们实际上仅在这里仅迭代最后一个祖先的方法,因此这似乎是最终解决方案。

(很抱歉将其用作变更元素,但是一旦开始...)

此错误是在这是我的pr

Fast 1st-party fix

You can add from typing import Optional to files that use CurrentSiteManager. It will resolve this problem (yes, # noqa: F401 is your friend).

One-time fix for package

As a quick workaround, you can modify django-stubs/contrib/sites/managers.pyi to have the following content:

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: ...

Problem root

It is not a real solution and is a bug in mypy_django_plugin. I'm looking for a solution now. The problem is that helpers.copy_method_to_another_class (and consequently transformers.models.AddManagers.create_new_model_parametrized_manager) is using context of model class definition. I don't understand now how to get and pass another context properly without symmetrical issue, and merging is definitely not an option. I'll update this on success and raise a PR to maintainer. It would be great if you file an issue to django-stubs (and attach link to this question) so that I have less to explain (or somebody else could help if I fail).

Better fix #1

here we can add original_module_name=base_manager_info.module_name call argument. It will allow resolving everything inherited from first MRO parent. However, it seems like this should fail for longer inheritance chains. My bad, we're actually iterating here over methods of last ancestor only, so this seems to be the final solution.

(I'm sorry for using this as a changelog, but once started...)

This bug was fixed in this my PR.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文