From 98ef09585a9756542def3570f9c08b00e00c44f1 Mon Sep 17 00:00:00 2001 From: yanyongyu Date: Wed, 19 Jan 2022 16:16:56 +0800 Subject: [PATCH] :bulb: add docstrings --- nonebot/matcher.py | 4 + nonebot/params.py | 56 +++++++++++-- nonebot/permission.py | 103 +++++++++++++++--------- nonebot/rule.py | 183 +++++++++++++++++++++++++++++------------- nonebot/typing.py | 68 ++++++---------- nonebot/utils.py | 37 +++++---- poetry.lock | 8 +- 7 files changed, 297 insertions(+), 162 deletions(-) diff --git a/nonebot/matcher.py b/nonebot/matcher.py index 307e90c3..db983319 100644 --- a/nonebot/matcher.py +++ b/nonebot/matcher.py @@ -245,6 +245,8 @@ class Matcher(metaclass=MatcherMeta): 参数: bot: Bot 对象 event: 上报事件 + stack: 异步上下文栈 + dependency_cache: 依赖缓存 返回: 是否满足权限 @@ -269,6 +271,8 @@ class Matcher(metaclass=MatcherMeta): bot: Bot 对象 event: 上报事件 state: 当前状态 + stack: 异步上下文栈 + dependency_cache: 依赖缓存 返回: 是否满足匹配规则 diff --git a/nonebot/params.py b/nonebot/params.py index 2f6cef4c..d9686468 100644 --- a/nonebot/params.py +++ b/nonebot/params.py @@ -1,4 +1,5 @@ -""" +"""本模块定义了依赖注入的各类参数。 + FrontMatter: sidebar_position: 4 description: nonebot.params 模块 @@ -61,8 +62,7 @@ def Depends( *, use_cache: bool = True, ) -> Any: - """ - 参数依赖注入装饰器 + """子依赖装饰器 参数: dependency: 依赖函数。默认为参数的类型注释。 @@ -87,6 +87,8 @@ def Depends( class DependParam(Param): + """子依赖参数""" + @classmethod def _check_param( cls, @@ -182,6 +184,8 @@ class _BotChecker(Param): class BotParam(Param): + """{ref}`nonebot.adapters._bot.Bot` 参数""" + @classmethod def _check_param( cls, dependent: Dependent, name: str, param: inspect.Parameter @@ -223,6 +227,8 @@ class _EventChecker(Param): class EventParam(Param): + """{ref}`nonebot.adapters._event.Event` 参数""" + @classmethod def _check_param( cls, dependent: Dependent, name: str, param: inspect.Parameter @@ -256,6 +262,7 @@ async def _event_type(event: Event) -> str: def EventType() -> str: + """{ref}`nonebot.adapters._event.Event` 类型参数""" return Depends(_event_type) @@ -264,6 +271,7 @@ async def _event_message(event: Event) -> Message: def EventMessage() -> Any: + """{ref}`nonebot.adapters._event.Event` 消息参数""" return Depends(_event_message) @@ -272,6 +280,7 @@ async def _event_plain_text(event: Event) -> str: def EventPlainText() -> str: + """{ref}`nonebot.adapters._event.Event` 纯文本消息参数""" return Depends(_event_plain_text) @@ -280,6 +289,7 @@ async def _event_to_me(event: Event) -> bool: def EventToMe() -> bool: + """{ref}`nonebot.adapters._event.Event` `to_me` 参数""" return Depends(_event_to_me) @@ -288,11 +298,14 @@ class StateInner(T_State): def State() -> T_State: - warnings.warn("State() is deprecated, use T_State instead", DeprecationWarning) + """**Deprecated**: 事件处理状态参数,请直接使用 {ref}`nonebot.typing.T_State`""" + warnings.warn("State() is deprecated, use `T_State` instead", DeprecationWarning) return StateInner() class StateParam(Param): + """事件处理状态参数""" + @classmethod def _check_param( cls, dependent: Dependent, name: str, param: inspect.Parameter @@ -314,7 +327,8 @@ def _command(state: T_State) -> Message: def Command() -> Tuple[str, ...]: - return Depends(_command, use_cache=False) + """消息命令元组""" + return Depends(_command) def _raw_command(state: T_State) -> Message: @@ -322,7 +336,8 @@ def _raw_command(state: T_State) -> Message: def RawCommand() -> str: - return Depends(_raw_command, use_cache=False) + """消息命令文本""" + return Depends(_raw_command) def _command_arg(state: T_State) -> Message: @@ -330,7 +345,8 @@ def _command_arg(state: T_State) -> Message: def CommandArg() -> Any: - return Depends(_command_arg, use_cache=False) + """消息命令参数""" + return Depends(_command_arg) def _shell_command_args(state: T_State) -> Any: @@ -338,6 +354,7 @@ def _shell_command_args(state: T_State) -> Any: def ShellCommandArgs(): + """shell 命令解析后的参数字典""" return Depends(_shell_command_args, use_cache=False) @@ -346,6 +363,7 @@ def _shell_command_argv(state: T_State) -> List[str]: def ShellCommandArgv() -> Any: + """shell 命令原始参数列表""" return Depends(_shell_command_argv, use_cache=False) @@ -354,6 +372,7 @@ def _regex_matched(state: T_State) -> str: def RegexMatched() -> str: + """正则匹配结果""" return Depends(_regex_matched, use_cache=False) @@ -362,6 +381,7 @@ def _regex_group(state: T_State): def RegexGroup() -> Tuple[Any, ...]: + """正则匹配结果 group 元组""" return Depends(_regex_group, use_cache=False) @@ -370,10 +390,13 @@ def _regex_dict(state: T_State): def RegexDict() -> Dict[str, Any]: + """正则匹配结果 group 字典""" return Depends(_regex_dict, use_cache=False) class MatcherParam(Param): + """事件响应器实例参数""" + @classmethod def _check_param( cls, dependent: Dependent, name: str, param: inspect.Parameter @@ -388,6 +411,8 @@ class MatcherParam(Param): def Received(id: Optional[str] = None, default: Any = None) -> Any: + """`receive` 事件参数""" + def _received(matcher: "Matcher"): return matcher.get_receive(id or "", default) @@ -395,6 +420,8 @@ def Received(id: Optional[str] = None, default: Any = None) -> Any: def LastReceived(default: Any = None) -> Any: + """`last_receive` 事件参数""" + def _last_received(matcher: "Matcher") -> Any: return matcher.get_last_receive(default) @@ -410,18 +437,23 @@ class ArgInner: def Arg(key: Optional[str] = None) -> Any: + """`got` 的 Arg 参数消息""" return ArgInner(key, "message") def ArgStr(key: Optional[str] = None) -> str: + """`got` 的 Arg 参数消息文本""" return ArgInner(key, "str") # type: ignore def ArgPlainText(key: Optional[str] = None) -> str: + """`got` 的 Arg 参数消息纯文本""" return ArgInner(key, "plaintext") # type: ignore class ArgParam(Param): + """`got` 的 Arg 参数""" + @classmethod def _check_param( cls, dependent: Dependent, name: str, param: inspect.Parameter @@ -442,6 +474,8 @@ class ArgParam(Param): class ExceptionParam(Param): + """`run_postprocessor` 的异常参数""" + @classmethod def _check_param( cls, dependent: Dependent, name: str, param: inspect.Parameter @@ -456,6 +490,8 @@ class ExceptionParam(Param): class DefaultParam(Param): + """默认值参数""" + @classmethod def _check_param( cls, dependent: Dependent, name: str, param: inspect.Parameter @@ -468,3 +504,9 @@ class DefaultParam(Param): from nonebot.matcher import Matcher + +__autodoc__ = { + "DependsInner": False, + "StateInner": False, + "ArgInner": False, +} diff --git a/nonebot/permission.py b/nonebot/permission.py index 3079f47e..28f4e632 100644 --- a/nonebot/permission.py +++ b/nonebot/permission.py @@ -1,7 +1,7 @@ -""" -## 权限 +"""本模块是 {ref}`nonebot.matcher.Matcher.permission` 的类型定义。 -每个 `Matcher` 拥有一个 `Permission` ,其中是 `PermissionChecker` 的集合,只要有一个 `PermissionChecker` 检查结果为 `True` 时就会继续运行。 +每个 {ref}`nonebot.matcher.Matcher` 拥有一个 {ref}`nonebot.permission.Permission` , +其中是 `PermissionChecker` 的集合,只要有一个 `PermissionChecker` 检查结果为 `True` 时就会继续运行。 FrontMatter: sidebar_position: 6 @@ -15,7 +15,7 @@ from typing import Any, Set, Tuple, Union, NoReturn, Optional, Coroutine from nonebot.adapters import Bot, Event from nonebot.dependencies import Dependent from nonebot.exception import SkippedException -from nonebot.typing import T_Handler, T_DependencyCache, T_PermissionChecker +from nonebot.typing import T_DependencyCache, T_PermissionChecker from nonebot.params import ( BotParam, EventType, @@ -33,15 +33,18 @@ async def _run_coro_with_catch(coro: Coroutine[Any, Any, Any]): class Permission: - """ - `Matcher` 规则类,当事件传递时,在 `Matcher` 运行前进行检查。 + """{ref}`nonebot.matcher.Matcher` 权限类。 + + 当事件传递时,在 {ref}`nonebot.matcher.Matcher` 运行前进行检查。 + + 参数: + checkers: PermissionChecker 用法: ```python Permission(async_function) | sync_function # 等价于 - from nonebot.utils import run_sync - Permission(async_function, run_sync(sync_function)) + Permission(async_function, sync_function) ``` """ @@ -55,11 +58,6 @@ class Permission: ] def __init__(self, *checkers: Union[T_PermissionChecker, Dependent[bool]]) -> None: - """ - 参数: - *checkers: PermissionChecker - """ - self.checkers: Set[Dependent[bool]] = set( checker if isinstance(checker, Dependent) @@ -68,9 +66,7 @@ class Permission: ) for checker in checkers ) - """ - 存储 `PermissionChecker` - """ + """存储 `PermissionChecker`""" async def __call__( self, @@ -79,8 +75,7 @@ class Permission: stack: Optional[AsyncExitStack] = None, dependency_cache: Optional[T_DependencyCache] = None, ) -> bool: - """ - 检查是否满足某个权限 + """检查是否满足某个权限 参数: bot: Bot 对象 @@ -120,44 +115,73 @@ class Permission: class Message: + """检查是否为消息事件""" + + __slots__ = () + async def __call__(self, type: str = EventType()) -> bool: return type == "message" class Notice: + """检查是否为通知事件""" + + __slots__ = () + async def __call__(self, type: str = EventType()) -> bool: return type == "notice" class Request: + """检查是否为请求事件""" + + __slots__ = () + async def __call__(self, type: str = EventType()) -> bool: return type == "request" class MetaEvent: + """检查是否为元事件""" + + __slots__ = () + async def __call__(self, type: str = EventType()) -> bool: return type == "meta_event" -MESSAGE = Permission(Message()) +MESSAGE: Permission = Permission(Message()) +"""匹配任意 `message` 类型事件 + +仅在需要同时捕获不同类型事件时使用,优先使用 message type 的 Matcher。 """ -匹配任意 `message` 类型事件,仅在需要同时捕获不同类型事件时使用。优先使用 message type 的 Matcher。 +NOTICE: Permission = Permission(Notice()) +"""匹配任意 `notice` 类型事件 + +仅在需要同时捕获不同类型事件时使用,优先使用 notice type 的 Matcher。 """ -NOTICE = Permission(Notice()) +REQUEST: Permission = Permission(Request()) +"""匹配任意 `request` 类型事件 + +仅在需要同时捕获不同类型事件时使用,优先使用 request type 的 Matcher。 """ -匹配任意 `notice` 类型事件,仅在需要同时捕获不同类型事件时使用。优先使用 notice type 的 Matcher。 -""" -REQUEST = Permission(Request()) -""" -匹配任意 `request` 类型事件,仅在需要同时捕获不同类型事件时使用。优先使用 request type 的 Matcher。 -""" -METAEVENT = Permission(MetaEvent()) -""" -匹配任意 `meta_event` 类型事件,仅在需要同时捕获不同类型事件时使用。优先使用 meta_event type 的 Matcher。 +METAEVENT: Permission = Permission(MetaEvent()) +"""匹配任意 `meta_event` 类型事件 + +仅在需要同时捕获不同类型事件时使用,优先使用 meta_event type 的 Matcher。 """ class User: + """检查当前事件是否属于指定会话 + + 参数: + users: 会话 ID 元组 + perm: 需同时满足的权限 + """ + + __slots__ = ("users", "perm") + def __init__( self, users: Tuple[str, ...], perm: Optional[Permission] = None ) -> None: @@ -172,18 +196,21 @@ class User: def USER(*users: str, perm: Optional[Permission] = None): - """ - `event` 的 `session_id` 在白名单内且满足 perm + """匹配当前事件属于指定会话 参数: - *user: 白名单 - perm: 需要同时满足的权限 + user: 会话白名单 + perm: 需要同时满足的权限 """ return Permission(User(users, perm)) class SuperUser: + """检查当前事件是否是消息事件且属于超级管理员""" + + __slots__ = () + async def __call__(self, bot: Bot, event: Event) -> bool: return event.get_type() == "message" and ( f"{bot.adapter.get_name().split(maxsplit=1)[0].lower()}:{event.get_user_id()}" @@ -192,7 +219,7 @@ class SuperUser: ) -SUPERUSER = Permission(SuperUser()) -""" -匹配任意超级用户消息类型事件 -""" +SUPERUSER: Permission = Permission(SuperUser()) +"""匹配任意超级用户消息类型事件""" + +__autodoc__ = {"Permission.__call__": True} diff --git a/nonebot/rule.py b/nonebot/rule.py index 8decd8c5..479017c2 100644 --- a/nonebot/rule.py +++ b/nonebot/rule.py @@ -1,7 +1,7 @@ -""" -## 规则 +"""本模块是 {ref}`nonebot.matcher.Matcher.rule` 的类型定义。 -每个事件响应器 `Matcher` 拥有一个匹配规则 `Rule` ,其中是 `RuleChecker` 的集合,只有当所有 `RuleChecker` 检查结果为 `True` 时继续运行。 +每个事件响应器 {ref}`nonebot.matcher.Matcher` 拥有一个匹配规则 {ref}`nonebot.rule.Rule` +其中是 `RuleChecker` 的集合,只有当所有 `RuleChecker` 检查结果为 `True` 时继续运行。 FrontMatter: sidebar_position: 5 @@ -42,6 +42,7 @@ from nonebot.params import ( BotParam, EventToMe, EventType, + CommandArg, EventParam, StateParam, DependParam, @@ -61,15 +62,18 @@ CMD_RESULT = TypedDict( class Rule: - """ - `Matcher` 规则类,当事件传递时,在 `Matcher` 运行前进行检查。 + """{ref}`nonebot.matcher.Matcher` 规则类。 + + 当事件传递时,在 {ref}`nonebot.matcher.Matcher` 运行前进行检查。 + + 参数: + *checkers: RuleChecker 用法: ```python Rule(async_function) & sync_function # 等价于 - from nonebot.utils import run_sync - Rule(async_function, run_sync(sync_function)) + Rule(async_function, sync_function) ``` """ @@ -84,11 +88,6 @@ class Rule: ] def __init__(self, *checkers: Union[T_RuleChecker, Dependent[bool]]) -> None: - """ - 参数: - *checkers: RuleChecker - - """ self.checkers: Set[Dependent[bool]] = set( checker if isinstance(checker, Dependent) @@ -97,9 +96,7 @@ class Rule: ) for checker in checkers ) - """ - 存储 `RuleChecker` - """ + """存储 `RuleChecker`""" async def __call__( self, @@ -109,8 +106,7 @@ class Rule: stack: Optional[AsyncExitStack] = None, dependency_cache: Optional[T_DependencyCache] = None, ) -> bool: - """ - 检查是否符合所有规则 + """检查是否符合所有规则 参数: bot: Bot 对象 @@ -186,6 +182,15 @@ class TrieRule: class StartswithRule: + """检查消息纯文本是否以指定字符串开头。 + + 参数: + msg: 指定消息开头字符串元组 + ignorecase: 是否忽略大小写 + """ + + __slots__ = ("msg", "ignorecase") + def __init__(self, msg: Tuple[str, ...], ignorecase: bool = False): self.msg = msg self.ignorecase = ignorecase @@ -205,11 +210,11 @@ class StartswithRule: def startswith(msg: Union[str, Tuple[str, ...]], ignorecase: bool = False) -> Rule: - """ - 匹配消息开头 + """匹配消息纯文本开头。 参数: - msg: 消息开头字符串 + msg: 指定消息开头字符串元组 + ignorecase: 是否忽略大小写 """ if isinstance(msg, str): msg = (msg,) @@ -218,6 +223,15 @@ def startswith(msg: Union[str, Tuple[str, ...]], ignorecase: bool = False) -> Ru class EndswithRule: + """检查消息纯文本是否以指定字符串结尾。 + + 参数: + msg: 指定消息结尾字符串元组 + ignorecase: 是否忽略大小写 + """ + + __slots__ = ("msg", "ignorecase") + def __init__(self, msg: Tuple[str, ...], ignorecase: bool = False): self.msg = msg self.ignorecase = ignorecase @@ -237,11 +251,11 @@ class EndswithRule: def endswith(msg: Union[str, Tuple[str, ...]], ignorecase: bool = False) -> Rule: - """ - 匹配消息结尾 + """匹配消息纯文本结尾。 参数: - msg: 消息结尾字符串 + msg: 指定消息开头字符串元组 + ignorecase: 是否忽略大小写 """ if isinstance(msg, str): msg = (msg,) @@ -250,6 +264,14 @@ def endswith(msg: Union[str, Tuple[str, ...]], ignorecase: bool = False) -> Rule class KeywordsRule: + """检查消息纯文本是否包含指定关键字。 + + 参数: + keywords: 指定关键字元组 + """ + + __slots__ = ("keywords",) + def __init__(self, *keywords: str): self.keywords = keywords @@ -262,17 +284,24 @@ class KeywordsRule: def keyword(*keywords: str) -> Rule: - """ - 匹配消息关键词 + """匹配消息纯文本关键词。 参数: - *keywords: 关键词 + keywords: 指定关键字元组 """ return Rule(KeywordsRule(*keywords)) class CommandRule: + """检查消息是否为指定命令。 + + 参数: + cmds: 指定命令元组列表 + """ + + __slots__ = ("cmds",) + def __init__(self, cmds: List[Tuple[str, ...]]): self.cmds = cmds @@ -284,22 +313,26 @@ class CommandRule: def command(*cmds: Union[str, Tuple[str, ...]]) -> Rule: - """ - 命令形式匹配,根据配置里提供的 `command_start`, `command_sep` 判断消息是否为命令。 + """匹配消息命令。 - 可以通过 `state["_prefix"]["command"]` 获取匹配成功的命令(例:`("test",)`),通过 `state["_prefix"]["raw_command"]` 获取匹配成功的原始命令文本(例:`"/test"`)。 + 根据配置里提供的 {ref}``command_start` `, + {ref}``command_sep` ` 判断消息是否为命令。 + + 可以通过 {ref}`nonebot.params.Command` 获取匹配成功的命令(例: `("test",)`), + 通过 {ref}`nonebot.params.RawCommand` 获取匹配成功的原始命令文本(例: `"/test"`), + 通过 {ref}`nonebot.params.CommandArg` 获取匹配成功的命令参数。 参数: - *cmds: 命令内容 + cmds: 命令文本或命令元组 用法: 使用默认 `command_start`, `command_sep` 配置 - 命令 `("test",)` 可以匹配:`/test` 开头的消息 - 命令 `("test", "sub")` 可以匹配”`/test.sub` 开头的消息 + 命令 `("test",)` 可以匹配: `/test` 开头的消息 + 命令 `("test", "sub")` 可以匹配: `/test.sub` 开头的消息 :::tip 提示 - 命令内容与后续消息间无需空格! + 命令内容与后续消息间无需空格! ::: """ @@ -324,8 +357,11 @@ def command(*cmds: Union[str, Tuple[str, ...]]) -> Rule: class ArgumentParser(ArgParser): - """ - `shell_like` 命令参数解析器,解析出错时不会退出程序。 + """`shell_like` 命令参数解析器,解析出错时不会退出程序。 + + 用法: + 用法与 `argparse.ArgumentParser` 相同, + 参考文档: [argparse](https://docs.python.org/3/library/argparse.html) """ def _print_message(self, message, file=None): @@ -350,6 +386,15 @@ class ArgumentParser(ArgParser): class ShellCommandRule: + """检查消息是否为指定 shell 命令。 + + 参数: + cmds: 指定命令元组列表 + parser: 可选参数解析器 + """ + + __slots__ = ("cmds", "parser") + def __init__(self, cmds: List[Tuple[str, ...]], parser: Optional[ArgumentParser]): self.cmds = cmds self.parser = parser @@ -358,12 +403,11 @@ class ShellCommandRule: self, state: T_State, cmd: Optional[Tuple[str, ...]] = Command(), - msg: Message = EventMessage(), + msg: Optional[Message] = CommandArg(), ) -> bool: - if cmd in self.cmds: + if cmd in self.cmds and msg is not None: message = str(msg) - strip_message = message[len(state[PREFIX_KEY][RAW_CMD_KEY]) :].lstrip() - state[SHELL_ARGV] = shlex.split(strip_message) + state[SHELL_ARGV] = shlex.split(message) if self.parser: try: args = self.parser.parse_args(state[SHELL_ARGV]) @@ -378,18 +422,24 @@ class ShellCommandRule: def shell_command( *cmds: Union[str, Tuple[str, ...]], parser: Optional[ArgumentParser] = None ) -> Rule: - """ - 支持 `shell_like` 解析参数的命令形式匹配,根据配置里提供的 `command_start`, `command_sep` 判断消息是否为命令。 + """匹配 `shell_like` 形式的消息命令。 - 可以通过 `state["_prefix"]["command"]` 获取匹配成功的命令(例:`("test",)`),通过 `state["_prefix"]["raw_command"]` 获取匹配成功的原始命令文本(例:`"/test"`)。 + 根据配置里提供的 {ref}``command_start` `, + {ref}``command_sep` ` 判断消息是否为命令。 - 可以通过 `state["argv"]` 获取用户输入的原始参数列表 + 可以通过 {ref}`nonebot.params.Command` 获取匹配成功的命令(例: `("test",)`), + 通过 {ref}`nonebot.params.RawCommand` 获取匹配成功的原始命令文本(例: `"/test"`), + 通过 {ref}`nonebot.params.ShellCommandArgv` 获取解析前的参数列表(例: `["arg", "-h"]`), + 通过 {ref}`nonebot.params.ShellCommandArgs` 获取解析后的参数字典(例: `{"arg": "arg", "h": True}`)。 - 添加 `parser` 参数后, 可以自动处理消息并将结果保存在 `state["args"]` 中。 + :::warning 警告 + 如果参数解析失败,则通过 {ref}`nonebot.params.ShellCommandArgs` + 获取的将是 {ref}`nonebot.exception.ParserExit` 异常。 + ::: 参数: - *cmds: 命令内容 - parser: `nonebot.rule.ArgumentParser` 对象 + cmds: 命令文本或命令元组 + parser: {ref}`nonebot.rule.ArgumentParser` 对象 用法: 使用默认 `command_start`, `command_sep` 配置,更多示例参考 `argparse` 标准库文档。 @@ -404,7 +454,7 @@ def shell_command( ``` :::tip 提示 - 命令内容与后续消息间无需空格! + 命令内容与后续消息间无需空格! ::: """ if parser is not None and not isinstance(parser, ArgumentParser): @@ -431,6 +481,15 @@ def shell_command( class RegexRule: + """检查消息字符串是否符合指定正则表达式。 + + 参数: + regex: 正则表达式 + flags: 正则表达式标记 + """ + + __slots__ = ("regex", "flags") + def __init__(self, regex: str, flags: int = 0): self.regex = regex self.flags = flags @@ -454,32 +513,46 @@ class RegexRule: def regex(regex: str, flags: Union[int, re.RegexFlag] = 0) -> Rule: - """ - 根据正则表达式进行匹配。 + """匹配符合正则表达式的消息字符串。 - 可以通过 `state["_matched"]` `state["_matched_groups"]` `state["_matched_dict"]` - 获取正则表达式匹配成功的文本。 + 可以通过 {ref}`nonebot.params.RegexMatched` 获取匹配成功的字符串, + 通过 {ref}`nonebot.params.RegexGroup` 获取匹配成功的 group 元组, + 通过 {ref}`nonebot.params.RegexDict` 获取匹配成功的 group 字典。 参数: regex: 正则表达式 - flags: 正则标志 + flags: 正则表达式标记 :::tip 提示 正则表达式匹配使用 search 而非 match,如需从头匹配请使用 `r"^xxx"` 来确保匹配开头 ::: + + :::tip 提示 + 正则表达式匹配使用 `EventMessage` 的 `str` 字符串,而非 `EventMessage` 的 `PlainText` 纯文本字符串 + ::: """ return Rule(RegexRule(regex, flags)) class ToMeRule: + """检查事件是否与机器人有关。""" + + __slots__ = () + async def __call__(self, to_me: bool = EventToMe()) -> bool: return to_me def to_me() -> Rule: - """ - 通过 `event.is_tome()` 判断事件是否与机器人有关 - """ + """匹配与机器人有关的事件。""" return Rule(ToMeRule()) + + +__autodoc__ = { + "Rule.__call__": True, + "TrieRule": False, + "ArgumentParser.exit": False, + "ArgumentParser.parse_args": False, +} diff --git a/nonebot/typing.py b/nonebot/typing.py index a92b79e9..12abedab 100644 --- a/nonebot/typing.py +++ b/nonebot/typing.py @@ -1,12 +1,12 @@ -""" -## 类型 +"""本模块定义了 NoneBot 模块中共享的一些类型。 -下面的文档中,「类型」部分使用 Python 的 Type Hint 语法,见 [`PEP 484`](https://www.python.org/dev/peps/pep-0484/)、[`PEP 526`](https://www.python.org/dev/peps/pep-0526/) 和 [`typing`](https://docs.python.org/3/library/typing.html)。 +下面的文档中,「类型」部分使用 Python 的 Type Hint 语法, +参考 [`PEP 484`](https://www.python.org/dev/peps/pep-0484/), +[`PEP 526`](https://www.python.org/dev/peps/pep-0526/) 和 +[`typing`](https://docs.python.org/3/library/typing.html)。 除了 Python 内置的类型,下面还出现了如下 NoneBot 自定类型,实际上它们是 Python 内置类型的别名。 -以下类型均可从 nonebot.typing 模块导入。 - FrontMatter: sidebar_position: 11 description: nonebot.typing 模块 @@ -25,13 +25,15 @@ from typing import ( if TYPE_CHECKING: from asyncio import Task - from nonebot.adapters import Bot, Event + from nonebot.adapters import Bot from nonebot.permission import Permission T_Wrapped = TypeVar("T_Wrapped", bound=Callable) -def overrides(InterfaceClass: object): +def overrides(InterfaceClass: object) -> Callable[[T_Wrapped], T_Wrapped]: + """标记一个方法为父类 interface 的 implement""" + def overrider(func: T_Wrapped) -> T_Wrapped: assert func.__name__ in dir(InterfaceClass), f"Error method: {func.__name__}" return func @@ -40,32 +42,21 @@ def overrides(InterfaceClass: object): T_State = Dict[Any, Any] -""" -事件处理状态 State 类型 -""" +"""事件处理状态 State 类型""" T_BotConnectionHook = Callable[["Bot"], Awaitable[None]] -""" -Bot 连接建立时执行的函数 -""" +"""Bot 连接建立时插槽函数""" T_BotDisconnectionHook = Callable[["Bot"], Awaitable[None]] -""" -Bot 连接断开时执行的函数 -""" +"""Bot 连接断开时插槽函数""" T_CallingAPIHook = Callable[["Bot", str, Dict[str, Any]], Awaitable[None]] -""" -`bot.call_api` 时执行的函数 -""" +"""`bot.call_api` 插槽函数""" T_CalledAPIHook = Callable[ ["Bot", Optional[Exception], str, Dict[str, Any], Any], Awaitable[None] ] -""" -`bot.call_api` 后执行的函数,参数分别为 bot, exception, api, data, result -""" +"""`bot.call_api` 后执行的函数,参数分别为 bot, exception, api, data, result""" T_EventPreProcessor = Callable[..., Union[None, Awaitable[None]]] -""" -事件预处理函数 EventPreProcessor 类型 +"""事件预处理函数 EventPreProcessor 类型 依赖参数: @@ -76,8 +67,7 @@ T_EventPreProcessor = Callable[..., Union[None, Awaitable[None]]] - DefaultParam: 带有默认值的参数 """ T_EventPostProcessor = Callable[..., Union[None, Awaitable[None]]] -""" -事件预处理函数 EventPostProcessor 类型 +"""事件预处理函数 EventPostProcessor 类型 依赖参数: @@ -88,8 +78,7 @@ T_EventPostProcessor = Callable[..., Union[None, Awaitable[None]]] - DefaultParam: 带有默认值的参数 """ T_RunPreProcessor = Callable[..., Union[None, Awaitable[None]]] -""" -事件响应器运行前预处理函数 RunPreProcessor 类型 +"""事件响应器运行前预处理函数 RunPreProcessor 类型 依赖参数: @@ -101,8 +90,7 @@ T_RunPreProcessor = Callable[..., Union[None, Awaitable[None]]] - DefaultParam: 带有默认值的参数 """ T_RunPostProcessor = Callable[..., Union[None, Awaitable[None]]] -""" -事件响应器运行前预处理函数 RunPostProcessor 类型,第二个参数为运行时产生的错误(如果存在) +"""事件响应器运行前预处理函数 RunPostProcessor 类型 依赖参数: @@ -116,8 +104,7 @@ T_RunPostProcessor = Callable[..., Union[None, Awaitable[None]]] """ T_RuleChecker = Callable[..., Union[bool, Awaitable[bool]]] -""" -RuleChecker 即判断是否响应事件的处理函数。 +"""RuleChecker 即判断是否响应事件的处理函数。 依赖参数: @@ -128,8 +115,7 @@ RuleChecker 即判断是否响应事件的处理函数。 - DefaultParam: 带有默认值的参数 """ T_PermissionChecker = Callable[..., Union[bool, Awaitable[bool]]] -""" -RuleChecker 即判断是否响应消息的处理函数。 +"""PermissionChecker 即判断事件是否满足权限的处理函数。 依赖参数: @@ -140,12 +126,9 @@ RuleChecker 即判断是否响应消息的处理函数。 """ T_Handler = Callable[..., Any] -""" -Handler 处理函数。 -""" +"""Handler 处理函数。""" T_TypeUpdater = Callable[..., Union[str, Awaitable[str]]] -""" -TypeUpdater 在 Matcher.pause, Matcher.reject 时被运行,用于更新响应的事件类型。默认会更新为 `message`。 +"""TypeUpdater 在 Matcher.pause, Matcher.reject 时被运行,用于更新响应的事件类型。默认会更新为 `message`。 依赖参数: @@ -157,8 +140,7 @@ TypeUpdater 在 Matcher.pause, Matcher.reject 时被运行,用于更新响应 - DefaultParam: 带有默认值的参数 """ T_PermissionUpdater = Callable[..., Union["Permission", Awaitable["Permission"]]] -""" -PermissionUpdater 在 Matcher.pause, Matcher.reject 时被运行,用于更新会话对象权限。默认会更新为当前事件的触发对象。 +"""PermissionUpdater 在 Matcher.pause, Matcher.reject 时被运行,用于更新会话对象权限。默认会更新为当前事件的触发对象。 依赖参数: @@ -170,6 +152,4 @@ PermissionUpdater 在 Matcher.pause, Matcher.reject 时被运行,用于更新 - DefaultParam: 带有默认值的参数 """ T_DependencyCache = Dict[Callable[..., Any], "Task[Any]"] -""" -依赖缓存, 用于存储依赖函数的返回值 -""" +"""依赖缓存, 用于存储依赖函数的返回值""" diff --git a/nonebot/utils.py b/nonebot/utils.py index 3cafa155..f6f585df 100644 --- a/nonebot/utils.py +++ b/nonebot/utils.py @@ -1,4 +1,5 @@ -""" +"""本模块包含了 NoneBot 的一些工具函数 + FrontMatter: sidebar_position: 8 description: nonebot.utils 模块 @@ -36,8 +37,9 @@ V = TypeVar("V") def escape_tag(s: str) -> str: - """ - 用于记录带颜色日志时转义 `` 类型特殊标签 + """用于记录带颜色日志时转义 `` 类型特殊标签 + + 参考: [loguru color 标签](https://loguru.readthedocs.io/en/stable/api/logger.html#color) 参数: s: 需要转义的字符串 @@ -48,6 +50,7 @@ def escape_tag(s: str) -> str: def generic_check_issubclass( cls: Any, class_or_tuple: Union[Type[Any], Tuple[Type[Any], ...]] ) -> bool: + """检查 cls 是否是 class_or_tuple 中的一个类型子类或""" try: return issubclass(cls, class_or_tuple) except TypeError: @@ -65,6 +68,7 @@ def generic_check_issubclass( def is_coroutine_callable(call: Callable[..., Any]) -> bool: + """检查 call 是否是一个 callable 协程函数""" if inspect.isroutine(call): return inspect.iscoroutinefunction(call) if inspect.isclass(call): @@ -74,6 +78,7 @@ def is_coroutine_callable(call: Callable[..., Any]) -> bool: def is_gen_callable(call: Callable[..., Any]) -> bool: + """检查 call 是否是一个生成器函数""" if inspect.isgeneratorfunction(call): return True func_ = getattr(call, "__call__", None) @@ -81,6 +86,7 @@ def is_gen_callable(call: Callable[..., Any]) -> bool: def is_async_gen_callable(call: Callable[..., Any]) -> bool: + """检查 call 是否是一个异步生成器函数""" if inspect.isasyncgenfunction(call): return True func_ = getattr(call, "__call__", None) @@ -88,8 +94,7 @@ def is_async_gen_callable(call: Callable[..., Any]) -> bool: def run_sync(call: Callable[P, R]) -> Callable[P, Awaitable[R]]: - """ - 一个用于包装 sync function 为 async function 的装饰器 + """一个用于包装 sync function 为 async function 的装饰器 参数: call: 被装饰的同步函数 @@ -109,6 +114,7 @@ def run_sync(call: Callable[P, R]) -> Callable[P, Awaitable[R]]: async def run_sync_ctx_manager( cm: ContextManager[T], ) -> AsyncGenerator[T, None]: + """一个用于包装 sync context manager 为 async context manager 的执行函数""" try: yield await run_sync(cm.__enter__)() except Exception as e: @@ -120,15 +126,14 @@ async def run_sync_ctx_manager( def get_name(obj: Any) -> str: + """获取对象的名称""" if inspect.isfunction(obj) or inspect.isclass(obj): return obj.__name__ return obj.__class__.__name__ class DataclassEncoder(json.JSONEncoder): - """ - 在JSON序列化 `Message` (List[Dataclass]) 时使用的 `JSONEncoder` - """ + """在JSON序列化 {re}`nonebot.adapters._message.Message` (List[Dataclass]) 时使用的 `JSONEncoder`""" @overrides(json.JSONEncoder) def default(self, o): @@ -137,14 +142,18 @@ class DataclassEncoder(json.JSONEncoder): return super().default(o) -def logger_wrapper(logger_name: str): - """ - 用于打印 adapter 的日志。 +def logger_wrapper(logger_name: str) -> Callable[[str, str, Optional[Exception]], None]: + """用于打印 adapter 的日志。 参数: - level: 日志等级 - message: 日志信息 - exception: 异常信息 + logger_name: adapter 的名称 + + 返回: + 日志记录函数 + + - level: 日志等级 + - message: 日志信息 + - exception: 异常信息 """ def log(level: str, message: str, exception: Optional[Exception] = None): diff --git a/poetry.lock b/poetry.lock index b896f412..283d991e 100644 --- a/poetry.lock +++ b/poetry.lock @@ -562,7 +562,7 @@ six = ">=1.6.1" type = "git" url = "https://github.com/nonebot/nb-autodoc.git" reference = "master" -resolved_reference = "aeef9c61e6561baa12ead377554eda8edbcd5a9d" +resolved_reference = "35bcf0e5c41aa59aa923e201b3935ea96afc6273" [[package]] name = "nodeenv" @@ -642,7 +642,7 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "pre-commit" -version = "2.16.0" +version = "2.17.0" description = "A framework for managing and maintaining multi-language pre-commit hooks." category = "dev" optional = false @@ -1759,8 +1759,8 @@ pluggy = [ {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, ] pre-commit = [ - {file = "pre_commit-2.16.0-py2.py3-none-any.whl", hash = "sha256:758d1dc9b62c2ed8881585c254976d66eae0889919ab9b859064fc2fe3c7743e"}, - {file = "pre_commit-2.16.0.tar.gz", hash = "sha256:fe9897cac830aa7164dbd02a4e7b90cae49630451ce88464bca73db486ba9f65"}, + {file = "pre_commit-2.17.0-py2.py3-none-any.whl", hash = "sha256:725fa7459782d7bec5ead072810e47351de01709be838c2ce1726b9591dad616"}, + {file = "pre_commit-2.17.0.tar.gz", hash = "sha256:c1a8040ff15ad3d648c70cc3e55b93e4d2d5b687320955505587fd79bbaed06a"}, ] priority = [ {file = "priority-2.0.0-py3-none-any.whl", hash = "sha256:6f8eefce5f3ad59baf2c080a664037bb4725cd0a790d53d59ab4059288faf6aa"},