You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
DjangoBlog/djangoblog/plugin_manage/hooks.py

89 lines
4.0 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 钩子系统核心模块
# 该模块实现了一个轻量级的钩子Hook机制支持注册回调函数、执行动作钩子Action Hook和过滤钩子Filter Hook
# 主要功能包括:管理钩子与回调函数的映射关系、按顺序执行钩子回调、处理回调执行过程中的异常并记录日志
# 适用于需要模块解耦、灵活扩展的场景,通过钩子机制实现不同组件间的间接交互
import logging
# 初始化日志记录器,用于记录钩子注册、执行过程中的调试信息和错误信息
logger = logging.getLogger(__name__)
# 私有字典,用于存储钩子名称与回调函数列表的映射关系
# 键为钩子名称(字符串),值为注册到该钩子的回调函数列表
_hooks = {}
def register(hook_name: str, callback: callable):
"""
注册一个回调函数到指定的钩子上。
同一钩子可以注册多个回调函数,执行时将按注册顺序依次调用。
参数:
hook_name: 钩子名称,用于标识一组相关的回调函数
callback: 可调用对象(函数、方法等),将在钩子触发时执行
"""
# 如果钩子名称不在映射表中,初始化一个空列表用于存储回调
if hook_name not in _hooks:
_hooks[hook_name] = []
# 将回调函数添加到对应钩子的列表中
_hooks[hook_name].append(callback)
# 记录调试日志,说明已成功注册回调
logger.debug(f"Registered hook '{hook_name}' with callback '{callback.__name__}'")
def run_action(hook_name: str, *args, **kwargs):
"""
执行指定名称的动作钩子Action Hook
动作钩子用于触发一系列操作,不关注返回值,按注册顺序依次执行所有回调函数。
参数:
hook_name: 要执行的钩子名称
*args: 传递给回调函数的位置参数
**kwargs: 传递给回调函数的关键字参数
"""
# 检查该钩子是否有注册的回调函数
if hook_name in _hooks:
logger.debug(f"Running action hook '{hook_name}'")
# 遍历执行该钩子下的所有回调函数
for callback in _hooks[hook_name]:
try:
# 调用回调函数并传递参数
callback(*args, **kwargs)
except Exception as e:
# 捕获并记录回调执行过程中的异常,不中断后续回调
logger.error(
f"Error running action hook '{hook_name}' callback '{callback.__name__}': {e}",
exc_info=True # 记录完整的异常堆栈信息,便于调试
)
def apply_filters(hook_name: str, value, *args, **kwargs):
"""
执行指定名称的过滤钩子Filter Hook
过滤钩子用于对某个值进行一系列处理,将值依次传递给所有回调函数,最终返回处理后的结果。
参数:
hook_name: 要执行的钩子名称
value: 初始值,将被回调函数依次处理
*args: 传递给回调函数的额外位置参数
**kwargs: 传递给回调函数的额外关键字参数
返回:
经过所有回调函数处理后的最终值
"""
# 检查该钩子是否有注册的回调函数
if hook_name in _hooks:
logger.debug(f"Applying filter hook '{hook_name}'")
# 遍历执行该钩子下的所有回调函数,依次处理值
for callback in _hooks[hook_name]:
try:
# 调用回调函数,传入当前值和其他参数,并用返回值更新当前值
value = callback(value, *args, **kwargs)
except Exception as e:
# 捕获并记录回调执行过程中的异常,不中断后续回调
logger.error(
f"Error applying filter hook '{hook_name}' callback '{callback.__name__}': {e}",
exc_info=True # 记录完整的异常堆栈信息,便于调试
)
# 返回最终处理后的值
return value