• Python pluggy框架基础用法总结


    代码为例进行说明

    实践环境

    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.pymyhookimpl.pyother.pyexample.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")
    

    参考连接

    https://pypi.org/project/pluggy/

    作者:授客
    公众号:授客的知识库
    QQ:1033553122
    全国软件测试QQ交流群:7156436

    Git地址:https://gitee.com/ishouke
    友情提示:限于时间仓促,文中可能存在错误,欢迎指正、评论!
    作者五行缺钱,如果觉得文章对您有帮助,请扫描下边的二维码打赏作者,金额随意,您的支持将是我继续创作的源动力,打赏后如有任何疑问,请联系我!!!
                微信打赏                       支付宝打赏                        授课的知识库               全国软件测试交流QQ群  
                          

  • 相关阅读:
    键盘记录器,可截获到 QQ 的password
    《python源代码剖析》笔记 pythonm内存管理机制
    Unity 捕获IronPython脚本错误
    POJ 3020 Antenna Placement 最大匹配
    XCL-Charts画线图(Line Chart)
    android设置背景色为透明
    设计时属性文件
    Windows Mobile基础
    Wince 的CAB安装包
    惠普的 ipaq112 恢复出厂设置
  • 原文地址:https://www.cnblogs.com/shouke/p/14940707.html
Copyright © 2020-2023  润新知