未调用 mypy 插件回调
mypy plugin callback not being called
我正在尝试制作我的第一个 mypy 插件来为此代码添加类型检查
adt.py
from dataclasses import make_dataclass
def adt(datatype, *ctrs: str):
basecls = type(datatype, (), {})
klass = lambda x: x.split()[0]
fields = lambda x: x.split()[1:]
clss = (make_dataclass(klass(cls),
bases=(basecls,),
fields=fields(cls))
for cls in ctrs)
return (basecls, *clss)
Maybe, Just, None_ = adt("Maybe", "Just x", "None")
j = Just(1)
def foo(m: Maybe):
pass
我创建了一个 adt_plugin.py
文件保存到磁盘并配置 mypy.ini
加载它,它正在加载(我可以看到一些打印),但我的插件回调似乎不是被调用,我缺少什么?
我的插件代码什么都不做,现在就失败了
adt_plugin.py
from typing import *
from mypy.plugin import Plugin, DynamicClassDefContext
T = TypeVar('T')
CB = Optional[Callable[[T], None]]
class AdtPlugin(Plugin):
def get_dynamic_class_hook(self, fullname: str) -> 'CB[DynamicClassDefContext]':
print(fullname)
if fullname == "adt.adt":
print("foo")
print(decl_info_hook)
return decl_info_hook
return None
def plugin(version: str):
# ignore version argument if the plugin works with all mypy versions.
return AdtPlugin
def decl_info_hook(ctx : DynamicClassDefContext) -> None:
ctx.api.fail("Not able to calculate MRO for declarative base", ctx.call)
mypy.ini
(在当前文件夹)
[mypy]
plugins = /home/geckos/code/python/adt_plugin.py
当我运行mypy adt.py
我看到:
python mypy --no-incremental adt.py
builtins.object
builtins.object
builtins.object
builtins.object
builtins.object
builtins.object
builtins.object
builtins.object
builtins.object
builtins.object
builtins.object
builtins.object
builtins.object
builtins.object
adt.adt
foo
<function decl_info_hook at 0x7f55cabf9ab0>
adt.Just
builtins.type
adt.py:19: error: Variable "adt.Maybe" is not valid as a type
adt.py:19: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases
Found 1 error in 1 file (checked 1 source file)
所以有foo
,所以调用了AdtPlugin.get_dynamic_class_hook
,它也返回了decl_info_hook
,函数名是正确的,我们可以在打印中看到它,但是这个函数根本没有被调用,我在上面放了一个错误,我也试过 raise Exception("foooo")
在里面但是没有任何反应。
知道如何调试吗?
好的,我遇到了问题,mypy 不会将此 x, y, ..., z = something()
检测为动态 class 创建。该语句需要具有 a = f()
形式,其中分配了单个值,否则它不会调用插件挂钩。
我正在尝试制作我的第一个 mypy 插件来为此代码添加类型检查
adt.py
from dataclasses import make_dataclass
def adt(datatype, *ctrs: str):
basecls = type(datatype, (), {})
klass = lambda x: x.split()[0]
fields = lambda x: x.split()[1:]
clss = (make_dataclass(klass(cls),
bases=(basecls,),
fields=fields(cls))
for cls in ctrs)
return (basecls, *clss)
Maybe, Just, None_ = adt("Maybe", "Just x", "None")
j = Just(1)
def foo(m: Maybe):
pass
我创建了一个 adt_plugin.py
文件保存到磁盘并配置 mypy.ini
加载它,它正在加载(我可以看到一些打印),但我的插件回调似乎不是被调用,我缺少什么?
我的插件代码什么都不做,现在就失败了
adt_plugin.py
from typing import *
from mypy.plugin import Plugin, DynamicClassDefContext
T = TypeVar('T')
CB = Optional[Callable[[T], None]]
class AdtPlugin(Plugin):
def get_dynamic_class_hook(self, fullname: str) -> 'CB[DynamicClassDefContext]':
print(fullname)
if fullname == "adt.adt":
print("foo")
print(decl_info_hook)
return decl_info_hook
return None
def plugin(version: str):
# ignore version argument if the plugin works with all mypy versions.
return AdtPlugin
def decl_info_hook(ctx : DynamicClassDefContext) -> None:
ctx.api.fail("Not able to calculate MRO for declarative base", ctx.call)
mypy.ini
(在当前文件夹)
[mypy]
plugins = /home/geckos/code/python/adt_plugin.py
当我运行mypy adt.py
我看到:
python mypy --no-incremental adt.py
builtins.object
builtins.object
builtins.object
builtins.object
builtins.object
builtins.object
builtins.object
builtins.object
builtins.object
builtins.object
builtins.object
builtins.object
builtins.object
builtins.object
adt.adt
foo
<function decl_info_hook at 0x7f55cabf9ab0>
adt.Just
builtins.type
adt.py:19: error: Variable "adt.Maybe" is not valid as a type
adt.py:19: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases
Found 1 error in 1 file (checked 1 source file)
所以有foo
,所以调用了AdtPlugin.get_dynamic_class_hook
,它也返回了decl_info_hook
,函数名是正确的,我们可以在打印中看到它,但是这个函数根本没有被调用,我在上面放了一个错误,我也试过 raise Exception("foooo")
在里面但是没有任何反应。
知道如何调试吗?
好的,我遇到了问题,mypy 不会将此 x, y, ..., z = something()
检测为动态 class 创建。该语句需要具有 a = f()
形式,其中分配了单个值,否则它不会调用插件挂钩。