本文介绍Matche如何实例化、handler如何注册到Matcher,顺便介绍Rule和Permission的实例化
注意区分handlers和handler
- handler:被形如@xxx.handle()等装饰的函数,类型是函数
- handlers:特指Matcher.handlers,类型为List[Dependent[Any]],每个元素都是handler转化的Denpendent handler
Matcher的实例化
Matcher通过各种on函数生成,如on、on_metaevent、on_message等
这里以on()为例进行分析
def on( type: str = "", rule: Optional[Union[Rule, T_RuleChecker]] = None, permission: Optional[Union[Permission, T_PermissionChecker]] = None, *, handlers: Optional[List[Union[T_Handler, Dependent]]] = None, temp: bool = False, expire_time: Optional[Union[datetime, timedelta]] = None, priority: int = 1, block: bool = False, state: Optional[T_State] = None, _depth: int = 0, ) -> Type[Matcher]: plugin_chain = _current_plugin_chain.get() # 姑且当作Matcher所在插件,具体分析要到第四章杂项 matcher = Matcher.new( type, Rule() & rule, Permission() | permission, temp=temp, expire_time=expire_time, priority=priority, block=block, handlers=handlers, plugin=plugin_chain[-1] if plugin_chain else None, module=_get_matcher_module(_depth + 1), default_state=state, ) _store_matcher(matcher) # 姑且认为Matcher被存到所在plugin中,具体分析要到第四章杂项 return matcher
显然核心代码是Matcher.new
class Matcher(metaclass=MatcherMeta): @classmethod def new( cls, type_: str = "", rule: Optional[Rule] = None, permission: Optional[Permission] = None, handlers: Optional[List[Union[T_Handler, Dependent[Any]]]] = None, temp: bool = False, priority: int = 1, block: bool = False, *, plugin: Optional["Plugin"] = None, module: Optional[ModuleType] = None, expire_time: Optional[Union[datetime, timedelta]] = None, default_state: Optional[T_State] = None, default_type_updater: Optional[Union[T_TypeUpdater, Dependent[str]]] = None, default_permission_updater: Optional[ Union[T_PermissionUpdater, Dependent[Permission]] ] = None, ) -> Type["Matcher"]: NewMatcher = type( "Matcher", (Matcher,), { "plugin": plugin, "module": module, "plugin_name": plugin and plugin.name, "module_name": module and module.__name__, "type": type_, "rule": rule or Rule(), "permission": permission or Permission(), "handlers": [ handler if isinstance(handler, Dependent) else Dependent[Any].parse( call=handler, allow_types=cls.HANDLER_PARAM_TYPES ) for handler in handlers ] if handlers else [], "temp": temp, "expire_time": ( expire_time and ( expire_time if isinstance(expire_time, datetime) else datetime.now() + expire_time ) ), "priority": priority, "block": block, "_default_state": default_state or {}, "_default_type_updater": ( default_type_updater and ( default_type_updater if isinstance(default_type_updater, Dependent) else Dependent[str].parse( call=default_type_updater, allow_types=cls.HANDLER_PARAM_TYPES, ) ) ), "_default_permission_updater": ( default_permission_updater and ( default_permission_updater if isinstance(default_permission_updater, Dependent) else Dependent[Permission].parse( call=default_permission_updater, allow_types=cls.HANDLER_PARAM_TYPES, ) ) ), }, ) matchers[priority].append(NewMatcher) # 根据优先级将Matcher子类储存 return NewMatcher
Matcher的元类是MatcherMeta,可以说卵用没有,唯一的作用是实现Matcher的自定义打印
type的作用是生成类,例如
class A: def class_name(self): return self.__class__ @staticmethod def number(): return 1 @property def string(self): return "233" def new_class_name(self): return str(self.__class__) + "new" def new_number(): return 2 def new_string(self): return "666" B = type( "B", # 类名 (A,), # 父类 { "class_name": new_class_name, "number": staticmethod(new_number), "string": property(new_string), "show": lambda self: print(self.class_name(), self.number(), self.string) } # 类方法、对象方法、类属性 ) B().show()
实际上与下面写法相同
class B(A): def class_name(self): return str(self.__class__) + "new" @staticmethod def number(): return 2 @property def string(self): return "666" def show(self): print(self.class_name(), self.number(), self.string)
总之随便你怎么折腾都行
可以看出,Matcher.new生成的是Matcher子类,重写了父类的以下类属性
plugin: Optional["Plugin"] = None """Matcher所在插件,通过_current_plugin_chain.get获取,具体代码将在第四章分析""" module: Optional[ModuleType] = None """Matcher所在插件模块,通过_get_matcher_module获取,具体代码将在第四章分析""" plugin_name: Optional[str] = None """Matcher所在插件名,用plugin.name或plugin类作为名称""" module_name: Optional[str] = None """Matcher所在点分割插件模块路径,module.\__name__或module类作为名称""" type: str = "" """ Matcher类型,Matcher的类型决定了事件匹配规则 例如on_metaevent的类型是“meta_event”、on_message的类型是“message”等,可以再nonebot.plugin.on中查看 """ rule: Rule = Rule() """Matcher匹配规则,见后文详细介绍""" permission: Permission = Permission() """Matcher触发权限,见后文详细介绍""" handlers: List[Dependent[Any]] = [] """ Matcher拥有的事件处理函数列表,可以在on函数注册,如on_message(handlers=[handler1,handler2]) 也可以通过Matcher的其它方法注册,见后文 """ priority: int = 1 """Matcher优先级,顾名思义,优先级越高小越先运行,同一优先级的同时运行(详见第三节)""" block: bool = False """Matcher是否阻止事件传播,无论Matcher是否被触发""" temp: bool = False """Matcher是否为临时,无论Matcher是否被触发""" expire_time: Optional[datetime] = None """Matcher过期时间,可以是datetime或timedelta""" _default_state: T_State = {} """ Matcher默认状态,用于存储上下文,例如对话系统可能用到,默认为空字典 你也可以在初始化的时候放一些值进去 """ _default_type_updater: Optional[Dependent[str]] = None """ Matcher类型更新函数,Matcher.pause, Matcher.reject(第三节介绍)时被运行 用于更新Matcher的type。默认会更新为message """ _default_permission_updater: Optional[Dependent[Permission]] = None """ Matcher权限更新函数,在Matcher.pause, Matcher.reject(第三节介绍)时被运行 用于更新会话对象权限。默认会更新为当前事件的触发对象 """
Matcher的HANDLER_PARAM_TYPES有DependParam、BotParam、EventParam、StateParam、ArgParam、MatcherParam、DefaultParam
Handlers的注册
Matcher.append_handler
class Matcher(metaclass=MatcherMeta): ... @classmethod def append_handler( cls, handler: T_Handler, parameterless: Optional[Iterable[Any]] = None ) -> Dependent[Any]: handler_ = Dependent[Any].parse( #将handler转化为Dependent call=handler, parameterless=parameterless, allow_types=cls.HANDLER_PARAM_TYPES, ) cls.handlers.append(handler_) # 添加到Matcher.handlers列表中 return handler_ # 返回值是Dependent handler,不是handler,和后面三种注册方法不同 ... # 例如有多个handler需要注册,可以循环使用append_handler。一般不作为装饰器使用
Matcher.handle
class Matcher(metaclass=MatcherMeta): ... @classmethod def handle( cls, parameterless: Optional[Iterable[Any]] = None ) -> Callable[[T_Handler], T_Handler]: def _decorator(func: T_Handler) -> T_Handler: cls.append_handler(func, parameterless=parameterless) return func return _decorator ... # 和append_handler几乎相同,作为装饰器使用,返回值是handler本身
Matcher.receive
class Matcher(metaclass=MatcherMeta): ... @classmethod def receive( cls, id: str = "", parameterless: Optional[Iterable[Any]] = None ) -> Callable[[T_Handler], T_Handler]: async def _receive(event: Event, matcher: "Matcher") -> Union[None, NoReturn]: matcher.set_target(RECEIVE_KEY.format(id=id)) if matcher.get_target() == RECEIVE_KEY.format(id=id): matcher.set_receive(id, event) return if matcher.get_receive(id, ...) is not ...: return await matcher.reject() ``` 额外添加Depends(_receive)到parameterless,那么有什么用呢? 由于我们现在连parameterless是干什么的都不知道,因此下一节再介绍Depends(_receive) ``` _parameterless = (Depends(_receive), *(parameterless or tuple())) def _decorator(func: T_Handler) -> T_Handler: if cls.handlers and cls.handlers[-1].call is func: ``` 如果Matcher的handlers不为空,且handlers[-1]的func也是当前传入的handler 例如 @xxx.receive() receive要在handle等的上面 @xxx.handle() async def(xxx:bot): pass ``` func_handler = cls.handlers[-1] new_handler = Dependent( call=func_handler.call, params=func_handler.params, parameterless=Dependent.parse_parameterless( # 将参数转化为Param子类 tuple(_parameterless), cls.HANDLER_PARAM_TYPES ) + func_handler.parameterless, ) cls.handlers[-1] = new_handler # 将handlers[-1]的parameterless加上receive的parameterless和Depends(_receive) else: ``` 其他情况,按正常流程注册 @xxx.receive() async def(xxx:bot): pass ``` cls.append_handler(func, parameterless=_parameterless) return func return _decorator ... # 可见Matcher.receive注册的Dependent handler的核心在于parameterless的第一位是Depends(_receive),其它与普通Dependent handler没区别
Matcher.got
class Matcher(metaclass=MatcherMeta): ... @classmethod def got( cls, key: str, prompt: Optional[Union[str, Message, MessageSegment, MessageTemplate]] = None, parameterless: Optional[Iterable[Any]] = None, ) -> Callable[[T_Handler], T_Handler]: async def _key_getter(event: Event, matcher: "Matcher"): matcher.set_target(ARG_KEY.format(key=key)) if matcher.get_target() == ARG_KEY.format(key=key): matcher.set_arg(key, event.get_message()) return if matcher.get_arg(key, ...) is not ...: return await matcher.reject(prompt) _parameterless = (Depends(_key_getter), *(parameterless or tuple())) def _decorator(func: T_Handler) -> T_Handler: if cls.handlers and cls.handlers[-1].call is func: ``` 用法一 @xxx.got() got要在handle等的上面 @xxx.handle() async def(xxx:bot): pass ``` func_handler = cls.handlers[-1] new_handler = Dependent( call=func_handler.call, params=func_handler.params, parameterless=Dependent.parse_parameterless( tuple(_parameterless), cls.HANDLER_PARAM_TYPES ) + func_handler.parameterless, ) cls.handlers[-1] = new_handler else: ``` 用法二 @xxx.got() async def(xxx:bot): pass ``` cls.append_handler(func, parameterless=_parameterless) return func return _decorator # 和Matcher.receive几乎一样,只不过parameterless第一位是Depends(_key_getter),同样下节再介绍
Rule
只介绍Rule的实例化,关于Rule的运行将在下节介绍
class Rule: HANDLER_PARAM_TYPES = [ DependParam, BotParam, EventParam, StateParam, DefaultParam, ] def __init__(self, *checkers: Union[T_RuleChecker, Dependent[bool]]) -> None: ``` T_RuleChecker = _DependentCallable[bool] _DependentCallable = Union[Callable[..., T], Callable[..., Awaitable[T]]] 所以返回值为bool的同步函数、异步函数和对应Dependent都可以作为Rule ``` self.checkers: Set[Dependent[bool]] = { # 把不是Dependent的Rule转化为Dependent Rule checker if isinstance(checker, Dependent) else Dependent[bool].parse( call=checker, allow_types=self.HANDLER_PARAM_TYPES # 相较于Matcher,Rule的参数不支持ArgParam和MatcherParam,因为此时还没有运行到Matcher ) for checker in checkers } def __and__(self, other: Optional[Union["Rule", T_RuleChecker]]) -> "Rule": ``` 支持左 & 运算 Rule() & Rule() Rule() & Union[T_RuleChecker, Dependent[bool]]类型 最终生成一个新的Rule Rule() & None 返回自身,防止意外None值 ``` if other is None: return self elif isinstance(other, Rule): return Rule(*self.checkers, *other.checkers) else: return Rule(*self.checkers, other) def __rand__(self, other: Optional[Union["Rule", T_RuleChecker]]) -> "Rule": ``` 支持右 & 运算 Rule() & Rule() Union[T_RuleChecker, Dependent[bool]]类型 & Rule() 最终生成一个新的Rule None & Rule() 返回自身,防止意外None值 ``` if other is None: return self elif isinstance(other, Rule): return Rule(*other.checkers, *self.checkers) else: return Rule(other, *self.checkers) def __or__(self, other: object) -> NoReturn: ``` 不支持 | 运算 ``` raise RuntimeError("Or operation between rules is not allowed.")
Permission
class Permission: HANDLER_PARAM_TYPES = [ DependParam, BotParam, EventParam, DefaultParam, ] def __init__(self, *checkers: Union[T_PermissionChecker, Dependent[bool]]) -> None: ``` T_PermissionChecker = _DependentCallable[bool] _DependentCallable = Union[Callable[..., T], Callable[..., Awaitable[T]]] ``` self.checkers: Set[Dependent[bool]] = { checker if isinstance(checker, Dependent) else Dependent[bool].parse( call=checker, allow_types=self.HANDLER_PARAM_TYPES ) for checker in checkers } # 逻辑和Rule几乎一样,不过HANDLER_PARAM_TYPES又比Rule少了StateParam,因为此时还没有上下文 def __and__(self, other: object) -> NoReturn: ``` 不支持 & 运算 ``` raise RuntimeError("And operation between Permissions is not allowed.") def __or__( self, other: Optional[Union["Permission", T_PermissionChecker]] ) -> "Permission": ``` 支持左 | 运算 Permission() | Permission() Permission() | Union[T_PermissionChecker, Dependent[bool]]类型 最终生成一个新的Permission Permission() | None 返回自身,防止意外None值 ``` if other is None: return self elif isinstance(other, Permission): return Permission(*self.checkers, *other.checkers) else: return Permission(*self.checkers, other) def __ror__( self, other: Optional[Union["Permission", T_PermissionChecker]] ) -> "Permission": ``` 支持右 | 运算 Permission() | Permission() Union[T_PermissionChecker, Dependent[bool]]类型 | Permission() 最终生成一个新的Permission None | Permission() 返回自身,防止意外None值 ``` if other is None: return self elif isinstance(other, Permission): return Permission(*other.checkers, *self.checkers) else: return Permission(other, *self.checkers)
on、on_metaevent、on_message、on_notice、on_request
用于生成Matcher子类
分别可以生成Matcher.type为任意、meta_event、message、notice、request的Matcher子类
on
on_metaevent
on_message
on_notice
on_request
``` 主要代码已在前文介绍 默认不block ``` def on( type: str = "", rule: Optional[Union[Rule, T_RuleChecker]] = None, permission: Optional[Union[Permission, T_PermissionChecker]] = None, *, handlers: Optional[List[Union[T_Handler, Dependent]]] = None, temp: bool = False, expire_time: Optional[Union[datetime, timedelta]] = None, priority: int = 1, block: bool = False, state: Optional[T_State] = None, _depth: int = 0, ) -> Type[Matcher]: plugin_chain = _current_plugin_chain.get() matcher = Matcher.new( type, Rule() & rule, Permission() | permission, temp=temp, expire_time=expire_time, priority=priority, block=block, handlers=handlers, plugin=plugin_chain[-1] if plugin_chain else None, module=_get_matcher_module(_depth + 1), default_state=state, ) _store_matcher(matcher) return matcher
``` Matcher.type为meta_event 没有permission,因为这不是用户触发的事件 默认不block ``` def on_metaevent( rule: Optional[Union[Rule, T_RuleChecker]] = None, *, handlers: Optional[List[Union[T_Handler, Dependent]]] = None, temp: bool = False, expire_time: Optional[Union[datetime, timedelta]] = None, priority: int = 1, block: bool = False, state: Optional[T_State] = None, _depth: int = 0, ) -> Type[Matcher]: plugin_chain = _current_plugin_chain.get() matcher = Matcher.new( "meta_event", Rule() & rule, Permission(), temp=temp, expire_time=expire_time, priority=priority, block=block, handlers=handlers, plugin=plugin_chain[-1] if plugin_chain else None, module=_get_matcher_module(_depth + 1), default_state=state, ) _store_matcher(matcher) return matcher
``` Matcher.type为on_message 默认会block ``` def on_message( rule: Optional[Union[Rule, T_RuleChecker]] = None, permission: Optional[Union[Permission, T_PermissionChecker]] = None, *, handlers: Optional[List[Union[T_Handler, Dependent]]] = None, temp: bool = False, expire_time: Optional[Union[datetime, timedelta]] = None, priority: int = 1, block: bool = True, state: Optional[T_State] = None, _depth: int = 0, ) -> Type[Matcher]: plugin_chain = _current_plugin_chain.get() matcher = Matcher.new( "message", Rule() & rule, Permission() | permission, temp=temp, expire_time=expire_time, priority=priority, block=block, handlers=handlers, plugin=plugin_chain[-1] if plugin_chain else None, module=_get_matcher_module(_depth + 1), default_state=state, ) _store_matcher(matcher) return matcher
``` Matcher.type为notice 没有permission,因为这不是用户触发的事件 默认会block ``` def on_notice( rule: Optional[Union[Rule, T_RuleChecker]] = None, *, handlers: Optional[List[Union[T_Handler, Dependent]]] = None, temp: bool = False, expire_time: Optional[Union[datetime, timedelta]] = None, priority: int = 1, block: bool = True, state: Optional[T_State] = None, _depth: int = 0, ) -> Type[Matcher]: plugin_chain = _current_plugin_chain.get() matcher = Matcher.new( "notice", Rule() & rule, Permission(), temp=temp, expire_time=expire_time, priority=priority, block=block, handlers=handlers, plugin=plugin_chain[-1] if plugin_chain else None, module=_get_matcher_module(_depth + 1), default_state=state, ) _store_matcher(matcher) return matcher
``` Matcher.type为request 没有permission,因为这不是用户触发的事件 默认不block ``` def on_request( rule: Optional[Union[Rule, T_RuleChecker]] = None, *, handlers: Optional[List[Union[T_Handler, Dependent]]] = None, temp: bool = False, expire_time: Optional[Union[datetime, timedelta]] = None, priority: int = 1, block: bool = False, state: Optional[T_State] = None, _depth: int = 0, ) -> Type[Matcher]: plugin_chain = _current_plugin_chain.get() matcher = Matcher.new( "request", Rule() & rule, Permission(), temp=temp, expire_time=expire_time, priority=priority, block=block, handlers=handlers, plugin=plugin_chain[-1] if plugin_chain else None, module=_get_matcher_module(_depth + 1), default_state=state, ) _store_matcher(matcher) return matcher
对于其它on函数将在下一节介绍