1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
|
注册插件 (register): 传递实现插件的实体类对象
判断是否传递插件名字,如果没传,就获取对象的name属性,如果还没有就直接用 id() 生产一个随机字符串做当前对象在插件中的名字
判断名字是否存在,或者是否已被注册: self._name2plugin 和 self._plugin2hookcaller,前者是用 plugin_name 做 key,后者是用 plugin object 做 key,判断是否已经注册过重复的 plugin
self._name2plugin[plugin_name(插件名字)] = plugin(传递的实体类对象)
self._plugin2hookcallers[plugin(传递的实体类对象)] = hookcallers = [],其实就是初始化一下 self._plugin2hookcallers[plugin],因为列表的引用传递,所有直接修改 hookcallers 也可以作用在 self 中
遍历实体类对象的方法列表,判断是否被 impl 装饰:
先判断参数列表是否为空: 如果不为空,进行设置默认值 (其实正常是不会出现没有值的情况),然后从实体类对象中获取到该方法的对象
判断 self.hook 中是否以及注册了当前插件 (就是 add_hookspecs 注册的 spec 中是否有当前方法)
hook.has_spec() 判断注册 spec 的 spec 属性不为空
hook._maybe_apply_history(hookimpl)
a.判断是否有_call_history 这个属性
hook._add_hookimpl(hookimpl):
a.判断是否为 hookwrapper 为 True,添加到不同的 wrappers 中
b.判断是否有 trylast tryfirst 属性,将 hookimpl 存放到对应位置
c.将 hook 添加到 hookcallers 中
遍历结束后,返回 plugin_name(第一步产生)
运行插件 pm.hook.myhook(arg1=1, arg2=2):本质就是调用对象的call方法
self._inner_hookexec(hook(hook 对象), methods(插件), kwargs(参数))
1 2 3 4 5 6 |
|
1. 先将 hook_impls 变成一个可迭代对象 (reversed(hook_impls))
2. 先把顺序参数的参数列表,拿到 (列表推导式)
3. 判断需不需要将其他插件执行的结果传递进去
- 需要
- 先从 hook_impl 中拿出对应的方法并且传递参数,执行关键字 yield 前面部分
- 然后 next()
- 最后将这个方法添加到 teardowns 列表中去- 不需要
- 先从 hook_impl 中拿出对于的方法并且传递参数
- 判断执行后的返回值是不是为空,不为空则添加到 results 列表中
- 最后判断是否有 firstresult 属性,如果有直接结束循环
4. 最后执行 (finally 中代码)
- 如果 firstresult 为 true,那么直接返回第一个插件返回的结果即可
- 执行 teardowns 列表中的需要最后执行的插件
- 通过迭代器的 send 方法,将上几个插件的结果传递进去
5. 返回 result 对象 :会判断是否有报错 如果没有直接返回结果列表,如果有报错会抛出异常
?现在我也找了很多测试的朋友,做了一个分享技术的交流群,共享了很多我们收集的技术文档和视频教程。
如果你不想再体验自学时找不到资源,没人解答问题,坚持几天便放弃的感受
可以加入我们一起交流。而且还有很多在自动化,性能,安全,测试开发等等方面有一定建树的技术大牛
分享他们的经验,还会分享很多直播讲座和技术沙龙
可以免费学习!划重点!开源的!!!
qq群号:485187702【暗号:csdn11】
最后感谢每一个认真阅读我文章的人,看着粉丝一路的上涨和关注,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走!?希望能帮助到你!【100%无套路免费领取】