Python装饰器实现Hook类
背景
最近有个新的需求是使用Redmine进行一些提交前后的处理,备忘下一些思路
实现思路
为了统一代码的路径以及调用方式,封装了一个Hook类,按理来说是可以对所有类似的代码使用的,这里使用了Python装饰器,统一对同一个命名类的进行处理,相当于定义了函数的路由
核心代码见下:
Hook.py
from functools import wraps
class Hook():
hook_registry = {}
STOP_EXECUTION = "STOP" # 将停止标识封装为类属性
@classmethod
def registry_hook(cls, hook_name, priority=0):
def hook_decorator(func):
@wraps(func)
def wrapped_function(*args, **kwargs):
print(f"Hook '{hook_name}' is triggered for {func.__name__}")
return func(*args, **kwargs)
cls.hook_registry.setdefault(hook_name, []).append((priority, wrapped_function))
cls.hook_registry[hook_name].sort(key=lambda x: x[0], reverse=True) # 按优先级降序排序
return wrapped_function
return hook_decorator
@classmethod
def trigger_hooks(cls, hook_name, *args, **kwargs):
if hook_name in cls.hook_registry:
for priority, func in cls.hook_registry[hook_name]:
result = func(*args, **kwargs)
if result == cls.STOP_EXECUTION: # 使用类属性停止执行链
print(f"Execution chain stopped at hook '{hook_name}' by {func.__name__}")
break
用法示例:
import Hook
hook = Hook()
@hook.registry_hook("after_commit", priority=2)
def test(params):
print(f"test function called with params: {params}")
return svn_hook.STOP_EXECUTION
@hook.registry_hook("after_commit", priority=1)
def test2(params):
print(f"test2 function called with params: {params}")
@hook.registry_hook("after_commit", priority=3)
def test3(params):
print(f"test3 function called with params: {params}")
# 模拟触发钩子
svn_hook.trigger_hooks("after_commit", "stop")
输出
Hook 'after_commit' is triggered for test3
test3 function called with params: stop
Hook 'after_commit' is triggered for test
test function called with params: stop
Execution chain stopped at hook 'after_commit' by test

浙公网安备 33010602011771号