11"""
22事件管理器,用于管理事件与事件监听器
33"""
4- import traceback
5- from typing import Any , TypeVar
6-
4+ import inspect
75from collections .abc import Callable
86from dataclasses import dataclass , field
7+ from typing import Any , TypeVar
98
109from Lib .core .ThreadPool import async_task
1110from Lib .core import ConfigManager
1211from Lib .utils import Logger
13- import inspect
12+ from Lib . common import save_exc_dump
1413
1514logger = Logger .get_logger ()
1615
@@ -26,6 +25,7 @@ class Hook(_Event):
2625 """
2726 钩子事件,用于在事件处理过程中跳过某些监听器
2827 """
28+
2929 def __init__ (self , event , listener ):
3030 self .event = event
3131 self .listener = listener
@@ -36,17 +36,21 @@ def call(self):
3636 """
3737 if self .__class__ in event_listeners :
3838 for listener in sorted (event_listeners [self .__class__ ], key = lambda i : i .priority , reverse = True ):
39- if not ConfigManager .GlobalConfig ().debug .enable :
40- try :
41- res = listener .func (self , ** listener .kwargs )
42- except Exception as e :
43- logger .error (f"Error occurred in listener: { repr (e )} \n { traceback .format_exc ()} " )
44- continue
45- else :
39+ try :
4640 res = listener .func (self , ** listener .kwargs )
41+ except Exception as e :
42+ if ConfigManager .GlobalConfig ().debug .save_dump :
43+ dump_path = save_exc_dump (f"监听器中发生错误" )
44+ else :
45+ dump_path = None
46+ logger .error (f"监听器中发生错误: { repr (e )} "
47+ f"{ f"\n 已保存异常到 { dump_path } " if dump_path else "" } " ,
48+ exc_info = True )
49+ continue
4750 if res is True :
4851 return True
4952 return False
53+ return None
5054
5155
5256T = TypeVar ('T' , bound = '_Event' )
@@ -64,7 +68,7 @@ class EventListener:
6468
6569 def __post_init__ (self ):
6670 # 确保监听器函数至少有一个参数
67- assert len (inspect .signature (self .func ).parameters ) >= 1 , "The listener takes at least 1 parameter "
71+ assert len (inspect .signature (self .func ).parameters ) >= 1 , "监听器至少接受 1 个参数 "
6872
6973
7074# 定义监听器的类型和存储
@@ -81,7 +85,8 @@ def event_listener(event_class: type[T], priority: int = 0, **kwargs):
8185 priority: 优先级,默认为0
8286 **kwargs: 附加参数
8387 """
84- assert issubclass (event_class , _Event ), "Event class must be a subclass of Event"
88+ if not issubclass (event_class , _Event ):
89+ raise TypeError ("event_class 类必须是 _Event 的子类" )
8590
8691 def wrapper (func : Callable [[T , ...], Any ]):
8792 # 注册事件监听器
@@ -92,6 +97,40 @@ def wrapper(func: Callable[[T, ...], Any]):
9297 return wrapper
9398
9499
100+ def unregister_listener (event_class : type [T ], func : Callable [[T , ...], Any ]):
101+ """
102+ 用于取消注册监听器
103+ 注意,会删除所有与给定函数匹配的监听器。
104+
105+ Args:
106+ event_class: 事件类型
107+ func: 监听器函数
108+ """
109+ if not issubclass (event_class , _Event ):
110+ raise TypeError ("event_class 类必须是 _Event 的子类" )
111+
112+ listeners_list = event_listeners .get (event_class )
113+
114+ if not listeners_list :
115+ raise ValueError (f"事件类型 { event_class .__name__ } 没有已注册的监听器。" )
116+
117+ # 查找所有与给定函数匹配的监听器对象
118+ listeners_to_remove = [listener for listener in listeners_list if listener .func == func ]
119+
120+ if not listeners_to_remove :
121+ # 如果没有找到匹配的函数
122+ raise ValueError (f"未找到函数 { func .__name__ } 对应的监听器,无法为事件 { event_class .__name__ } 注销。" )
123+
124+ # 移除所有找到的监听器
125+ removed_count = 0
126+ for listener_obj in listeners_to_remove :
127+ listeners_list .remove (listener_obj )
128+ removed_count += 1
129+
130+ if not listeners_list :
131+ del event_listeners [event_class ]
132+
133+
95134class Event (_Event ):
96135 """
97136 基事件类,所有自定义事件均继承自此类,继承自此类以创建自定义事件
@@ -108,16 +147,19 @@ def call(self):
108147 res_list = []
109148 for listener in sorted (event_listeners [self .__class__ ], key = lambda i : i .priority , reverse = True ):
110149 if self ._call_hook (listener ):
111- logger .debug (f"Skipped listener : { listener .func .__name__ } " )
150+ logger .debug (f"由 Hook 跳过监听器 : { listener .func .__name__ } " )
112151 continue
113- if not ConfigManager .GlobalConfig ().debug .enable :
114- try :
115- res = listener .func (self , ** listener .kwargs )
116- except Exception as e :
117- logger .error (f"Error occurred in listener: { repr (e )} \n { traceback .format_exc ()} " )
118- continue
119- else :
152+ try :
120153 res = listener .func (self , ** listener .kwargs )
154+ except Exception as e :
155+ if ConfigManager .GlobalConfig ().debug .save_dump :
156+ dump_path = save_exc_dump (f"监听器中发生错误" )
157+ else :
158+ dump_path = None
159+ logger .error (f"监听器中发生错误: { repr (e )} "
160+ f"{ f"\n 已保存异常到 { dump_path } " if dump_path else "" } " ,
161+ exc_info = True )
162+ continue
121163 res_list .append (res )
122164
123165 @async_task
0 commit comments