mypy 在引用带有包名称前缀的别名时出现错误:“名称未定义”

问题描述 投票:0回答:1

我正在尝试使用存根文件为 Python 包中包装的本机库提供更好的类型注释。

考虑以下玩具示例: 封装结构:

. geometry
|- typing
|  `- __init__.pyi
|- geometry.cpython-39-x86_64-linux-gnu.so
|- __init__.py
|- __init__.pyi
`- py.typed
 

存根文件具有以下内容:

geometry/typing__init__.pyi

import geometry
import typing

Point = tuple[int, int]
Primitive = geometry.Circle | geometry.Rect
Primitives = typing.Sequence[Primitive]

geometry/__init__.pyi

import geometry.typing


class Circle:
    center: geometry.typing.Point
    radius: int

    def __init__(self, center: geometry.typing.Point, radius: int): ...


class Rect:
    top_left: geometry.typing.Point
    width: int
    height: int

    def __init__(self, top_left: geometry.typing.Point, width: int, height: int): ...


def calculate_union_area(primitives: geometry.typing.Primitives) -> float: ... 

geometry/__init__.py

from .geometry import Circle, Rect, calculate_union_area

通过:

mypy.stubtest
运行
python -m mypy.stubtest geometry
给出以下输出:

error: not checking stubs due to mypy build errors:
geometry/__init__.pyi:4: error: Name "geometry.typing.Point" is not defined  [name-defined]
geometry/__init__.pyi:7: error: Name "geometry.typing.Point" is not defined  [name-defined]
geometry/__init__.pyi:10: error: Name "geometry.typing.Point" is not defined  [name-defined]
geometry/__init__.pyi:14: error: Name "geometry.typing.Point" is not defined  [name-defined]
geometry/__init__.pyi:16: error: Name "geometry.typing.Primitives" is not defined  [name-defined]

如果我尝试在外部文件中使用

geometry.typing
中的类型:

import geometry
import geometry.typing

from geometry.typing import Point


def foo(pt: Point) -> None:
    print(pt)

foo((1, 2))
foo(('bar', 31))

def baz(primitives: geometry.typing.Primitives) -> None:
    print(len(primitives))

baz([geometry.Circle([0, 0], 3)), geometry.Rect((1, 2), width=10, height=10)])

来自 pylance 和 Pyright 语言服务器的类型提示和自动完成功能按预期工作。

在上面的示例中调用 mypy 作为

python -m mypy --strict --follow_imports_for_stubs main.py
再次给出有关使用
geometry.typing.Primitives
注释的错误:
Name "geometry.typing.Primitives" is not defined  [name-defined]
,但解析了
Point
名称,甚至其类型抱怨
foo(('bar', 31))
中的错误使用。

版本:

  • 我的py版本:0.991

  • python版本:3.10.9

所以,问题如下:

通过全名使用别名类型时如何让 mypy 满意?

注意:将

geometry.typing.__init__.pyi
更改为
geometry.typing.__init__.py

import typing

if typing.TYPE_CHECKING:
    # same content goes here

什么也没做 - 错误仍然存在。

注意:使用

from geometry.typing import Name
形式并非如此,因为在实际示例中,模块之间可能存在名称冲突。

注意:使用

from geometry.typing import Name as geometry_typing_Name
形式也不是这样,因为它看起来很难看,除此之外,它是解决可能的 mypy 检查器问题的拐杖。

python type-hinting mypy
1个回答
0
投票

我有一个类似的问题,我在这里的讨论中解决了https://github.com/konradhalas/dacite/issues/133

在你的情况下,它会涉及到添加 init.pyi 文件(可能在这个文件中:geometry/typing__init__.pyi)类似的想法

__all__ = [
"Point",
"Primitives"] 

另请参阅此处有关 __all__ 的讨论:Python 中 __all__ 是什么意思?

© www.soinside.com 2019 - 2024. All rights reserved.