代码为例进行说明

实践环境

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/

Python pluggy框架基础用法总结的更多相关文章

  1. Python Numpy shape 基础用法(转自他人的博客,如涉及到侵权,请联系我)

    Python Numpy shape 基础用法 shape函数是numpy.core.fromnumeric中的函数,它的功能是读取矩阵的长度,比如shape[0]就是读取矩阵第一维度的长度.它的输入 ...

  2. Python学习---Python的框架基础学习

    框架基础 框架实质: 所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端 B/S结构的响应: import socket def handle_requ ...

  3. python内建函数isinstance基础用法

      语法:isinstance(object,type) 作用:来判断一个对象是否是一个已知的类型.  其第一个参数(object)为对象,第二个参数(type)为类型名(int...)或类型名的一个 ...

  4. python bottle框架(WEB开发、运维开发)教程

    教程目录 一:python基础(略,基础还是自己看书学吧) 二:bottle基础 python bottle web框架简介 python bottle 框架环境安装 python bottle 框架 ...

  5. Python云端系统开发入门——框架基础

    Django框架基础 这是我学习北京理工大学嵩天老师的<Python云端系统开发入门>课程的笔记,在此我特别感谢老师的精彩讲解和对我的引导. 1.Django简介与安装 Django是一个 ...

  6. 【Python爬虫】selenium基础用法

    selenium 基础用法 阅读目录 初识selenium 基本使用 查找元素 元素互交操作 执行JavaScript 获取元素信息 等待 前进后退 Cookies 选项卡管理 异常处理 初识sele ...

  7. Python web框架 Tornado(一)基础学习

    概述 Tornado 是 FriendFeed 使用的可扩展的非阻塞式 web 服务器及其相关工具的开源版本.这个 Web 框架看起来有些像web.py 或者 Google 的 webapp,不过为了 ...

  8. 零基础小白必看篇:从0到1构建Python Web框架

    造轮子是最好的一种学习方式,本文尝试从0开始造个Python Web框架的轮子,我称它为ToyWebF. 本文操作环境为:MacOS,文中涉及的命令,请根据自己的系统进行替换. ToyWebF的简单特 ...

  9. Python测试框架pytest入门基础

    Pytest简介 Pytest is a mature full-featured Python testing tool that helps you write better programs.T ...

  10. 爬虫之Scrapy框架介绍及基础用法

    今日内容概要 爬虫框架之Scrapy 利用该框架爬取博客园 并发编程 今日内容详细 爬虫框架Scrapy 1.什么是框架? 框架类似于房子的结构,框架会提前帮你创建好所有的文件和内部环境 你只需要往对 ...

随机推荐

  1. JS / jQuery 刷新页面的方法

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. Django路由控制器urls

    路由, 是一种映射关系,是把客户端请求的url地址和用户请求的应用程序(这里指django里面的视图进行一对一绑定映射的一种关系). 在django中所有的路由最终都被保存到一个变量 urlpatte ...

  3. 自动化测试在 Kubernetes Operator 开发中的应用:以 OpenTelemetry 为例

    背景 最近在给 opentelemetry-operator提交一个标签选择器的功能时,因为当时修改的函数是私有的,无法添加单测函数,所以社区建议我补充一个 e2e test. 因为在当前的版本下,只 ...

  4. LLM 大模型学习必知必会系列(十):基于AgentFabric实现交互式智能体应用,Agent实战

    LLM 大模型学习必知必会系列(十):基于AgentFabric实现交互式智能体应用,Agent实战 0.前言 **Modelscope **是一个交互式智能体应用基于ModelScope-Agent ...

  5. S212-搜索+字典树-212. Word Search II-(Hard)

    一.题目 题目很简单,输入一个字母组成的二维数组,以某一个字母为起点,向.上下左右搜索.练成的字符看是不是在给定的字符串数组中 二.解答 通过深度优先搜索,每一步和数组中的字符串匹配是可以计算出来正确 ...

  6. c/c++复习 2.0 ProMax

    main函数执行前后做了什么 初始化.data数据段,包括静态变量和全局变量 初始化.bss字段,包括int 0; bool false: 指针 NULL 设置栈指针.main函数的参数传递.全局对象 ...

  7. CSP-S2021 游记

    那天是惊蛰 满天花瓣 就像现在 我看清了无池里的那个人 前言 终于是开了 游记 的坑(期盼已久!) 虽然参加过 CSP-J2019 ,CSP-S2020 以及 NOIP2020 ,但是都没有写过游记( ...

  8. pandas基础--层次化索引

    pandas含有是数据分析工作变得更快更简单的高级数据结构和操作工具,是基于numpy构建的. 本章节的代码引入pandas约定为:import pandas as pd,另外import numpy ...

  9. kettle从入门到精通 第六十四课 ETL之kettle kettle中执行SQL脚本步骤,使用需当心

    1.群里有不定时会有同学反馈执行SQL脚本步骤使用有问题,那么咱们今天一起来学习下该步骤.trans中的执行SQL脚本有两方面功能,使用时需小心,不然很容易踩坑. 官方定义: 翻译: 您可以使用此步骤 ...

  10. 夜莺官方文档优化第一弹:手把手教你部署和架构讲解,消灭所有部署失败的 case!干!

    前置说明 各种环境的选型建议 Docker compose 方式:仅仅用于简单测试,不推荐在生产环境使用 Docker compose,升级起来挺麻烦的,除非你对 Docker compose 真的很 ...