示例
给定文件./mylib/minimalistic_repro.py
class Foo:
def __init__(self, param):
self.param = param
class Bar:
def __init__(self, param):
self.param = param
def foobar(par1, par2):
return par1.param + par2.param
及其存根./mylib/minimalistic_repro.pyi
from typing import TypeAlias
FooBar: TypeAlias = Foo | Bar
class Foo:
param: int
def __init__(self, param: int) -> None: ...
class Bar:
param: int
def __init__(self, param: int) -> None: ...
def foobar(par1: FooBar, par2: FooBar) -> int: ...
请注意第三行的类型别名:FooBar: TypeAlias = Foo | Bar
mypy --strict mylib
,flake8 mylib
全部ruff check --select E,F,B,SIM
通过。
但是,运行 stubtest 时:
python -m mypy.stubtest mylib
我收到以下错误:
error: mylib.minimalistic_repro.FooBar is not present at runtime
…
我目前的解决方法是使用允许列表(stubtest --generate-allowlist
)。
问题
● 有没有“更好”的方法来避免这个“错误”?/……
● …我是不是在做一些根本性的错误?……
● …如果不是:这是否值得提出功能请求?
其他方法
● 当然我可以声明
def foobar(par1: Foo | Bar, par2: Foo | Bar)
,
但我的实际任务(为第三方 pypi 包编写类型提示)需要最多 18 种类型的联合。
● 我通过将 FooBar 类型别名定义放在 .py 文件 (tp_aliases.py) 中然后重新导入来运行上述示例stubtest
。对于我实际的 pypi 包类型提示任务(tp_aliases.py 不是 pypi 包的一部分),此方法不起作用。
stubtest
正在抱怨,因为它认为你的FooBar
是一个公共 API 符号,这可能会导致类型检查器/IDE 自动完成做出错误的假设和建议。修复此问题的“正确”方法是将其设为私有;即在名称前面加上下划线:
对于类和函数,您也可以使用
typing.type_check_only
:还有命令行选项
--ignore-missing-stub
可以抑制所有此类错误。