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/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM