我想将类型注释添加到我的pluggy hook规范中,以便可以对hook实现进行类型检查。使用pluggy documentation中的简化示例:
import pluggy # type: ignore
hookspec = pluggy.HookspecMarker("myproject")
hookimpl = pluggy.HookimplMarker("myproject")
class MySpec(object):
"""A hook specification namespace."""
@hookspec
def myhook(self, arg1, arg2):
"""My special little hook that you can customize."""
class Plugin_1(object):
"""A hook implementation namespace."""
@hookimpl
def myhook(self, arg1, arg2):
print("inside Plugin_1.myhook()")
return arg1 + arg2 + "a" # intentional error
# create a manager and add the spec
pm = pluggy.PluginManager("myproject")
pm.add_hookspecs(MySpec)
# register plugins
pm.register(Plugin_1())
# call our `myhook` hook
# intentional incompatible type for parameter arg2
results = pm.hook.myhook(arg1=1, arg2="1")
print(results)
我相信正确有效的诠释应该是:
def myhook(self, arg1: int, arg2: int) -> int: ...
我试着把这个注释添加到hookspec中。如我所料,这不起作用。我相信这是因为pluggy实现的间接寻址是动态的。必须运行代码,以便PluginManager
的add_hookspecs()
方法可以定义可用的钩子。你知道吗
我看到pm.hook
是pluggy.hooks._HookRelay
类型,pm.hook.myhook
是pluggy.hooks._HookCaller
的一个实例,它有一个__call__()
方法。你知道吗
我尝试使用stubgen
为pluggy创建一组.pyi
文件,然后以两种不同的方式将注释添加到pluggy.hooks._HookCaller
:
class _HookCaller:
def __init__(self, trace: Any) -> None: ...
def myhook(self, arg1: int, arg2: int) -> int: ...
def __call__(self, arg1: int, arg2: int) -> int: ...
当我执行MYPYPATH=./stubs mypy --verboes example.py
时,我可以看到hooks.pyi
正在被解析,但是没有检测到参数类型不匹配。即使我从import pluggy
中删除# type: ignore
注释,这种行为也是一致的。你知道吗
问题:
.pyi
钩子的类型注释定义为外部.pyi
文件?你知道吗.pyi
文件将包含什么?我应该将其存储在哪里,以便在运行类型检查时mypy
将其拾取?你知道吗
第一个问题是
@hookspec
删除了myhook
方法的类型提示:这种解决方法否定了对外部
.pyi
文件的要求。只需使用现有的钩子规范来定义类型提示。这解决了Q1和Q2:您不需要.pyi
文件。只需使用typing.cast()
给mypy一个提示,它无法从静态分析中学习:这可以通过添加注释来检查:
通过mypy运行以下命令:
现在
mypy
捕获钩子调用者和钩子实现(Q3)的类型问题!你知道吗完整代码:
相关问题 更多 >
编程相关推荐