示例
给定文件
./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)
,● 我通过将 FooBar 类型别名定义放入 .py 文件 (tp_aliases.py) 中,然后重新导入,使上述示例与
stubtest
一起运行。这种方法在我实际的 pypi 包类型提示任务中不起作用(tp_aliases.py 不是 pypi 包的一部分)。
stubtest
正在抱怨,因为它认为您的 FooBar
是公共 API 符号,这可能会导致类型检查器/IDE 自动完成功能做出错误的假设和建议。
修复它的“正确”方法是将其设为私有;也就是说,在名称前面添加下划线:
_FooBar: TypeAlias = Foo | Bar
def foobar(par1: _FooBar, par2: _FooBar) -> int: ...
typing.type_check_only
:
# type_check_only is not available at runtime and can only be used in stubs
from typing import type_check_only
@type_check_only
def this_function_is_not_available_at_runtime(): ...
@type_check_only
class AndSoDoesThisClass: ...