Python pluggy框架基础用法总结
程序员文章站
2022-03-07 08:46:47
代码为例进行说明 实践环境 Python 3.6.5 pluggy 0.13.0 例1 注册类函数为插件函数 #!/usr/bin/env python # -*- coding:utf-8 -*- import pluggy hookspec = pluggy.HookspecMarker("my ......
代码为例进行说明
实践环境
python 3.6.5
pluggy 0.13.0
例1 注册类函数为插件函数
#!/usr/bin/env python # -*- coding:utf-8 -*- import pluggy hookspec = pluggy.hookspecmarker("myproject") # hook 标签 用于标记hook hookimpl = pluggy.hookimplmarker("myproject") # hook 实现标签 用于标记hook的一个或多个实现 class myspec(object): """hook 集合""" @hookspec def myhook(self, arg1, arg2): pass @hookspec def my_hook_func1(self, arg1, arg2): pass @hookspec def my_hook_func2(self, arg1, arg2): pass # 插件类 class plugin_1(object): """hook实现类1""" @hookimpl def myhook(self, arg1, arg2): print("plugin_1.myhook called") return arg1 + arg2 @hookimpl def my_hook_func2(self, arg1, arg2): print("plugin_1.my_hook_func2 called, args:", arg1, arg2) def my_hook_func3(self, arg1, arg2): print("plugin_1.my_hook_func3 called, args:", arg1, arg2) class plugin_2(object): """hook实现类2""" @hookimpl def myhook(self, arg1, arg2): print("plugin_2.myhook called") return arg1 - arg2 @hookimpl def my_hook_func2(self, arg1, arg2): print("plugin_2.my_hook_func2, args:", arg1, arg2) # 初始化 pluginmanager pm = pluggy.pluginmanager("myproject") # 登记hook集合(hook函数声明) pm.add_hookspecs(myspec) # 注册插件(hook函数实现) pm.register(plugin_1()) pm.register(plugin_2()) # 调用自定义hook results = pm.hook.myhook(arg1=1, arg2=2) # 调用两个插件类中的同名hook函数 # 后注册的插件中的函数会先被调用 print(results) # 输出 [-1, 3] results = pm.hook.my_hook_func1(arg1="name", arg2="shouke") print(results) pm.hook.my_hook_func2(arg1="addr", arg2="sz")
运行结果
plugin_2.myhook called plugin_1.myhook called [-1, 3] [] plugin_2.my_hook_func2, args: addr sz plugin_1.my_hook_func2 called, args: addr sz
例2 注册模块函数为插件函数
myhookspec.py
, myhookimpl.py
, other.py
, example.py
位于同一包目录下
myhookspec.py
import pluggy hookspec = pluggy.hookspecmarker("myproject") # hook 标签 用于标记hook hookimpl = pluggy.hookimplmarker("myproject") # hook 实现标签 用于标记hook的一个或多个实现 @hookspec def global_hook_func1(arg1, arg2): pass
myhookimpl.py
import pluggy from myhookspec import hookimpl @hookimpl def global_hook_func1(arg1, arg2): print("global_hook_func1 in myhookimpl.py, args:", arg1, arg2) return "myhookimpl.py"
other.py
from myhookspec import hookimpl @hookimpl def global_hook_func1(arg1, arg2): print("global_hook_func1 in other.py, args:", arg1, arg2) return "other.py"
example.py
#!/usr/bin/env python # -*- coding:utf-8 -*- import sys import pluggy import myhookspec import myhookimpl import other # 初始化 pluginmanager pm = pluggy.pluginmanager("myproject") # 登记hook集合 pm.add_hookspecs(myhookspec) # 登记hook的实现 pm.register(myhookimpl) # 插件也可以是模块 pm.register(other) print(pm.hook.global_hook_func1(arg1="name", arg2="shouke"))
example.py运行结果如下
global_hook_func1 in other.py, args: name shouke global_hook_func1 in myhookimpl.py, args: name shouke ['other.py', 'myhookimpl.py']
例3:自定义插件类实现hook函数免@hookimpl装饰器
myhookspec.py
import pluggy hookspec = pluggy.hookspecmarker("myproject") @hookspec def mytest_hook_func1(arg1, arg2): pass
other.py
def mytest_hook_func1(arg1, arg2): print("global_hook_func1 in other.py, args:", arg1, arg2) return "other.py"
example.py
#!/usr/bin/env python # -*- coding:utf-8 -*- import inspect import pluggy import myhookspec import other class pytestpluginmanager(pluggy.pluginmanager): """ 插件类,实现不用@hookimplmarkerinstance装饰的函数也可以当做函数体 """ def parse_hookimpl_opts(self, plugin, name): # 规定免@hookimpl装饰的 hooks 函数总是以 mytest_打头,这样以避免访问非可读属性 if not name.startswith("mytest_"): return method = getattr(plugin, name) opts = super().parse_hookimpl_opts(plugin, name) # 考虑hook只能为函数(consider only actual functions for hooks) if not inspect.isroutine(method): return # 收集未被标记的,以mytest打头的hook函数,(collect unmarked hooks as long as they have the `pytest_' prefix) if opts is none and name.startswith("mytest_"): opts = {} return opts # 初始化 pluginmanager pm = pytestpluginmanager("myproject") # 登记hook集合 pm.add_hookspecs(myhookspec) # 登记hook的实现 pm.register(other) pm.hook.mytest_hook_func1(arg1="addr", arg2="sz")