💡 add docstrings

This commit is contained in:
yanyongyu 2022-01-19 16:16:56 +08:00
parent 4701537a48
commit 98ef09585a
7 changed files with 297 additions and 162 deletions

View File

@ -245,6 +245,8 @@ class Matcher(metaclass=MatcherMeta):
参数: 参数:
bot: Bot 对象 bot: Bot 对象
event: 上报事件 event: 上报事件
stack: 异步上下文栈
dependency_cache: 依赖缓存
返回: 返回:
是否满足权限 是否满足权限
@ -269,6 +271,8 @@ class Matcher(metaclass=MatcherMeta):
bot: Bot 对象 bot: Bot 对象
event: 上报事件 event: 上报事件
state: 当前状态 state: 当前状态
stack: 异步上下文栈
dependency_cache: 依赖缓存
返回: 返回:
是否满足匹配规则 是否满足匹配规则

View File

@ -1,4 +1,5 @@
""" """本模块定义了依赖注入的各类参数。
FrontMatter: FrontMatter:
sidebar_position: 4 sidebar_position: 4
description: nonebot.params 模块 description: nonebot.params 模块
@ -61,8 +62,7 @@ def Depends(
*, *,
use_cache: bool = True, use_cache: bool = True,
) -> Any: ) -> Any:
""" """子依赖装饰器
参数依赖注入装饰器
参数: 参数:
dependency: 依赖函数默认为参数的类型注释 dependency: 依赖函数默认为参数的类型注释
@ -87,6 +87,8 @@ def Depends(
class DependParam(Param): class DependParam(Param):
"""子依赖参数"""
@classmethod @classmethod
def _check_param( def _check_param(
cls, cls,
@ -182,6 +184,8 @@ class _BotChecker(Param):
class BotParam(Param): class BotParam(Param):
"""{ref}`nonebot.adapters._bot.Bot` 参数"""
@classmethod @classmethod
def _check_param( def _check_param(
cls, dependent: Dependent, name: str, param: inspect.Parameter cls, dependent: Dependent, name: str, param: inspect.Parameter
@ -223,6 +227,8 @@ class _EventChecker(Param):
class EventParam(Param): class EventParam(Param):
"""{ref}`nonebot.adapters._event.Event` 参数"""
@classmethod @classmethod
def _check_param( def _check_param(
cls, dependent: Dependent, name: str, param: inspect.Parameter cls, dependent: Dependent, name: str, param: inspect.Parameter
@ -256,6 +262,7 @@ async def _event_type(event: Event) -> str:
def EventType() -> str: def EventType() -> str:
"""{ref}`nonebot.adapters._event.Event` 类型参数"""
return Depends(_event_type) return Depends(_event_type)
@ -264,6 +271,7 @@ async def _event_message(event: Event) -> Message:
def EventMessage() -> Any: def EventMessage() -> Any:
"""{ref}`nonebot.adapters._event.Event` 消息参数"""
return Depends(_event_message) return Depends(_event_message)
@ -272,6 +280,7 @@ async def _event_plain_text(event: Event) -> str:
def EventPlainText() -> str: def EventPlainText() -> str:
"""{ref}`nonebot.adapters._event.Event` 纯文本消息参数"""
return Depends(_event_plain_text) return Depends(_event_plain_text)
@ -280,6 +289,7 @@ async def _event_to_me(event: Event) -> bool:
def EventToMe() -> bool: def EventToMe() -> bool:
"""{ref}`nonebot.adapters._event.Event` `to_me` 参数"""
return Depends(_event_to_me) return Depends(_event_to_me)
@ -288,11 +298,14 @@ class StateInner(T_State):
def State() -> 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() return StateInner()
class StateParam(Param): class StateParam(Param):
"""事件处理状态参数"""
@classmethod @classmethod
def _check_param( def _check_param(
cls, dependent: Dependent, name: str, param: inspect.Parameter cls, dependent: Dependent, name: str, param: inspect.Parameter
@ -314,7 +327,8 @@ def _command(state: T_State) -> Message:
def Command() -> Tuple[str, ...]: def Command() -> Tuple[str, ...]:
return Depends(_command, use_cache=False) """消息命令元组"""
return Depends(_command)
def _raw_command(state: T_State) -> Message: def _raw_command(state: T_State) -> Message:
@ -322,7 +336,8 @@ def _raw_command(state: T_State) -> Message:
def RawCommand() -> str: def RawCommand() -> str:
return Depends(_raw_command, use_cache=False) """消息命令文本"""
return Depends(_raw_command)
def _command_arg(state: T_State) -> Message: def _command_arg(state: T_State) -> Message:
@ -330,7 +345,8 @@ def _command_arg(state: T_State) -> Message:
def CommandArg() -> Any: def CommandArg() -> Any:
return Depends(_command_arg, use_cache=False) """消息命令参数"""
return Depends(_command_arg)
def _shell_command_args(state: T_State) -> Any: def _shell_command_args(state: T_State) -> Any:
@ -338,6 +354,7 @@ def _shell_command_args(state: T_State) -> Any:
def ShellCommandArgs(): def ShellCommandArgs():
"""shell 命令解析后的参数字典"""
return Depends(_shell_command_args, use_cache=False) return Depends(_shell_command_args, use_cache=False)
@ -346,6 +363,7 @@ def _shell_command_argv(state: T_State) -> List[str]:
def ShellCommandArgv() -> Any: def ShellCommandArgv() -> Any:
"""shell 命令原始参数列表"""
return Depends(_shell_command_argv, use_cache=False) return Depends(_shell_command_argv, use_cache=False)
@ -354,6 +372,7 @@ def _regex_matched(state: T_State) -> str:
def RegexMatched() -> str: def RegexMatched() -> str:
"""正则匹配结果"""
return Depends(_regex_matched, use_cache=False) return Depends(_regex_matched, use_cache=False)
@ -362,6 +381,7 @@ def _regex_group(state: T_State):
def RegexGroup() -> Tuple[Any, ...]: def RegexGroup() -> Tuple[Any, ...]:
"""正则匹配结果 group 元组"""
return Depends(_regex_group, use_cache=False) return Depends(_regex_group, use_cache=False)
@ -370,10 +390,13 @@ def _regex_dict(state: T_State):
def RegexDict() -> Dict[str, Any]: def RegexDict() -> Dict[str, Any]:
"""正则匹配结果 group 字典"""
return Depends(_regex_dict, use_cache=False) return Depends(_regex_dict, use_cache=False)
class MatcherParam(Param): class MatcherParam(Param):
"""事件响应器实例参数"""
@classmethod @classmethod
def _check_param( def _check_param(
cls, dependent: Dependent, name: str, param: inspect.Parameter 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: def Received(id: Optional[str] = None, default: Any = None) -> Any:
"""`receive` 事件参数"""
def _received(matcher: "Matcher"): def _received(matcher: "Matcher"):
return matcher.get_receive(id or "", default) 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: def LastReceived(default: Any = None) -> Any:
"""`last_receive` 事件参数"""
def _last_received(matcher: "Matcher") -> Any: def _last_received(matcher: "Matcher") -> Any:
return matcher.get_last_receive(default) return matcher.get_last_receive(default)
@ -410,18 +437,23 @@ class ArgInner:
def Arg(key: Optional[str] = None) -> Any: def Arg(key: Optional[str] = None) -> Any:
"""`got` 的 Arg 参数消息"""
return ArgInner(key, "message") return ArgInner(key, "message")
def ArgStr(key: Optional[str] = None) -> str: def ArgStr(key: Optional[str] = None) -> str:
"""`got` 的 Arg 参数消息文本"""
return ArgInner(key, "str") # type: ignore return ArgInner(key, "str") # type: ignore
def ArgPlainText(key: Optional[str] = None) -> str: def ArgPlainText(key: Optional[str] = None) -> str:
"""`got` 的 Arg 参数消息纯文本"""
return ArgInner(key, "plaintext") # type: ignore return ArgInner(key, "plaintext") # type: ignore
class ArgParam(Param): class ArgParam(Param):
"""`got` 的 Arg 参数"""
@classmethod @classmethod
def _check_param( def _check_param(
cls, dependent: Dependent, name: str, param: inspect.Parameter cls, dependent: Dependent, name: str, param: inspect.Parameter
@ -442,6 +474,8 @@ class ArgParam(Param):
class ExceptionParam(Param): class ExceptionParam(Param):
"""`run_postprocessor` 的异常参数"""
@classmethod @classmethod
def _check_param( def _check_param(
cls, dependent: Dependent, name: str, param: inspect.Parameter cls, dependent: Dependent, name: str, param: inspect.Parameter
@ -456,6 +490,8 @@ class ExceptionParam(Param):
class DefaultParam(Param): class DefaultParam(Param):
"""默认值参数"""
@classmethod @classmethod
def _check_param( def _check_param(
cls, dependent: Dependent, name: str, param: inspect.Parameter cls, dependent: Dependent, name: str, param: inspect.Parameter
@ -468,3 +504,9 @@ class DefaultParam(Param):
from nonebot.matcher import Matcher from nonebot.matcher import Matcher
__autodoc__ = {
"DependsInner": False,
"StateInner": False,
"ArgInner": False,
}

View File

@ -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: FrontMatter:
sidebar_position: 6 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.adapters import Bot, Event
from nonebot.dependencies import Dependent from nonebot.dependencies import Dependent
from nonebot.exception import SkippedException 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 ( from nonebot.params import (
BotParam, BotParam,
EventType, EventType,
@ -33,15 +33,18 @@ async def _run_coro_with_catch(coro: Coroutine[Any, Any, Any]):
class Permission: class Permission:
""" """{ref}`nonebot.matcher.Matcher` 权限类。
`Matcher` 规则类当事件传递时 `Matcher` 运行前进行检查
当事件传递时 {ref}`nonebot.matcher.Matcher` 运行前进行检查
参数:
checkers: PermissionChecker
用法: 用法:
```python ```python
Permission(async_function) | sync_function Permission(async_function) | sync_function
# 等价于 # 等价于
from nonebot.utils import run_sync Permission(async_function, sync_function)
Permission(async_function, run_sync(sync_function))
``` ```
""" """
@ -55,11 +58,6 @@ class Permission:
] ]
def __init__(self, *checkers: Union[T_PermissionChecker, Dependent[bool]]) -> None: def __init__(self, *checkers: Union[T_PermissionChecker, Dependent[bool]]) -> None:
"""
参数:
*checkers: PermissionChecker
"""
self.checkers: Set[Dependent[bool]] = set( self.checkers: Set[Dependent[bool]] = set(
checker checker
if isinstance(checker, Dependent) if isinstance(checker, Dependent)
@ -68,9 +66,7 @@ class Permission:
) )
for checker in checkers for checker in checkers
) )
""" """存储 `PermissionChecker`"""
存储 `PermissionChecker`
"""
async def __call__( async def __call__(
self, self,
@ -79,8 +75,7 @@ class Permission:
stack: Optional[AsyncExitStack] = None, stack: Optional[AsyncExitStack] = None,
dependency_cache: Optional[T_DependencyCache] = None, dependency_cache: Optional[T_DependencyCache] = None,
) -> bool: ) -> bool:
""" """检查是否满足某个权限
检查是否满足某个权限
参数: 参数:
bot: Bot 对象 bot: Bot 对象
@ -120,44 +115,73 @@ class Permission:
class Message: class Message:
"""检查是否为消息事件"""
__slots__ = ()
async def __call__(self, type: str = EventType()) -> bool: async def __call__(self, type: str = EventType()) -> bool:
return type == "message" return type == "message"
class Notice: class Notice:
"""检查是否为通知事件"""
__slots__ = ()
async def __call__(self, type: str = EventType()) -> bool: async def __call__(self, type: str = EventType()) -> bool:
return type == "notice" return type == "notice"
class Request: class Request:
"""检查是否为请求事件"""
__slots__ = ()
async def __call__(self, type: str = EventType()) -> bool: async def __call__(self, type: str = EventType()) -> bool:
return type == "request" return type == "request"
class MetaEvent: class MetaEvent:
"""检查是否为元事件"""
__slots__ = ()
async def __call__(self, type: str = EventType()) -> bool: async def __call__(self, type: str = EventType()) -> bool:
return type == "meta_event" 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 METAEVENT: Permission = Permission(MetaEvent())
""" """匹配任意 `meta_event` 类型事件
REQUEST = Permission(Request())
""" 仅在需要同时捕获不同类型事件时使用优先使用 meta_event type Matcher
匹配任意 `request` 类型事件仅在需要同时捕获不同类型事件时使用优先使用 request type Matcher
"""
METAEVENT = Permission(MetaEvent())
"""
匹配任意 `meta_event` 类型事件仅在需要同时捕获不同类型事件时使用优先使用 meta_event type Matcher
""" """
class User: class User:
"""检查当前事件是否属于指定会话
参数:
users: 会话 ID 元组
perm: 需同时满足的权限
"""
__slots__ = ("users", "perm")
def __init__( def __init__(
self, users: Tuple[str, ...], perm: Optional[Permission] = None self, users: Tuple[str, ...], perm: Optional[Permission] = None
) -> None: ) -> None:
@ -172,11 +196,10 @@ class User:
def USER(*users: str, perm: Optional[Permission] = None): def USER(*users: str, perm: Optional[Permission] = None):
""" """匹配当前事件属于指定会话
`event` `session_id` 在白名单内且满足 perm
参数: 参数:
*user: 白名单 user: 会话白名单
perm: 需要同时满足的权限 perm: 需要同时满足的权限
""" """
@ -184,6 +207,10 @@ def USER(*users: str, perm: Optional[Permission] = None):
class SuperUser: class SuperUser:
"""检查当前事件是否是消息事件且属于超级管理员"""
__slots__ = ()
async def __call__(self, bot: Bot, event: Event) -> bool: async def __call__(self, bot: Bot, event: Event) -> bool:
return event.get_type() == "message" and ( return event.get_type() == "message" and (
f"{bot.adapter.get_name().split(maxsplit=1)[0].lower()}:{event.get_user_id()}" 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}

View File

@ -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: FrontMatter:
sidebar_position: 5 sidebar_position: 5
@ -42,6 +42,7 @@ from nonebot.params import (
BotParam, BotParam,
EventToMe, EventToMe,
EventType, EventType,
CommandArg,
EventParam, EventParam,
StateParam, StateParam,
DependParam, DependParam,
@ -61,15 +62,18 @@ CMD_RESULT = TypedDict(
class Rule: class Rule:
""" """{ref}`nonebot.matcher.Matcher` 规则类。
`Matcher` 规则类当事件传递时 `Matcher` 运行前进行检查
当事件传递时 {ref}`nonebot.matcher.Matcher` 运行前进行检查
参数:
*checkers: RuleChecker
用法: 用法:
```python ```python
Rule(async_function) & sync_function Rule(async_function) & sync_function
# 等价于 # 等价于
from nonebot.utils import run_sync Rule(async_function, sync_function)
Rule(async_function, run_sync(sync_function))
``` ```
""" """
@ -84,11 +88,6 @@ class Rule:
] ]
def __init__(self, *checkers: Union[T_RuleChecker, Dependent[bool]]) -> None: def __init__(self, *checkers: Union[T_RuleChecker, Dependent[bool]]) -> None:
"""
参数:
*checkers: RuleChecker
"""
self.checkers: Set[Dependent[bool]] = set( self.checkers: Set[Dependent[bool]] = set(
checker checker
if isinstance(checker, Dependent) if isinstance(checker, Dependent)
@ -97,9 +96,7 @@ class Rule:
) )
for checker in checkers for checker in checkers
) )
""" """存储 `RuleChecker`"""
存储 `RuleChecker`
"""
async def __call__( async def __call__(
self, self,
@ -109,8 +106,7 @@ class Rule:
stack: Optional[AsyncExitStack] = None, stack: Optional[AsyncExitStack] = None,
dependency_cache: Optional[T_DependencyCache] = None, dependency_cache: Optional[T_DependencyCache] = None,
) -> bool: ) -> bool:
""" """检查是否符合所有规则
检查是否符合所有规则
参数: 参数:
bot: Bot 对象 bot: Bot 对象
@ -186,6 +182,15 @@ class TrieRule:
class StartswithRule: class StartswithRule:
"""检查消息纯文本是否以指定字符串开头。
参数:
msg: 指定消息开头字符串元组
ignorecase: 是否忽略大小写
"""
__slots__ = ("msg", "ignorecase")
def __init__(self, msg: Tuple[str, ...], ignorecase: bool = False): def __init__(self, msg: Tuple[str, ...], ignorecase: bool = False):
self.msg = msg self.msg = msg
self.ignorecase = ignorecase self.ignorecase = ignorecase
@ -205,11 +210,11 @@ class StartswithRule:
def startswith(msg: Union[str, Tuple[str, ...]], ignorecase: bool = False) -> Rule: def startswith(msg: Union[str, Tuple[str, ...]], ignorecase: bool = False) -> Rule:
""" """匹配消息纯文本开头。
匹配消息开头
参数: 参数:
msg: 消息开头字符串 msg: 指定消息开头字符串元组
ignorecase: 是否忽略大小写
""" """
if isinstance(msg, str): if isinstance(msg, str):
msg = (msg,) msg = (msg,)
@ -218,6 +223,15 @@ def startswith(msg: Union[str, Tuple[str, ...]], ignorecase: bool = False) -> Ru
class EndswithRule: class EndswithRule:
"""检查消息纯文本是否以指定字符串结尾。
参数:
msg: 指定消息结尾字符串元组
ignorecase: 是否忽略大小写
"""
__slots__ = ("msg", "ignorecase")
def __init__(self, msg: Tuple[str, ...], ignorecase: bool = False): def __init__(self, msg: Tuple[str, ...], ignorecase: bool = False):
self.msg = msg self.msg = msg
self.ignorecase = ignorecase self.ignorecase = ignorecase
@ -237,11 +251,11 @@ class EndswithRule:
def endswith(msg: Union[str, Tuple[str, ...]], ignorecase: bool = False) -> Rule: def endswith(msg: Union[str, Tuple[str, ...]], ignorecase: bool = False) -> Rule:
""" """匹配消息纯文本结尾。
匹配消息结尾
参数: 参数:
msg: 消息结尾字符串 msg: 指定消息开头字符串元组
ignorecase: 是否忽略大小写
""" """
if isinstance(msg, str): if isinstance(msg, str):
msg = (msg,) msg = (msg,)
@ -250,6 +264,14 @@ def endswith(msg: Union[str, Tuple[str, ...]], ignorecase: bool = False) -> Rule
class KeywordsRule: class KeywordsRule:
"""检查消息纯文本是否包含指定关键字。
参数:
keywords: 指定关键字元组
"""
__slots__ = ("keywords",)
def __init__(self, *keywords: str): def __init__(self, *keywords: str):
self.keywords = keywords self.keywords = keywords
@ -262,17 +284,24 @@ class KeywordsRule:
def keyword(*keywords: str) -> Rule: def keyword(*keywords: str) -> Rule:
""" """匹配消息纯文本关键词。
匹配消息关键词
参数: 参数:
*keywords: 关键词 keywords: 指定关键字元组
""" """
return Rule(KeywordsRule(*keywords)) return Rule(KeywordsRule(*keywords))
class CommandRule: class CommandRule:
"""检查消息是否为指定命令。
参数:
cmds: 指定命令元组列表
"""
__slots__ = ("cmds",)
def __init__(self, cmds: List[Tuple[str, ...]]): def __init__(self, cmds: List[Tuple[str, ...]]):
self.cmds = cmds self.cmds = cmds
@ -284,22 +313,26 @@ class CommandRule:
def command(*cmds: Union[str, Tuple[str, ...]]) -> Rule: def command(*cmds: Union[str, Tuple[str, ...]]) -> Rule:
""" """匹配消息命令。
命令形式匹配根据配置里提供的 `command_start`, `command_sep` 判断消息是否为命令
可以通过 `state["_prefix"]["command"]` 获取匹配成功的命令`("test",)`通过 `state["_prefix"]["raw_command"]` 获取匹配成功的原始命令文本`"/test"` 根据配置里提供的 {ref}``command_start` <nonebot.config.Config.command_start>`,
{ref}``command_sep` <nonebot.config.Config.command_sep>` 判断消息是否为命令
可以通过 {ref}`nonebot.params.Command` 获取匹配成功的命令: `("test",)`
通过 {ref}`nonebot.params.RawCommand` 获取匹配成功的原始命令文本: `"/test"`
通过 {ref}`nonebot.params.CommandArg` 获取匹配成功的命令参数
参数: 参数:
*cmds: 命令内容 cmds: 命令文本或命令元组
用法: 用法:
使用默认 `command_start`, `command_sep` 配置 使用默认 `command_start`, `command_sep` 配置
命令 `("test",)` 可以匹配`/test` 开头的消息 命令 `("test",)` 可以匹配: `/test` 开头的消息
命令 `("test", "sub")` 可以匹配`/test.sub` 开头的消息 命令 `("test", "sub")` 可以匹配: `/test.sub` 开头的消息
:::tip 提示 :::tip 提示
命令内容与后续消息间无需空格 命令内容与后续消息间无需空格!
::: :::
""" """
@ -324,8 +357,11 @@ def command(*cmds: Union[str, Tuple[str, ...]]) -> Rule:
class ArgumentParser(ArgParser): 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): def _print_message(self, message, file=None):
@ -350,6 +386,15 @@ class ArgumentParser(ArgParser):
class ShellCommandRule: class ShellCommandRule:
"""检查消息是否为指定 shell 命令。
参数:
cmds: 指定命令元组列表
parser: 可选参数解析器
"""
__slots__ = ("cmds", "parser")
def __init__(self, cmds: List[Tuple[str, ...]], parser: Optional[ArgumentParser]): def __init__(self, cmds: List[Tuple[str, ...]], parser: Optional[ArgumentParser]):
self.cmds = cmds self.cmds = cmds
self.parser = parser self.parser = parser
@ -358,12 +403,11 @@ class ShellCommandRule:
self, self,
state: T_State, state: T_State,
cmd: Optional[Tuple[str, ...]] = Command(), cmd: Optional[Tuple[str, ...]] = Command(),
msg: Message = EventMessage(), msg: Optional[Message] = CommandArg(),
) -> bool: ) -> bool:
if cmd in self.cmds: if cmd in self.cmds and msg is not None:
message = str(msg) message = str(msg)
strip_message = message[len(state[PREFIX_KEY][RAW_CMD_KEY]) :].lstrip() state[SHELL_ARGV] = shlex.split(message)
state[SHELL_ARGV] = shlex.split(strip_message)
if self.parser: if self.parser:
try: try:
args = self.parser.parse_args(state[SHELL_ARGV]) args = self.parser.parse_args(state[SHELL_ARGV])
@ -378,18 +422,24 @@ class ShellCommandRule:
def shell_command( def shell_command(
*cmds: Union[str, Tuple[str, ...]], parser: Optional[ArgumentParser] = None *cmds: Union[str, Tuple[str, ...]], parser: Optional[ArgumentParser] = None
) -> Rule: ) -> Rule:
""" """匹配 `shell_like` 形式的消息命令。
支持 `shell_like` 解析参数的命令形式匹配根据配置里提供的 `command_start`, `command_sep` 判断消息是否为命令
可以通过 `state["_prefix"]["command"]` 获取匹配成功的命令`("test",)`通过 `state["_prefix"]["raw_command"]` 获取匹配成功的原始命令文本`"/test"` 根据配置里提供的 {ref}``command_start` <nonebot.config.Config.command_start>`,
{ref}``command_sep` <nonebot.config.Config.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: 命令内容 cmds: 命令文本或命令元组
parser: `nonebot.rule.ArgumentParser` 对象 parser: {ref}`nonebot.rule.ArgumentParser` 对象
用法: 用法:
使用默认 `command_start`, `command_sep` 配置更多示例参考 `argparse` 标准库文档 使用默认 `command_start`, `command_sep` 配置更多示例参考 `argparse` 标准库文档
@ -404,7 +454,7 @@ def shell_command(
``` ```
:::tip 提示 :::tip 提示
命令内容与后续消息间无需空格 命令内容与后续消息间无需空格!
::: :::
""" """
if parser is not None and not isinstance(parser, ArgumentParser): if parser is not None and not isinstance(parser, ArgumentParser):
@ -431,6 +481,15 @@ def shell_command(
class RegexRule: class RegexRule:
"""检查消息字符串是否符合指定正则表达式。
参数:
regex: 正则表达式
flags: 正则表达式标记
"""
__slots__ = ("regex", "flags")
def __init__(self, regex: str, flags: int = 0): def __init__(self, regex: str, flags: int = 0):
self.regex = regex self.regex = regex
self.flags = flags self.flags = flags
@ -454,32 +513,46 @@ class RegexRule:
def regex(regex: str, flags: Union[int, re.RegexFlag] = 0) -> Rule: 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: 正则表达式 regex: 正则表达式
flags: 正则标志 flags: 正则表达式标记
:::tip 提示 :::tip 提示
正则表达式匹配使用 search 而非 match如需从头匹配请使用 `r"^xxx"` 来确保匹配开头 正则表达式匹配使用 search 而非 match如需从头匹配请使用 `r"^xxx"` 来确保匹配开头
::: :::
:::tip 提示
正则表达式匹配使用 `EventMessage` `str` 字符串而非 `EventMessage` `PlainText` 纯文本字符串
:::
""" """
return Rule(RegexRule(regex, flags)) return Rule(RegexRule(regex, flags))
class ToMeRule: class ToMeRule:
"""检查事件是否与机器人有关。"""
__slots__ = ()
async def __call__(self, to_me: bool = EventToMe()) -> bool: async def __call__(self, to_me: bool = EventToMe()) -> bool:
return to_me return to_me
def to_me() -> Rule: def to_me() -> Rule:
""" """匹配与机器人有关的事件。"""
通过 `event.is_tome()` 判断事件是否与机器人有关
"""
return Rule(ToMeRule()) return Rule(ToMeRule())
__autodoc__ = {
"Rule.__call__": True,
"TrieRule": False,
"ArgumentParser.exit": False,
"ArgumentParser.parse_args": False,
}

View File

@ -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 内置类型的别名 除了 Python 内置的类型下面还出现了如下 NoneBot 自定类型实际上它们是 Python 内置类型的别名
以下类型均可从 nonebot.typing 模块导入
FrontMatter: FrontMatter:
sidebar_position: 11 sidebar_position: 11
description: nonebot.typing 模块 description: nonebot.typing 模块
@ -25,13 +25,15 @@ from typing import (
if TYPE_CHECKING: if TYPE_CHECKING:
from asyncio import Task from asyncio import Task
from nonebot.adapters import Bot, Event from nonebot.adapters import Bot
from nonebot.permission import Permission from nonebot.permission import Permission
T_Wrapped = TypeVar("T_Wrapped", bound=Callable) 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: def overrider(func: T_Wrapped) -> T_Wrapped:
assert func.__name__ in dir(InterfaceClass), f"Error method: {func.__name__}" assert func.__name__ in dir(InterfaceClass), f"Error method: {func.__name__}"
return func return func
@ -40,32 +42,21 @@ def overrides(InterfaceClass: object):
T_State = Dict[Any, Any] T_State = Dict[Any, Any]
""" """事件处理状态 State 类型"""
事件处理状态 State 类型
"""
T_BotConnectionHook = Callable[["Bot"], Awaitable[None]] T_BotConnectionHook = Callable[["Bot"], Awaitable[None]]
""" """Bot 连接建立时插槽函数"""
Bot 连接建立时执行的函数
"""
T_BotDisconnectionHook = Callable[["Bot"], Awaitable[None]] T_BotDisconnectionHook = Callable[["Bot"], Awaitable[None]]
""" """Bot 连接断开时插槽函数"""
Bot 连接断开时执行的函数
"""
T_CallingAPIHook = Callable[["Bot", str, Dict[str, Any]], Awaitable[None]] T_CallingAPIHook = Callable[["Bot", str, Dict[str, Any]], Awaitable[None]]
""" """`bot.call_api` 插槽函数"""
`bot.call_api` 时执行的函数
"""
T_CalledAPIHook = Callable[ T_CalledAPIHook = Callable[
["Bot", Optional[Exception], str, Dict[str, Any], Any], Awaitable[None] ["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]]] T_EventPreProcessor = Callable[..., Union[None, Awaitable[None]]]
""" """事件预处理函数 EventPreProcessor 类型
事件预处理函数 EventPreProcessor 类型
依赖参数: 依赖参数:
@ -76,8 +67,7 @@ T_EventPreProcessor = Callable[..., Union[None, Awaitable[None]]]
- DefaultParam: 带有默认值的参数 - DefaultParam: 带有默认值的参数
""" """
T_EventPostProcessor = Callable[..., Union[None, Awaitable[None]]] T_EventPostProcessor = Callable[..., Union[None, Awaitable[None]]]
""" """事件预处理函数 EventPostProcessor 类型
事件预处理函数 EventPostProcessor 类型
依赖参数: 依赖参数:
@ -88,8 +78,7 @@ T_EventPostProcessor = Callable[..., Union[None, Awaitable[None]]]
- DefaultParam: 带有默认值的参数 - DefaultParam: 带有默认值的参数
""" """
T_RunPreProcessor = Callable[..., Union[None, Awaitable[None]]] T_RunPreProcessor = Callable[..., Union[None, Awaitable[None]]]
""" """事件响应器运行前预处理函数 RunPreProcessor 类型
事件响应器运行前预处理函数 RunPreProcessor 类型
依赖参数: 依赖参数:
@ -101,8 +90,7 @@ T_RunPreProcessor = Callable[..., Union[None, Awaitable[None]]]
- DefaultParam: 带有默认值的参数 - DefaultParam: 带有默认值的参数
""" """
T_RunPostProcessor = Callable[..., Union[None, Awaitable[None]]] 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]]] T_RuleChecker = Callable[..., Union[bool, Awaitable[bool]]]
""" """RuleChecker 即判断是否响应事件的处理函数。
RuleChecker 即判断是否响应事件的处理函数
依赖参数: 依赖参数:
@ -128,8 +115,7 @@ RuleChecker 即判断是否响应事件的处理函数。
- DefaultParam: 带有默认值的参数 - DefaultParam: 带有默认值的参数
""" """
T_PermissionChecker = Callable[..., Union[bool, Awaitable[bool]]] T_PermissionChecker = Callable[..., Union[bool, Awaitable[bool]]]
""" """PermissionChecker 即判断事件是否满足权限的处理函数。
RuleChecker 即判断是否响应消息的处理函数
依赖参数: 依赖参数:
@ -140,12 +126,9 @@ RuleChecker 即判断是否响应消息的处理函数。
""" """
T_Handler = Callable[..., Any] T_Handler = Callable[..., Any]
""" """Handler 处理函数。"""
Handler 处理函数
"""
T_TypeUpdater = Callable[..., Union[str, Awaitable[str]]] 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: 带有默认值的参数 - DefaultParam: 带有默认值的参数
""" """
T_PermissionUpdater = Callable[..., Union["Permission", Awaitable["Permission"]]] 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: 带有默认值的参数 - DefaultParam: 带有默认值的参数
""" """
T_DependencyCache = Dict[Callable[..., Any], "Task[Any]"] T_DependencyCache = Dict[Callable[..., Any], "Task[Any]"]
""" """依赖缓存, 用于存储依赖函数的返回值"""
依赖缓存, 用于存储依赖函数的返回值
"""

View File

@ -1,4 +1,5 @@
""" """本模块包含了 NoneBot 的一些工具函数
FrontMatter: FrontMatter:
sidebar_position: 8 sidebar_position: 8
description: nonebot.utils 模块 description: nonebot.utils 模块
@ -36,8 +37,9 @@ V = TypeVar("V")
def escape_tag(s: str) -> str: def escape_tag(s: str) -> str:
""" """用于记录带颜色日志时转义 `<tag>` 类型特殊标签
用于记录带颜色日志时转义 `<tag>` 类型特殊标签
参考: [loguru color 标签](https://loguru.readthedocs.io/en/stable/api/logger.html#color)
参数: 参数:
s: 需要转义的字符串 s: 需要转义的字符串
@ -48,6 +50,7 @@ def escape_tag(s: str) -> str:
def generic_check_issubclass( def generic_check_issubclass(
cls: Any, class_or_tuple: Union[Type[Any], Tuple[Type[Any], ...]] cls: Any, class_or_tuple: Union[Type[Any], Tuple[Type[Any], ...]]
) -> bool: ) -> bool:
"""检查 cls 是否是 class_or_tuple 中的一个类型子类或"""
try: try:
return issubclass(cls, class_or_tuple) return issubclass(cls, class_or_tuple)
except TypeError: except TypeError:
@ -65,6 +68,7 @@ def generic_check_issubclass(
def is_coroutine_callable(call: Callable[..., Any]) -> bool: def is_coroutine_callable(call: Callable[..., Any]) -> bool:
"""检查 call 是否是一个 callable 协程函数"""
if inspect.isroutine(call): if inspect.isroutine(call):
return inspect.iscoroutinefunction(call) return inspect.iscoroutinefunction(call)
if inspect.isclass(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: def is_gen_callable(call: Callable[..., Any]) -> bool:
"""检查 call 是否是一个生成器函数"""
if inspect.isgeneratorfunction(call): if inspect.isgeneratorfunction(call):
return True return True
func_ = getattr(call, "__call__", None) 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: def is_async_gen_callable(call: Callable[..., Any]) -> bool:
"""检查 call 是否是一个异步生成器函数"""
if inspect.isasyncgenfunction(call): if inspect.isasyncgenfunction(call):
return True return True
func_ = getattr(call, "__call__", None) 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]]: def run_sync(call: Callable[P, R]) -> Callable[P, Awaitable[R]]:
""" """一个用于包装 sync function 为 async function 的装饰器
一个用于包装 sync function async function 的装饰器
参数: 参数:
call: 被装饰的同步函数 call: 被装饰的同步函数
@ -109,6 +114,7 @@ def run_sync(call: Callable[P, R]) -> Callable[P, Awaitable[R]]:
async def run_sync_ctx_manager( async def run_sync_ctx_manager(
cm: ContextManager[T], cm: ContextManager[T],
) -> AsyncGenerator[T, None]: ) -> AsyncGenerator[T, None]:
"""一个用于包装 sync context manager 为 async context manager 的执行函数"""
try: try:
yield await run_sync(cm.__enter__)() yield await run_sync(cm.__enter__)()
except Exception as e: except Exception as e:
@ -120,15 +126,14 @@ async def run_sync_ctx_manager(
def get_name(obj: Any) -> str: def get_name(obj: Any) -> str:
"""获取对象的名称"""
if inspect.isfunction(obj) or inspect.isclass(obj): if inspect.isfunction(obj) or inspect.isclass(obj):
return obj.__name__ return obj.__name__
return obj.__class__.__name__ return obj.__class__.__name__
class DataclassEncoder(json.JSONEncoder): class DataclassEncoder(json.JSONEncoder):
""" """在JSON序列化 {re}`nonebot.adapters._message.Message` (List[Dataclass]) 时使用的 `JSONEncoder`"""
在JSON序列化 `Message` (List[Dataclass]) 时使用的 `JSONEncoder`
"""
@overrides(json.JSONEncoder) @overrides(json.JSONEncoder)
def default(self, o): def default(self, o):
@ -137,14 +142,18 @@ class DataclassEncoder(json.JSONEncoder):
return super().default(o) return super().default(o)
def logger_wrapper(logger_name: str): def logger_wrapper(logger_name: str) -> Callable[[str, str, Optional[Exception]], None]:
""" """用于打印 adapter 的日志。
用于打印 adapter 的日志
参数: 参数:
level: 日志等级 logger_name: adapter 的名称
message: 日志信息
exception: 异常信息 返回:
日志记录函数
- level: 日志等级
- message: 日志信息
- exception: 异常信息
""" """
def log(level: str, message: str, exception: Optional[Exception] = None): def log(level: str, message: str, exception: Optional[Exception] = None):

8
poetry.lock generated
View File

@ -562,7 +562,7 @@ six = ">=1.6.1"
type = "git" type = "git"
url = "https://github.com/nonebot/nb-autodoc.git" url = "https://github.com/nonebot/nb-autodoc.git"
reference = "master" reference = "master"
resolved_reference = "aeef9c61e6561baa12ead377554eda8edbcd5a9d" resolved_reference = "35bcf0e5c41aa59aa923e201b3935ea96afc6273"
[[package]] [[package]]
name = "nodeenv" name = "nodeenv"
@ -642,7 +642,7 @@ testing = ["pytest", "pytest-benchmark"]
[[package]] [[package]]
name = "pre-commit" name = "pre-commit"
version = "2.16.0" version = "2.17.0"
description = "A framework for managing and maintaining multi-language pre-commit hooks." description = "A framework for managing and maintaining multi-language pre-commit hooks."
category = "dev" category = "dev"
optional = false optional = false
@ -1759,8 +1759,8 @@ pluggy = [
{file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"},
] ]
pre-commit = [ pre-commit = [
{file = "pre_commit-2.16.0-py2.py3-none-any.whl", hash = "sha256:758d1dc9b62c2ed8881585c254976d66eae0889919ab9b859064fc2fe3c7743e"}, {file = "pre_commit-2.17.0-py2.py3-none-any.whl", hash = "sha256:725fa7459782d7bec5ead072810e47351de01709be838c2ce1726b9591dad616"},
{file = "pre_commit-2.16.0.tar.gz", hash = "sha256:fe9897cac830aa7164dbd02a4e7b90cae49630451ce88464bca73db486ba9f65"}, {file = "pre_commit-2.17.0.tar.gz", hash = "sha256:c1a8040ff15ad3d648c70cc3e55b93e4d2d5b687320955505587fd79bbaed06a"},
] ]
priority = [ priority = [
{file = "priority-2.0.0-py3-none-any.whl", hash = "sha256:6f8eefce5f3ad59baf2c080a664037bb4725cd0a790d53d59ab4059288faf6aa"}, {file = "priority-2.0.0-py3-none-any.whl", hash = "sha256:6f8eefce5f3ad59baf2c080a664037bb4725cd0a790d53d59ab4059288faf6aa"},