diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 647312aa..da76a2b2 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -10,9 +10,11 @@ "settings": { "python.analysis.diagnosticMode": "workspace", "python.analysis.typeCheckingMode": "basic", + "ruff.organizeImports": false, "[python]": { "editor.defaultFormatter": "ms-python.black-formatter", "editor.codeActionsOnSave": { + "source.fixAll.ruff": true, "source.organizeImports": true } }, @@ -44,6 +46,7 @@ "ms-python.vscode-pylance", "ms-python.isort", "ms-python.black-formatter", + "charliermarsh.ruff", "EditorConfig.EditorConfig", "esbenp.prettier-vscode", "bradlc.vscode-tailwindcss" diff --git a/.github/workflows/ruff.yml b/.github/workflows/ruff.yml new file mode 100644 index 00000000..4e45cdfb --- /dev/null +++ b/.github/workflows/ruff.yml @@ -0,0 +1,21 @@ +name: Ruff Lint + +on: + push: + branches: + - master + pull_request: + paths: + - "nonebot/**" + - "packages/**" + - "tests/**" + +jobs: + ruff: + name: Ruff Lint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Run Ruff Lint + uses: chartboost/ruff-action@v1 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 10012164..9ce5420c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,11 +6,12 @@ ci: autoupdate_schedule: monthly autoupdate_commit_msg: ":arrow_up: auto update by pre-commit hooks" repos: - - repo: https://github.com/hadialqattan/pycln - rev: v2.1.5 + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.0.274 hooks: - - id: pycln - args: [--config, pyproject.toml] + - id: ruff + args: [--fix, --exit-non-zero-on-fix] + stages: [commit] - repo: https://github.com/pycqa/isort rev: 5.12.0 diff --git a/nonebot/__init__.py b/nonebot/__init__.py index b4d408c9..9946e953 100644 --- a/nonebot/__init__.py +++ b/nonebot/__init__.py @@ -24,12 +24,17 @@ - `load_all_plugins` => {ref}``load_all_plugins` ` - `load_from_json` => {ref}``load_from_json` ` - `load_from_toml` => {ref}``load_from_toml` ` -- `load_builtin_plugin` => {ref}``load_builtin_plugin` ` -- `load_builtin_plugins` => {ref}``load_builtin_plugins` ` +- `load_builtin_plugin` => + {ref}``load_builtin_plugin` ` +- `load_builtin_plugins` => + {ref}``load_builtin_plugins` ` - `get_plugin` => {ref}``get_plugin` ` -- `get_plugin_by_module_name` => {ref}``get_plugin_by_module_name` ` -- `get_loaded_plugins` => {ref}``get_loaded_plugins` ` -- `get_available_plugin_names` => {ref}``get_available_plugin_names` ` +- `get_plugin_by_module_name` => + {ref}``get_plugin_by_module_name` ` +- `get_loaded_plugins` => + {ref}``get_loaded_plugins` ` +- `get_available_plugin_names` => + {ref}``get_available_plugin_names` ` - `require` => {ref}``require` ` FrontMatter: @@ -69,7 +74,8 @@ def get_driver() -> Driver: 全局 {ref}`nonebot.drivers.Driver` 对象 异常: - ValueError: 全局 {ref}`nonebot.drivers.Driver` 对象尚未初始化 ({ref}`nonebot.init ` 尚未调用) + ValueError: 全局 {ref}`nonebot.drivers.Driver` 对象尚未初始化 + ({ref}`nonebot.init ` 尚未调用) 用法: ```python @@ -83,23 +89,33 @@ def get_driver() -> Driver: @overload def get_adapter(name: str) -> Adapter: - ... + """ + 参数: + name: 适配器名称 + + 返回: + 指定名称的 {ref}`nonebot.adapters.Adapter` 对象 + """ @overload def get_adapter(name: Type[A]) -> A: - ... + """ + 参数: + name: 适配器类型 + + 返回: + 指定类型的 {ref}`nonebot.adapters.Adapter` 对象 + """ def get_adapter(name: Union[str, Type[Adapter]]) -> Adapter: """获取已注册的 {ref}`nonebot.adapters.Adapter` 实例。 - 返回: - 指定名称或类型的 {ref}`nonebot.adapters.Adapter` 对象 - 异常: ValueError: 指定的 {ref}`nonebot.adapters.Adapter` 未注册 - ValueError: 全局 {ref}`nonebot.drivers.Driver` 对象尚未初始化 ({ref}`nonebot.init ` 尚未调用) + ValueError: 全局 {ref}`nonebot.drivers.Driver` 对象尚未初始化 + ({ref}`nonebot.init ` 尚未调用) 用法: ```python @@ -121,7 +137,8 @@ def get_adapters() -> Dict[str, Adapter]: 所有 {ref}`nonebot.adapters.Adapter` 实例字典 异常: - ValueError: 全局 {ref}`nonebot.drivers.Driver` 对象尚未初始化 ({ref}`nonebot.init ` 尚未调用) + ValueError: 全局 {ref}`nonebot.drivers.Driver` 对象尚未初始化 + ({ref}`nonebot.init ` 尚未调用) 用法: ```python @@ -139,7 +156,8 @@ def get_app() -> Any: 异常: AssertionError: 全局 Driver 对象不是 {ref}`nonebot.drivers.ReverseDriver` 类型 - ValueError: 全局 {ref}`nonebot.drivers.Driver` 对象尚未初始化 ({ref}`nonebot.init ` 尚未调用) + ValueError: 全局 {ref}`nonebot.drivers.Driver` 对象尚未初始化 + ({ref}`nonebot.init ` 尚未调用) 用法: ```python @@ -154,14 +172,16 @@ def get_app() -> Any: def get_asgi() -> Any: - """获取全局 {ref}`nonebot.drivers.ReverseDriver` 对应 [ASGI](https://asgi.readthedocs.io/) 对象。 + """获取全局 {ref}`nonebot.drivers.ReverseDriver` 对应 + [ASGI](https://asgi.readthedocs.io/) 对象。 返回: ASGI 对象 异常: AssertionError: 全局 Driver 对象不是 {ref}`nonebot.drivers.ReverseDriver` 类型 - ValueError: 全局 {ref}`nonebot.drivers.Driver` 对象尚未初始化 ({ref}`nonebot.init ` 尚未调用) + ValueError: 全局 {ref}`nonebot.drivers.Driver` 对象尚未初始化 + ({ref}`nonebot.init ` 尚未调用) 用法: ```python @@ -182,7 +202,8 @@ def get_bot(self_id: Optional[str] = None) -> Bot: 当不提供时,返回一个 {ref}`nonebot.adapters.Bot`。 参数: - self_id: 用来识别 {ref}`nonebot.adapters.Bot` 的 {ref}`nonebot.adapters.Bot.self_id` 属性 + self_id: 用来识别 {ref}`nonebot.adapters.Bot` 的 + {ref}`nonebot.adapters.Bot.self_id` 属性 返回: {ref}`nonebot.adapters.Bot` 对象 @@ -190,7 +211,8 @@ def get_bot(self_id: Optional[str] = None) -> Bot: 异常: KeyError: 对应 self_id 的 Bot 不存在 ValueError: 没有传入 self_id 且没有 Bot 可用 - ValueError: 全局 {ref}`nonebot.drivers.Driver` 对象尚未初始化 ({ref}`nonebot.init ` 尚未调用) + ValueError: 全局 {ref}`nonebot.drivers.Driver` 对象尚未初始化 + ({ref}`nonebot.init ` 尚未调用) 用法: ```python @@ -213,10 +235,12 @@ def get_bots() -> Dict[str, Bot]: """获取所有连接到 NoneBot 的 {ref}`nonebot.adapters.Bot` 对象。 返回: - 一个以 {ref}`nonebot.adapters.Bot.self_id` 为键,{ref}`nonebot.adapters.Bot` 对象为值的字典 + 一个以 {ref}`nonebot.adapters.Bot.self_id` 为键 + {ref}`nonebot.adapters.Bot` 对象为值的字典 异常: - ValueError: 全局 {ref}`nonebot.drivers.Driver` 对象尚未初始化 ({ref}`nonebot.init ` 尚未调用) + ValueError: 全局 {ref}`nonebot.drivers.Driver` 对象尚未初始化 + ({ref}`nonebot.init ` 尚未调用) 用法: ```python diff --git a/nonebot/config.py b/nonebot/config.py index ea64ff2e..b714d1d9 100644 --- a/nonebot/config.py +++ b/nonebot/config.py @@ -1,13 +1,16 @@ """本模块定义了 NoneBot 本身运行所需的配置项。 -NoneBot 使用 [`pydantic`](https://pydantic-docs.helpmanual.io/) 以及 [`python-dotenv`](https://saurabh-kumar.com/python-dotenv/) 来读取配置。 +NoneBot 使用 [`pydantic`](https://pydantic-docs.helpmanual.io/) 以及 +[`python-dotenv`](https://saurabh-kumar.com/python-dotenv/) 来读取配置。 -配置项需符合特殊格式或 json 序列化格式。详情见 [`pydantic Field Type`](https://pydantic-docs.helpmanual.io/usage/types/) 文档。 +配置项需符合特殊格式或 json 序列化格式 +详情见 [`pydantic Field Type`](https://pydantic-docs.helpmanual.io/usage/types/) 文档。 FrontMatter: sidebar_position: 1 description: nonebot.config 模块 """ + import os from datetime import timedelta from ipaddress import IPv4Address @@ -28,9 +31,8 @@ from nonebot.log import logger class CustomEnvSettings(EnvSettingsSource): def __call__(self, settings: BaseSettings) -> Dict[str, Any]: - """ - Build environment variables suitable for passing to the Model. - """ + """从环境变量和 dotenv 配置文件中读取配置项。""" + d: Dict[str, Any] = {} if settings.__config__.case_sensitive: @@ -56,7 +58,8 @@ class CustomEnvSettings(EnvSettingsSource): if env_val_built := self.explode_env_vars(field, env_vars): d[field.alias] = env_val_built else: - # field is complex and there's a value, decode that as JSON, then add explode_env_vars + # field is complex and there's a value + # decode that as JSON, then add explode_env_vars try: env_val = settings.__config__.parse_env_var(field.name, env_val) except ValueError as e: @@ -72,7 +75,8 @@ class CustomEnvSettings(EnvSettingsSource): else: d[field.alias] = env_val elif env_val is not None: - # simplest case, field is not complex, we only need to add the value if it was found + # simplest case, field is not complex + # we only need to add the value if it was found d[field.alias] = env_val # remain user custom config @@ -82,7 +86,7 @@ class CustomEnvSettings(EnvSettingsSource): # there's a value, decode that as JSON try: env_val = settings.__config__.parse_env_var(env_name, val_striped) - except ValueError as e: + except ValueError: logger.trace( "Error while parsing JSON for " f"{env_name!r}={val_striped!r}. " @@ -139,7 +143,7 @@ class BaseConfig(BaseSettings): class Env(BaseConfig): """运行环境配置。大小写不敏感。 - 将会从 `环境变量` > `.env 环境配置文件` 的优先级读取环境信息。 + 将会从 **环境变量** > **dotenv 配置文件** 的优先级读取环境信息。 """ environment: str = "prod" @@ -170,15 +174,17 @@ class Config(BaseConfig): 配置格式为 `[:][+[:]]*`。 `~` 为 `nonebot.drivers.` 的缩写。 + + 配置方法参考: [配置驱动器](https://nonebot.dev/docs/advanced/driver#%E9%85%8D%E7%BD%AE%E9%A9%B1%E5%8A%A8%E5%99%A8) """ host: IPvAnyAddress = IPv4Address("127.0.0.1") # type: ignore """NoneBot {ref}`nonebot.drivers.ReverseDriver` 服务端监听的 IP/主机名。""" port: int = Field(default=8080, ge=1, le=65535) """NoneBot {ref}`nonebot.drivers.ReverseDriver` 服务端监听的端口。""" log_level: Union[int, str] = "INFO" - """NoneBot 日志输出等级,可以为 `int` 类型等级或等级名称 + """NoneBot 日志输出等级,可以为 `int` 类型等级或等级名称。 - 参考 [`loguru 日志等级`](https://loguru.readthedocs.io/en/stable/api/logger.html#levels)。 + 参考 [记录日志](https://nonebot.dev/docs/appendices/log),[loguru 日志等级](https://loguru.readthedocs.io/en/stable/api/logger.html#levels)。 :::tip 提示 日志等级名称应为大写,如 `INFO`。 @@ -209,6 +215,8 @@ class Config(BaseConfig): command_start: Set[str] = {"/"} """命令的起始标记,用于判断一条消息是不是命令。 + 参考[命令响应规则](https://nonebot.dev/docs/advanced/matcher#command)。 + 用法: ```conf COMMAND_START=["/", ""] @@ -217,6 +225,8 @@ class Config(BaseConfig): command_sep: Set[str] = {"."} """命令的分隔标记,用于将文本形式的命令切分为元组(实际的命令名)。 + 参考[命令响应规则](https://nonebot.dev/docs/advanced/matcher#command)。 + 用法: ```conf COMMAND_SEP=["."] diff --git a/nonebot/consts.py b/nonebot/consts.py index 69c4f9a1..f64d5fc4 100644 --- a/nonebot/consts.py +++ b/nonebot/consts.py @@ -4,6 +4,7 @@ FrontMatter: sidebar_position: 9 description: nonebot.consts 模块 """ + import os import sys from typing import Literal diff --git a/nonebot/dependencies/__init__.py b/nonebot/dependencies/__init__.py index 417af13a..044837aa 100644 --- a/nonebot/dependencies/__init__.py +++ b/nonebot/dependencies/__init__.py @@ -82,8 +82,8 @@ class Dependent(Generic[R]): """ call: _DependentCallable[R] - params: Tuple[ModelField] = field(default_factory=tuple) - parameterless: Tuple[Param] = field(default_factory=tuple) + params: Tuple[ModelField, ...] = field(default_factory=tuple) + parameterless: Tuple[Param, ...] = field(default_factory=tuple) def __repr__(self) -> str: if inspect.isfunction(self.call) or inspect.isclass(self.call): @@ -129,7 +129,8 @@ class Dependent(Generic[R]): break else: raise ValueError( - f"Unknown parameter {param.name} for function {call} with type {param.annotation}" + f"Unknown parameter {param.name} " + f"for function {call} with type {param.annotation}" ) default_value = field_info.default @@ -182,7 +183,7 @@ class Dependent(Generic[R]): params = cls.parse_params(call, allow_types) parameterless_params = ( - tuple() + () if parameterless is None else cls.parse_parameterless(tuple(parameterless), allow_types) ) diff --git a/nonebot/dependencies/utils.py b/nonebot/dependencies/utils.py index 40b12451..55029c34 100644 --- a/nonebot/dependencies/utils.py +++ b/nonebot/dependencies/utils.py @@ -3,6 +3,7 @@ FrontMatter: sidebar_position: 1 description: nonebot.dependencies.utils 模块 """ + import inspect from typing import Any, Dict, TypeVar, Callable, ForwardRef @@ -17,6 +18,7 @@ V = TypeVar("V") def get_typed_signature(call: Callable[..., Any]) -> inspect.Signature: """获取可调用对象签名""" + signature = inspect.signature(call) globalns = getattr(call, "__globals__", {}) typed_params = [ @@ -33,6 +35,7 @@ def get_typed_signature(call: Callable[..., Any]) -> inspect.Signature: def get_typed_annotation(param: inspect.Parameter, globalns: Dict[str, Any]) -> Any: """获取参数的类型注解""" + annotation = param.annotation if isinstance(annotation, str): annotation = ForwardRef(annotation) @@ -47,6 +50,8 @@ def get_typed_annotation(param: inspect.Parameter, globalns: Dict[str, Any]) -> def check_field_type(field: ModelField, value: V) -> V: + """检查字段类型是否匹配""" + _, errs_ = field.validate(value, {}, loc=()) if errs_: raise TypeMisMatch(field, value) diff --git a/nonebot/drivers/_lifespan.py b/nonebot/drivers/_lifespan.py index 194986fd..d4b9f61a 100644 --- a/nonebot/drivers/_lifespan.py +++ b/nonebot/drivers/_lifespan.py @@ -1,10 +1,11 @@ +from typing_extensions import TypeAlias from typing import Any, List, Union, Callable, Awaitable, cast from nonebot.utils import run_sync, is_coroutine_callable -SYNC_LIFESPAN_FUNC = Callable[[], Any] -ASYNC_LIFESPAN_FUNC = Callable[[], Awaitable[Any]] -LIFESPAN_FUNC = Union[SYNC_LIFESPAN_FUNC, ASYNC_LIFESPAN_FUNC] +SYNC_LIFESPAN_FUNC: TypeAlias = Callable[[], Any] +ASYNC_LIFESPAN_FUNC: TypeAlias = Callable[[], Awaitable[Any]] +LIFESPAN_FUNC: TypeAlias = Union[SYNC_LIFESPAN_FUNC, ASYNC_LIFESPAN_FUNC] class Lifespan: diff --git a/nonebot/drivers/aiohttp.py b/nonebot/drivers/aiohttp.py index a4720af6..d988b658 100644 --- a/nonebot/drivers/aiohttp.py +++ b/nonebot/drivers/aiohttp.py @@ -29,7 +29,8 @@ try: import aiohttp except ModuleNotFoundError as e: # pragma: no cover raise ImportError( - "Please install aiohttp first to use this driver. `pip install nonebot2[aiohttp]`" + "Please install aiohttp first to use this driver. " + "Install with pip: `pip install nonebot2[aiohttp]`" ) from e diff --git a/nonebot/drivers/fastapi.py b/nonebot/drivers/fastapi.py index 4f7ea2a6..b0853304 100644 --- a/nonebot/drivers/fastapi.py +++ b/nonebot/drivers/fastapi.py @@ -41,7 +41,8 @@ try: from starlette.websockets import WebSocket, WebSocketState, WebSocketDisconnect except ModuleNotFoundError as e: # pragma: no cover raise ImportError( - "Please install FastAPI by using `pip install nonebot2[fastapi]`" + "Please install FastAPI first to use this driver. " + "Install with pip: `pip install nonebot2[fastapi]`" ) from e @@ -90,7 +91,7 @@ class Driver(ReverseDriver): """FastAPI 驱动框架。""" def __init__(self, env: Env, config: NoneBotConfig): - super(Driver, self).__init__(env, config) + super().__init__(env, config) self.fastapi_config: Config = Config(**config.dict()) diff --git a/nonebot/drivers/httpx.py b/nonebot/drivers/httpx.py index a0eac938..2118e509 100644 --- a/nonebot/drivers/httpx.py +++ b/nonebot/drivers/httpx.py @@ -14,6 +14,7 @@ FrontMatter: sidebar_position: 3 description: nonebot.drivers.httpx 模块 """ + from typing import Type, AsyncGenerator from contextlib import asynccontextmanager @@ -33,7 +34,8 @@ try: import httpx except ModuleNotFoundError as e: # pragma: no cover raise ImportError( - "Please install httpx by using `pip install nonebot2[httpx]`" + "Please install httpx first to use this driver. " + "Install with pip: `pip install nonebot2[httpx]`" ) from e diff --git a/nonebot/drivers/none.py b/nonebot/drivers/none.py index bc680a9f..e8e91cc6 100644 --- a/nonebot/drivers/none.py +++ b/nonebot/drivers/none.py @@ -9,7 +9,6 @@ FrontMatter: description: nonebot.drivers.none 模块 """ - import signal import asyncio import threading diff --git a/nonebot/drivers/quart.py b/nonebot/drivers/quart.py index 4c5d69cd..d7df01c0 100644 --- a/nonebot/drivers/quart.py +++ b/nonebot/drivers/quart.py @@ -39,7 +39,8 @@ try: from quart import Websocket as QuartWebSocket except ModuleNotFoundError as e: # pragma: no cover raise ImportError( - "Please install Quart by using `pip install nonebot2[quart]`" + "Please install Quart first to use this driver. " + "Install with pip: `pip install nonebot2[quart]`" ) from e _AsyncCallable = TypeVar("_AsyncCallable", bound=Callable[..., Coroutine]) @@ -188,9 +189,7 @@ class Driver(ReverseDriver): async def _handle_http(self, setup: HTTPServerSetup) -> Response: request: Request = _request - json = None - if request.is_json: - json = await request.get_json() + json = await request.get_json() if request.is_json else None data = await request.form files_dict = await request.files diff --git a/nonebot/drivers/websockets.py b/nonebot/drivers/websockets.py index 644fa063..9723aed5 100644 --- a/nonebot/drivers/websockets.py +++ b/nonebot/drivers/websockets.py @@ -14,10 +14,12 @@ FrontMatter: sidebar_position: 4 description: nonebot.drivers.websockets 模块 """ + import logging from functools import wraps +from typing_extensions import ParamSpec from contextlib import asynccontextmanager -from typing import Type, Union, AsyncGenerator +from typing import Type, Union, TypeVar, Callable, Awaitable, AsyncGenerator from nonebot.typing import overrides from nonebot.log import LoguruHandler @@ -32,16 +34,20 @@ try: from websockets.legacy.client import Connect, WebSocketClientProtocol except ModuleNotFoundError as e: # pragma: no cover raise ImportError( - "Please install websockets by using `pip install nonebot2[websockets]`" + "Please install websockets first to use this driver. " + "Install with pip: `pip install nonebot2[websockets]`" ) from e +T = TypeVar("T") +P = ParamSpec("P") + logger = logging.Logger("websockets.client", "INFO") logger.addHandler(LoguruHandler()) -def catch_closed(func): +def catch_closed(func: Callable[P, Awaitable[T]]) -> Callable[P, Awaitable[T]]: @wraps(func) - async def decorator(*args, **kwargs): + async def decorator(*args: P.args, **kwargs: P.kwargs) -> T: try: return await func(*args, **kwargs) except ConnectionClosed as e: diff --git a/nonebot/exception.py b/nonebot/exception.py index ac1c8c56..28e62815 100644 --- a/nonebot/exception.py +++ b/nonebot/exception.py @@ -43,9 +43,9 @@ class NoneBotException(Exception): # Rule Exception class ParserExit(NoneBotException): - """{ref}`nonebot.rule.shell_command` 处理消息失败时返回的异常""" + """{ref}`nonebot.rule.shell_command` 处理消息失败时返回的异常。""" - def __init__(self, status: int = 0, message: Optional[str] = None): + def __init__(self, status: int = 0, message: Optional[str] = None) -> None: self.status = status self.message = message @@ -69,7 +69,7 @@ class IgnoredException(ProcessException): reason: 忽略事件的原因 """ - def __init__(self, reason: Any): + def __init__(self, reason: Any) -> None: self.reason: Any = reason def __repr__(self) -> str: @@ -96,7 +96,7 @@ class SkippedException(ProcessException): class TypeMisMatch(SkippedException): """当前 `Handler` 的参数类型不匹配。""" - def __init__(self, param: ModelField, value: Any): + def __init__(self, param: ModelField, value: Any) -> None: self.param: ModelField = param self.value: Any = value @@ -108,7 +108,8 @@ class TypeMisMatch(SkippedException): class MockApiException(ProcessException): - """指示 NoneBot 阻止本次 API 调用或修改本次调用返回值,并返回自定义内容。可由 api hook 抛出。 + """指示 NoneBot 阻止本次 API 调用或修改本次调用返回值,并返回自定义内容。 + 可由 api hook 抛出。 参数: result: 返回的内容 @@ -144,7 +145,8 @@ class MatcherException(NoneBotException): class PausedException(MatcherException): - """指示 NoneBot 结束当前 `Handler` 并等待下一条消息后继续下一个 `Handler`。可用于用户输入新信息。 + """指示 NoneBot 结束当前 `Handler` 并等待下一条消息后继续下一个 `Handler`。 + 可用于用户输入新信息。 可以在 `Handler` 中通过 {ref}`nonebot.matcher.Matcher.pause` 抛出。 @@ -158,7 +160,8 @@ class PausedException(MatcherException): class RejectedException(MatcherException): - """指示 NoneBot 结束当前 `Handler` 并等待下一条消息后重新运行当前 `Handler`。可用于用户重新输入。 + """指示 NoneBot 结束当前 `Handler` 并等待下一条消息后重新运行当前 `Handler`。 + 可用于用户重新输入。 可以在 `Handler` 中通过 {ref}`nonebot.matcher.Matcher.reject` 抛出。 @@ -187,7 +190,7 @@ class FinishedException(MatcherException): # Adapter Exceptions class AdapterException(NoneBotException): - """代表 `Adapter` 抛出的异常,所有的 `Adapter` 都要在内部继承自这个 `Exception` + """代表 `Adapter` 抛出的异常,所有的 `Adapter` 都要在内部继承自这个 `Exception`。 参数: adapter_name: 标识 adapter @@ -210,7 +213,9 @@ class ApiNotAvailable(AdapterException): class NetworkError(AdapterException): - """在网络出现问题时抛出,如: API 请求地址不正确, API 请求无返回或返回状态非正常等。""" + """在网络出现问题时抛出, + 如: API 请求地址不正确, API 请求无返回或返回状态非正常等。 + """ class ActionFailed(AdapterException): @@ -219,13 +224,13 @@ class ActionFailed(AdapterException): # Driver Exceptions class DriverException(NoneBotException): - """`Driver` 抛出的异常基类""" + """`Driver` 抛出的异常基类。""" class WebSocketClosed(DriverException): - """WebSocket 连接已关闭""" + """WebSocket 连接已关闭。""" - def __init__(self, code: int, reason: Optional[str] = None): + def __init__(self, code: int, reason: Optional[str] = None) -> None: self.code = code self.reason = reason diff --git a/nonebot/internal/adapter/event.py b/nonebot/internal/adapter/event.py index e5a1aa6a..bef70717 100644 --- a/nonebot/internal/adapter/event.py +++ b/nonebot/internal/adapter/event.py @@ -44,10 +44,11 @@ class Event(abc.ABC, BaseModel): def get_log_string(self) -> str: """获取事件日志信息的方法。 - 通常你不需要修改这个方法,只有当希望 NoneBot 隐藏该事件日志时,可以抛出 `NoLogException` 异常。 + 通常你不需要修改这个方法,只有当希望 NoneBot 隐藏该事件日志时, + 可以抛出 `NoLogException` 异常。 异常: - NoLogException: + NoLogException: 希望 NoneBot 隐藏该事件日志 """ return f"[{self.get_event_name()}]: {self.get_event_description()}" @@ -58,7 +59,9 @@ class Event(abc.ABC, BaseModel): @abc.abstractmethod def get_session_id(self) -> str: - """获取会话 id 的方法,用于判断当前事件属于哪一个会话,通常是用户 id、群组 id 组合。""" + """获取会话 id 的方法,用于判断当前事件属于哪一个会话, + 通常是用户 id、群组 id 组合。 + """ raise NotImplementedError @abc.abstractmethod diff --git a/nonebot/internal/adapter/message.py b/nonebot/internal/adapter/message.py index 82e7fdde..36d7ccaf 100644 --- a/nonebot/internal/adapter/message.py +++ b/nonebot/internal/adapter/message.py @@ -98,7 +98,7 @@ class MessageSegment(abc.ABC, Generic[TM]): class Message(List[TMS], abc.ABC): - """消息数组 + """消息序列 参数: message: 消息内容 @@ -124,9 +124,9 @@ class Message(List[TMS], abc.ABC): def template(cls, format_string: Union[str, TM]) -> MessageTemplate[Self]: """创建消息模板。 - 用法和 `str.format` 大致相同, 但是可以输出消息对象, 并且支持以 `Message` 对象作为消息模板 - - 并且提供了拓展的格式化控制符, 可以用适用于该消息类型的 `MessageSegment` 的工厂方法创建消息 + 用法和 `str.format` 大致相同,支持以 `Message` 对象作为消息模板并输出消息对象。 + 并且提供了拓展的格式化控制符, + 可以通过该消息类型的 `MessageSegment` 工厂方法创建消息。 参数: format_string: 格式化模板 diff --git a/nonebot/internal/adapter/template.py b/nonebot/internal/adapter/template.py index f5d0d51d..f0edc32e 100644 --- a/nonebot/internal/adapter/template.py +++ b/nonebot/internal/adapter/template.py @@ -1,5 +1,6 @@ import functools from string import Formatter +from typing_extensions import TypeAlias from typing import ( TYPE_CHECKING, Any, @@ -25,7 +26,7 @@ if TYPE_CHECKING: TM = TypeVar("TM", bound="Message") TF = TypeVar("TF", str, "Message") -FormatSpecFunc = Callable[[Any], str] +FormatSpecFunc: TypeAlias = Callable[[Any], str] FormatSpecFunc_T = TypeVar("FormatSpecFunc_T", bound=FormatSpecFunc) diff --git a/nonebot/internal/driver/driver.py b/nonebot/internal/driver/driver.py index 94f9798d..a3a4818b 100644 --- a/nonebot/internal/driver/driver.py +++ b/nonebot/internal/driver/driver.py @@ -89,9 +89,7 @@ class Driver(abc.ABC): @abc.abstractmethod def run(self, *args, **kwargs): - """ - 启动驱动框架 - """ + """启动驱动框架""" logger.opt(colors=True).debug( f"Loaded adapters: {escape_tag(', '.join(self._adapters))}" ) @@ -152,8 +150,10 @@ class Driver(abc.ABC): await asyncio.gather(*coros) except Exception as e: logger.opt(colors=True, exception=e).error( - "Error when running WebSocketConnection hook. " - "Running cancelled!" + "" + "Error when running WebSocketConnection hook. " + "Running cancelled!" + "" ) asyncio.create_task(_run_hook(bot)) @@ -177,8 +177,10 @@ class Driver(abc.ABC): await asyncio.gather(*coros) except Exception as e: logger.opt(colors=True, exception=e).error( - "Error when running WebSocketDisConnection hook. " - "Running cancelled!" + "" + "Error when running WebSocketDisConnection hook. " + "Running cancelled!" + "" ) asyncio.create_task(_run_hook(bot)) @@ -241,7 +243,7 @@ def combine_driver(driver: Type[Driver], *mixins: Type[ForwardMixin]) -> Type[Dr # check first assert issubclass(driver, Driver), "`driver` must be subclass of Driver" assert all( - map(lambda m: issubclass(m, ForwardMixin), mixins) + issubclass(m, ForwardMixin) for m in mixins ), "`mixins` must be subclass of ForwardMixin" if not mixins: @@ -251,7 +253,9 @@ def combine_driver(driver: Type[Driver], *mixins: Type[ForwardMixin]) -> Type[Dr return ( driver.type.__get__(self) + "+" - + "+".join(map(lambda x: x.type.__get__(self), mixins)) + + "+".join(x.type.__get__(self) for x in mixins) ) - return type("CombinedDriver", (*mixins, driver, ForwardDriver), {"type": property(type_)}) # type: ignore + return type( + "CombinedDriver", (*mixins, driver, ForwardDriver), {"type": property(type_)} + ) # type: ignore diff --git a/nonebot/internal/driver/model.py b/nonebot/internal/driver/model.py index 104b5c6d..6324006b 100644 --- a/nonebot/internal/driver/model.py +++ b/nonebot/internal/driver/model.py @@ -2,6 +2,7 @@ import abc import urllib.request from enum import Enum from dataclasses import dataclass +from typing_extensions import TypeAlias from http.cookiejar import Cookie, CookieJar from typing import ( IO, @@ -21,28 +22,30 @@ from typing import ( from yarl import URL as URL from multidict import CIMultiDict -RawURL = Tuple[bytes, bytes, Optional[int], bytes] +RawURL: TypeAlias = Tuple[bytes, bytes, Optional[int], bytes] -SimpleQuery = Union[str, int, float] -QueryVariable = Union[SimpleQuery, List[SimpleQuery]] -QueryTypes = Union[ +SimpleQuery: TypeAlias = Union[str, int, float] +QueryVariable: TypeAlias = Union[SimpleQuery, List[SimpleQuery]] +QueryTypes: TypeAlias = Union[ None, str, Mapping[str, QueryVariable], List[Tuple[str, QueryVariable]] ] -HeaderTypes = Union[ +HeaderTypes: TypeAlias = Union[ None, CIMultiDict[str], Dict[str, str], List[Tuple[str, str]], ] -CookieTypes = Union[None, "Cookies", CookieJar, Dict[str, str], List[Tuple[str, str]]] +CookieTypes: TypeAlias = Union[ + None, "Cookies", CookieJar, Dict[str, str], List[Tuple[str, str]] +] -ContentTypes = Union[str, bytes, None] -DataTypes = Union[dict, None] -FileContent = Union[IO[bytes], bytes] -FileType = Tuple[Optional[str], FileContent, Optional[str]] -FileTypes = Union[ +ContentTypes: TypeAlias = Union[str, bytes, None] +DataTypes: TypeAlias = Union[dict, None] +FileContent: TypeAlias = Union[IO[bytes], bytes] +FileType: TypeAlias = Tuple[Optional[str], FileContent, Optional[str]] +FileTypes: TypeAlias = Union[ # file (or bytes) FileContent, # (filename, file (or bytes)) @@ -50,7 +53,7 @@ FileTypes = Union[ # (filename, file (or bytes), content_type) FileType, ] -FilesTypes = Union[Dict[str, FileTypes], List[Tuple[str, FileTypes]], None] +FilesTypes: TypeAlias = Union[Dict[str, FileTypes], List[Tuple[str, FileTypes]], None] class HTTPVersion(Enum): @@ -160,7 +163,6 @@ class Response: class WebSocket(abc.ABC): def __init__(self, *, request: Request): - # request self.request: Request = request def __repr__(self) -> str: @@ -169,9 +171,7 @@ class WebSocket(abc.ABC): @property @abc.abstractmethod def closed(self) -> bool: - """ - 连接是否已经关闭 - """ + """连接是否已经关闭""" raise NotImplementedError @abc.abstractmethod diff --git a/nonebot/internal/matcher/matcher.py b/nonebot/internal/matcher/matcher.py index f91d1a5f..3d243091 100644 --- a/nonebot/internal/matcher/matcher.py +++ b/nonebot/internal/matcher/matcher.py @@ -29,6 +29,13 @@ from nonebot.internal.adapter import ( MessageSegment, MessageTemplate, ) +from nonebot.typing import ( + T_State, + T_Handler, + T_TypeUpdater, + T_DependencyCache, + T_PermissionUpdater, +) from nonebot.consts import ( ARG_KEY, RECEIVE_KEY, @@ -36,14 +43,6 @@ from nonebot.consts import ( LAST_RECEIVE_KEY, REJECT_CACHE_TARGET, ) -from nonebot.typing import ( - Any, - T_State, - T_Handler, - T_TypeUpdater, - T_DependencyCache, - T_PermissionUpdater, -) from nonebot.exception import ( PausedException, StopPropagation, @@ -376,7 +375,7 @@ class Matcher(metaclass=MatcherMeta): return await matcher.reject() - _parameterless = (Depends(_receive), *(parameterless or tuple())) + _parameterless = (Depends(_receive), *(parameterless or ())) def _decorator(func: T_Handler) -> T_Handler: if cls.handlers and cls.handlers[-1].call is func: @@ -406,7 +405,8 @@ class Matcher(metaclass=MatcherMeta): ) -> Callable[[T_Handler], T_Handler]: """装饰一个函数来指示 NoneBot 获取一个参数 `key` - 当要获取的 `key` 不存在时接收用户新的一条消息再运行该函数,如果 `key` 已存在则直接继续运行 + 当要获取的 `key` 不存在时接收用户新的一条消息再运行该函数, + 如果 `key` 已存在则直接继续运行 参数: key: 参数名 @@ -423,7 +423,7 @@ class Matcher(metaclass=MatcherMeta): return await matcher.reject(prompt) - _parameterless = (Depends(_key_getter), *(parameterless or tuple())) + _parameterless = (Depends(_key_getter), *(parameterless or ())) def _decorator(func: T_Handler) -> T_Handler: if cls.handlers and cls.handlers[-1].call is func: @@ -454,7 +454,8 @@ class Matcher(metaclass=MatcherMeta): 参数: message: 消息内容 - kwargs: {ref}`nonebot.adapters.Bot.send` 的参数,请参考对应 adapter 的 bot 对象 api + kwargs: {ref}`nonebot.adapters.Bot.send` 的参数, + 请参考对应 adapter 的 bot 对象 api """ bot = current_bot.get() event = current_event.get() @@ -475,7 +476,8 @@ class Matcher(metaclass=MatcherMeta): 参数: message: 消息内容 - kwargs: {ref}`nonebot.adapters.Bot.send` 的参数,请参考对应 adapter 的 bot 对象 api + kwargs: {ref}`nonebot.adapters.Bot.send` 的参数, + 请参考对应 adapter 的 bot 对象 api """ if message is not None: await cls.send(message, **kwargs) @@ -491,7 +493,8 @@ class Matcher(metaclass=MatcherMeta): 参数: prompt: 消息内容 - kwargs: {ref}`nonebot.adapters.Bot.send` 的参数,请参考对应 adapter 的 bot 对象 api + kwargs: {ref}`nonebot.adapters.Bot.send` 的参数, + 请参考对应 adapter 的 bot 对象 api """ if prompt is not None: await cls.send(prompt, **kwargs) @@ -508,7 +511,8 @@ class Matcher(metaclass=MatcherMeta): 参数: prompt: 消息内容 - kwargs: {ref}`nonebot.adapters.Bot.send` 的参数,请参考对应 adapter 的 bot 对象 api + kwargs: {ref}`nonebot.adapters.Bot.send` 的参数, + 请参考对应 adapter 的 bot 对象 api """ if prompt is not None: await cls.send(prompt, **kwargs) @@ -527,7 +531,8 @@ class Matcher(metaclass=MatcherMeta): 参数: key: 参数名 prompt: 消息内容 - kwargs: {ref}`nonebot.adapters.Bot.send` 的参数,请参考对应 adapter 的 bot 对象 api + kwargs: {ref}`nonebot.adapters.Bot.send` 的参数, + 请参考对应 adapter 的 bot 对象 api """ matcher = current_matcher.get() matcher.set_target(ARG_KEY.format(key=key)) @@ -548,7 +553,8 @@ class Matcher(metaclass=MatcherMeta): 参数: id: 消息 id prompt: 消息内容 - kwargs: {ref}`nonebot.adapters.Bot.send` 的参数,请参考对应 adapter 的 bot 对象 api + kwargs: {ref}`nonebot.adapters.Bot.send` 的参数, + 请参考对应 adapter 的 bot 对象 api """ matcher = current_matcher.get() matcher.set_target(RECEIVE_KEY.format(id=id)) diff --git a/nonebot/internal/params.py b/nonebot/internal/params.py index 6012eca5..2d3885f5 100644 --- a/nonebot/internal/params.py +++ b/nonebot/internal/params.py @@ -63,7 +63,10 @@ def Depends( finally: ... - async def handler(param_name: Any = Depends(depend_func), gen: Any = Depends(depend_gen_func)): + async def handler( + param_name: Any = Depends(depend_func), + gen: Any = Depends(depend_gen_func), + ): ... ``` """ diff --git a/nonebot/log.py b/nonebot/log.py index 58a420ad..19739227 100644 --- a/nonebot/log.py +++ b/nonebot/log.py @@ -88,5 +88,6 @@ logger_id = logger.add( filter=default_filter, format=default_format, ) +"""默认日志处理器 id""" __autodoc__ = {"logger_id": False} diff --git a/nonebot/message.py b/nonebot/message.py index 9561005e..b1c18706 100644 --- a/nonebot/message.py +++ b/nonebot/message.py @@ -166,7 +166,7 @@ async def _apply_event_preprocessors( for proc in _event_preprocessors ) ) - except IgnoredException as e: + except IgnoredException: logger.opt(colors=True).info( f"Event {escape_tag(event.get_event_name())} is ignored" ) @@ -293,7 +293,7 @@ async def _apply_run_postprocessors( ) -> None: """运行事件响应器运行后处理。 - Args: + 参数: bot: Bot 对象 event: Event 对象 matcher: 事件响应器 diff --git a/nonebot/permission.py b/nonebot/permission.py index 9c4da085..69500ad1 100644 --- a/nonebot/permission.py +++ b/nonebot/permission.py @@ -1,7 +1,8 @@ """本模块是 {ref}`nonebot.matcher.Matcher.permission` 的类型定义。 -每个 {ref}`nonebot.matcher.Matcher` 拥有一个 {ref}`nonebot.permission.Permission` , -其中是 `PermissionChecker` 的集合,只要有一个 `PermissionChecker` 检查结果为 `True` 时就会继续运行。 +每个{ref}`事件响应器 ` +拥有一个 {ref}`nonebot.permission.Permission`,其中是 `PermissionChecker` 的集合。 +只要有一个 `PermissionChecker` 检查结果为 `True` 时就会继续运行。 FrontMatter: sidebar_position: 6 diff --git a/nonebot/plugin/__init__.py b/nonebot/plugin/__init__.py index fddc6896..b973d378 100644 --- a/nonebot/plugin/__init__.py +++ b/nonebot/plugin/__init__.py @@ -24,8 +24,10 @@ - `load_all_plugins` => {ref}``load_all_plugins` ` - `load_from_json` => {ref}``load_from_json` ` - `load_from_toml` => {ref}``load_from_toml` ` -- `load_builtin_plugin` => {ref}``load_builtin_plugin` ` -- `load_builtin_plugins` => {ref}``load_builtin_plugins` ` +- `load_builtin_plugin` => + {ref}``load_builtin_plugin` ` +- `load_builtin_plugins` => + {ref}``load_builtin_plugins` ` - `require` => {ref}``require` ` - `PluginMetadata` => {ref}``PluginMetadata` ` @@ -42,7 +44,7 @@ from typing import Set, Dict, List, Tuple, Optional _plugins: Dict[str, "Plugin"] = {} _managers: List["PluginManager"] = [] _current_plugin_chain: ContextVar[Tuple["Plugin", ...]] = ContextVar( - "_current_plugin_chain", default=tuple() + "_current_plugin_chain", default=() ) diff --git a/nonebot/plugin/load.py b/nonebot/plugin/load.py index 9b6c0bef..8e83b1ea 100644 --- a/nonebot/plugin/load.py +++ b/nonebot/plugin/load.py @@ -4,6 +4,7 @@ FrontMatter: sidebar_position: 1 description: nonebot.plugin.load 模块 """ + import json from pathlib import Path from types import ModuleType @@ -25,7 +26,8 @@ def load_plugin(module_path: Union[str, Path]) -> Optional[Plugin]: """加载单个插件,可以是本地插件或是通过 `pip` 安装的插件。 参数: - module_path: 插件名称 `path.to.your.plugin` 或插件路径 `pathlib.Path(path/to/your/plugin)` + module_path: 插件名称 `path.to.your.plugin` + 或插件路径 `pathlib.Path(path/to/your/plugin)` """ module_path = ( path_to_module_name(module_path) @@ -63,7 +65,8 @@ def load_all_plugins( def load_from_json(file_path: str, encoding: str = "utf-8") -> Set[Plugin]: - """导入指定 json 文件中的 `plugins` 以及 `plugin_dirs` 下多个插件,以 `_` 开头的插件不会被导入! + """导入指定 json 文件中的 `plugins` 以及 `plugin_dirs` 下多个插件。 + 以 `_` 开头的插件不会被导入! 参数: file_path: 指定 json 文件路径 @@ -81,7 +84,7 @@ def load_from_json(file_path: str, encoding: str = "utf-8") -> Set[Plugin]: nonebot.load_from_json("plugins.json") ``` """ - with open(file_path, "r", encoding=encoding) as f: + with open(file_path, encoding=encoding) as f: data = json.load(f) if not isinstance(data, dict): raise TypeError("json file must contains a dict!") @@ -93,7 +96,9 @@ def load_from_json(file_path: str, encoding: str = "utf-8") -> Set[Plugin]: def load_from_toml(file_path: str, encoding: str = "utf-8") -> Set[Plugin]: - """导入指定 toml 文件 `[tool.nonebot]` 中的 `plugins` 以及 `plugin_dirs` 下多个插件,以 `_` 开头的插件不会被导入! + """导入指定 toml 文件 `[tool.nonebot]` 中的 + `plugins` 以及 `plugin_dirs` 下多个插件。 + 以 `_` 开头的插件不会被导入! 参数: file_path: 指定 toml 文件路径 @@ -110,7 +115,7 @@ def load_from_toml(file_path: str, encoding: str = "utf-8") -> Set[Plugin]: nonebot.load_from_toml("pyproject.toml") ``` """ - with open(file_path, "r", encoding=encoding) as f: + with open(file_path, encoding=encoding) as f: data = tomllib.loads(f.read()) nonebot_data = data.get("tool", {}).get("nonebot") diff --git a/nonebot/plugin/manager.py b/nonebot/plugin/manager.py index 5f3e6b9a..8a2d99a0 100644 --- a/nonebot/plugin/manager.py +++ b/nonebot/plugin/manager.py @@ -6,6 +6,7 @@ FrontMatter: sidebar_position: 5 description: nonebot.plugin.manager 模块 """ + import sys import pkgutil import importlib diff --git a/nonebot/plugin/on.py b/nonebot/plugin/on.py index e4912b2d..84a3475f 100644 --- a/nonebot/plugin/on.py +++ b/nonebot/plugin/on.py @@ -4,6 +4,7 @@ FrontMatter: sidebar_position: 2 description: nonebot.plugin.on 模块 """ + import re import inspect from types import ModuleType @@ -322,7 +323,8 @@ def on_shell_command( 与普通的 `on_command` 不同的是,在添加 `parser` 参数时, 响应器会自动处理消息。 - 并将用户输入的原始参数列表保存在 `state["argv"]`, `parser` 处理的参数保存在 `state["args"]` 中 + 可以通过 {ref}`nonebot.params.ShellCommandArgv` 获取原始参数列表, + 通过 {ref}`nonebot.params.ShellCommandArgs` 获取解析后的参数字典。 参数: cmd: 指定命令内容 @@ -712,7 +714,8 @@ class MatcherGroup(_Group): 与普通的 `on_command` 不同的是,在添加 `parser` 参数时, 响应器会自动处理消息。 - 并将用户输入的原始参数列表保存在 `state["argv"]`, `parser` 处理的参数保存在 `state["args"]` 中 + 可以通过 {ref}`nonebot.params.ShellCommandArgv` 获取原始参数列表, + 通过 {ref}`nonebot.params.ShellCommandArgs` 获取解析后的参数字典。 参数: cmd: 指定命令内容 diff --git a/nonebot/plugin/on.pyi b/nonebot/plugin/on.pyi index 49d68c58..18e529ee 100644 --- a/nonebot/plugin/on.pyi +++ b/nonebot/plugin/on.pyi @@ -1,7 +1,6 @@ import re from types import ModuleType from datetime import datetime, timedelta -from typing import Set, List, Type, Tuple, Union, Optional from nonebot.adapters import Event from nonebot.matcher import Matcher @@ -12,399 +11,399 @@ from nonebot.typing import T_State, T_Handler, T_RuleChecker, T_PermissionChecke from .plugin import Plugin -def store_matcher(matcher: Type[Matcher]) -> None: ... -def get_matcher_plugin(depth: int = ...) -> Optional[Plugin]: ... -def get_matcher_module(depth: int = ...) -> Optional[ModuleType]: ... +def store_matcher(matcher: type[Matcher]) -> None: ... +def get_matcher_plugin(depth: int = ...) -> Plugin | None: ... +def get_matcher_module(depth: int = ...) -> ModuleType | None: ... def on( type: str = "", - rule: Optional[Union[Rule, T_RuleChecker]] = ..., - permission: Optional[Union[Permission, T_PermissionChecker]] = ..., + rule: Rule | T_RuleChecker | None = ..., + permission: Permission | T_PermissionChecker | None = ..., *, - handlers: Optional[List[Union[T_Handler, Dependent]]] = ..., + handlers: list[T_Handler | Dependent] | None = ..., temp: bool = ..., - expire_time: Optional[Union[datetime, timedelta]] = ..., + expire_time: datetime | timedelta | None = ..., priority: int = ..., block: bool = ..., - state: Optional[T_State] = ..., -) -> Type[Matcher]: ... + state: T_State | None = ..., +) -> type[Matcher]: ... def on_metaevent( - rule: Optional[Union[Rule, T_RuleChecker]] = ..., - permission: Optional[Union[Permission, T_PermissionChecker]] = ..., + rule: Rule | T_RuleChecker | None = ..., + permission: Permission | T_PermissionChecker | None = ..., *, - handlers: Optional[List[Union[T_Handler, Dependent]]] = ..., + handlers: list[T_Handler | Dependent] | None = ..., temp: bool = ..., - expire_time: Optional[Union[datetime, timedelta]] = ..., + expire_time: datetime | timedelta | None = ..., priority: int = ..., block: bool = ..., - state: Optional[T_State] = ..., -) -> Type[Matcher]: ... + state: T_State | None = ..., +) -> type[Matcher]: ... def on_message( - rule: Optional[Union[Rule, T_RuleChecker]] = ..., - permission: Optional[Union[Permission, T_PermissionChecker]] = ..., + rule: Rule | T_RuleChecker | None = ..., + permission: Permission | T_PermissionChecker | None = ..., *, - handlers: Optional[List[Union[T_Handler, Dependent]]] = ..., + handlers: list[T_Handler | Dependent] | None = ..., temp: bool = ..., - expire_time: Optional[Union[datetime, timedelta]] = ..., + expire_time: datetime | timedelta | None = ..., priority: int = ..., block: bool = ..., - state: Optional[T_State] = ..., -) -> Type[Matcher]: ... + state: T_State | None = ..., +) -> type[Matcher]: ... def on_notice( - rule: Optional[Union[Rule, T_RuleChecker]] = ..., - permission: Optional[Union[Permission, T_PermissionChecker]] = ..., + rule: Rule | T_RuleChecker | None = ..., + permission: Permission | T_PermissionChecker | None = ..., *, - handlers: Optional[List[Union[T_Handler, Dependent]]] = ..., + handlers: list[T_Handler | Dependent] | None = ..., temp: bool = ..., - expire_time: Optional[Union[datetime, timedelta]] = ..., + expire_time: datetime | timedelta | None = ..., priority: int = ..., block: bool = ..., - state: Optional[T_State] = ..., -) -> Type[Matcher]: ... + state: T_State | None = ..., +) -> type[Matcher]: ... def on_request( - rule: Optional[Union[Rule, T_RuleChecker]] = ..., - permission: Optional[Union[Permission, T_PermissionChecker]] = ..., + rule: Rule | T_RuleChecker | None = ..., + permission: Permission | T_PermissionChecker | None = ..., *, - handlers: Optional[List[Union[T_Handler, Dependent]]] = ..., + handlers: list[T_Handler | Dependent] | None = ..., temp: bool = ..., - expire_time: Optional[Union[datetime, timedelta]] = ..., + expire_time: datetime | timedelta | None = ..., priority: int = ..., block: bool = ..., - state: Optional[T_State] = ..., -) -> Type[Matcher]: ... + state: T_State | None = ..., +) -> type[Matcher]: ... def on_startswith( - msg: Union[str, Tuple[str, ...]], - rule: Optional[Union[Rule, T_RuleChecker]] = ..., + msg: str | tuple[str, ...], + rule: Rule | T_RuleChecker | None = ..., ignorecase: bool = ..., *, - permission: Optional[Union[Permission, T_PermissionChecker]] = ..., - handlers: Optional[List[Union[T_Handler, Dependent]]] = ..., + permission: Permission | T_PermissionChecker | None = ..., + handlers: list[T_Handler | Dependent] | None = ..., temp: bool = ..., - expire_time: Optional[Union[datetime, timedelta]] = ..., + expire_time: datetime | timedelta | None = ..., priority: int = ..., block: bool = ..., - state: Optional[T_State] = ..., -) -> Type[Matcher]: ... + state: T_State | None = ..., +) -> type[Matcher]: ... def on_endswith( - msg: Union[str, Tuple[str, ...]], - rule: Optional[Union[Rule, T_RuleChecker]] = ..., + msg: str | tuple[str, ...], + rule: Rule | T_RuleChecker | None = ..., ignorecase: bool = ..., *, - permission: Optional[Union[Permission, T_PermissionChecker]] = ..., - handlers: Optional[List[Union[T_Handler, Dependent]]] = ..., + permission: Permission | T_PermissionChecker | None = ..., + handlers: list[T_Handler | Dependent] | None = ..., temp: bool = ..., - expire_time: Optional[Union[datetime, timedelta]] = ..., + expire_time: datetime | timedelta | None = ..., priority: int = ..., block: bool = ..., - state: Optional[T_State] = ..., -) -> Type[Matcher]: ... + state: T_State | None = ..., +) -> type[Matcher]: ... def on_fullmatch( - msg: Union[str, Tuple[str, ...]], - rule: Optional[Union[Rule, T_RuleChecker]] = ..., + msg: str | tuple[str, ...], + rule: Rule | T_RuleChecker | None = ..., ignorecase: bool = ..., *, - permission: Optional[Union[Permission, T_PermissionChecker]] = ..., - handlers: Optional[List[Union[T_Handler, Dependent]]] = ..., + permission: Permission | T_PermissionChecker | None = ..., + handlers: list[T_Handler | Dependent] | None = ..., temp: bool = ..., - expire_time: Optional[Union[datetime, timedelta]] = ..., + expire_time: datetime | timedelta | None = ..., priority: int = ..., block: bool = ..., - state: Optional[T_State] = ..., -) -> Type[Matcher]: ... + state: T_State | None = ..., +) -> type[Matcher]: ... def on_keyword( - keywords: Set[str], - rule: Optional[Union[Rule, T_RuleChecker]] = ..., + keywords: set[str], + rule: Rule | T_RuleChecker | None = ..., *, - permission: Optional[Union[Permission, T_PermissionChecker]] = ..., - handlers: Optional[List[Union[T_Handler, Dependent]]] = ..., + permission: Permission | T_PermissionChecker | None = ..., + handlers: list[T_Handler | Dependent] | None = ..., temp: bool = ..., - expire_time: Optional[Union[datetime, timedelta]] = ..., + expire_time: datetime | timedelta | None = ..., priority: int = ..., block: bool = ..., - state: Optional[T_State] = ..., -) -> Type[Matcher]: ... + state: T_State | None = ..., +) -> type[Matcher]: ... def on_command( - cmd: Union[str, Tuple[str, ...]], - rule: Optional[Union[Rule, T_RuleChecker]] = ..., - aliases: Optional[Set[Union[str, Tuple[str, ...]]]] = ..., - force_whitespace: Optional[Union[str, bool]] = ..., + cmd: str | tuple[str, ...], + rule: Rule | T_RuleChecker | None = ..., + aliases: set[str | tuple[str, ...]] | None = ..., + force_whitespace: str | bool | None = ..., *, - permission: Optional[Union[Permission, T_PermissionChecker]] = ..., - handlers: Optional[List[Union[T_Handler, Dependent]]] = ..., + permission: Permission | T_PermissionChecker | None = ..., + handlers: list[T_Handler | Dependent] | None = ..., temp: bool = ..., - expire_time: Optional[Union[datetime, timedelta]] = ..., + expire_time: datetime | timedelta | None = ..., priority: int = ..., block: bool = ..., - state: Optional[T_State] = ..., -) -> Type[Matcher]: ... + state: T_State | None = ..., +) -> type[Matcher]: ... def on_shell_command( - cmd: Union[str, Tuple[str, ...]], - rule: Optional[Union[Rule, T_RuleChecker]] = ..., - aliases: Optional[Set[Union[str, Tuple[str, ...]]]] = ..., - parser: Optional[ArgumentParser] = ..., + cmd: str | tuple[str, ...], + rule: Rule | T_RuleChecker | None = ..., + aliases: set[str | tuple[str, ...]] | None = ..., + parser: ArgumentParser | None = ..., *, - permission: Optional[Union[Permission, T_PermissionChecker]] = ..., - handlers: Optional[List[Union[T_Handler, Dependent]]] = ..., + permission: Permission | T_PermissionChecker | None = ..., + handlers: list[T_Handler | Dependent] | None = ..., temp: bool = ..., - expire_time: Optional[Union[datetime, timedelta]] = ..., + expire_time: datetime | timedelta | None = ..., priority: int = ..., block: bool = ..., - state: Optional[T_State] = ..., -) -> Type[Matcher]: ... + state: T_State | None = ..., +) -> type[Matcher]: ... def on_regex( pattern: str, - flags: Union[int, re.RegexFlag] = ..., - rule: Optional[Union[Rule, T_RuleChecker]] = ..., + flags: int | re.RegexFlag = ..., + rule: Rule | T_RuleChecker | None = ..., *, - permission: Optional[Union[Permission, T_PermissionChecker]] = ..., - handlers: Optional[List[Union[T_Handler, Dependent]]] = ..., + permission: Permission | T_PermissionChecker | None = ..., + handlers: list[T_Handler | Dependent] | None = ..., temp: bool = ..., - expire_time: Optional[Union[datetime, timedelta]] = ..., + expire_time: datetime | timedelta | None = ..., priority: int = ..., block: bool = ..., - state: Optional[T_State] = ..., -) -> Type[Matcher]: ... + state: T_State | None = ..., +) -> type[Matcher]: ... def on_type( - types: Union[Type[Event], Tuple[Type[Event], ...]], - rule: Optional[Union[Rule, T_RuleChecker]] = ..., + types: type[Event] | tuple[type[Event], ...], + rule: Rule | T_RuleChecker | None = ..., *, - permission: Optional[Union[Permission, T_PermissionChecker]] = ..., - handlers: Optional[List[Union[T_Handler, Dependent]]] = ..., + permission: Permission | T_PermissionChecker | None = ..., + handlers: list[T_Handler | Dependent] | None = ..., temp: bool = ..., - expire_time: Optional[Union[datetime, timedelta]] = ..., + expire_time: datetime | timedelta | None = ..., priority: int = ..., block: bool = ..., - state: Optional[T_State] = ..., -) -> Type[Matcher]: ... + state: T_State | None = ..., +) -> type[Matcher]: ... class CommandGroup: def __init__( self, - cmd: Union[str, Tuple[str, ...]], + cmd: str | tuple[str, ...], *, - rule: Optional[Union[Rule, T_RuleChecker]] = ..., - permission: Optional[Union[Permission, T_PermissionChecker]] = ..., - handlers: Optional[List[Union[T_Handler, Dependent]]] = ..., + rule: Rule | T_RuleChecker | None = ..., + permission: Permission | T_PermissionChecker | None = ..., + handlers: list[T_Handler | Dependent] | None = ..., temp: bool = ..., - expire_time: Optional[Union[datetime, timedelta]] = ..., + expire_time: datetime | timedelta | None = ..., priority: int = ..., block: bool = ..., - state: Optional[T_State] = ..., + state: T_State | None = ..., ): ... def command( self, - cmd: Union[str, Tuple[str, ...]], + cmd: str | tuple[str, ...], *, - rule: Optional[Union[Rule, T_RuleChecker]] = ..., - aliases: Optional[Set[Union[str, Tuple[str, ...]]]] = ..., - force_whitespace: Optional[Union[str, bool]] = ..., - permission: Optional[Union[Permission, T_PermissionChecker]] = ..., - handlers: Optional[List[Union[T_Handler, Dependent]]] = ..., + rule: Rule | T_RuleChecker | None = ..., + aliases: set[str | tuple[str, ...]] | None = ..., + force_whitespace: str | bool | None = ..., + permission: Permission | T_PermissionChecker | None = ..., + handlers: list[T_Handler | Dependent] | None = ..., temp: bool = ..., - expire_time: Optional[Union[datetime, timedelta]] = ..., + expire_time: datetime | timedelta | None = ..., priority: int = ..., block: bool = ..., - state: Optional[T_State] = ..., - ) -> Type[Matcher]: ... + state: T_State | None = ..., + ) -> type[Matcher]: ... def shell_command( self, - cmd: Union[str, Tuple[str, ...]], + cmd: str | tuple[str, ...], *, - rule: Optional[Union[Rule, T_RuleChecker]] = ..., - aliases: Optional[Set[Union[str, Tuple[str, ...]]]] = ..., - parser: Optional[ArgumentParser] = ..., - permission: Optional[Union[Permission, T_PermissionChecker]] = ..., - handlers: Optional[List[Union[T_Handler, Dependent]]] = ..., + rule: Rule | T_RuleChecker | None = ..., + aliases: set[str | tuple[str, ...]] | None = ..., + parser: ArgumentParser | None = ..., + permission: Permission | T_PermissionChecker | None = ..., + handlers: list[T_Handler | Dependent] | None = ..., temp: bool = ..., - expire_time: Optional[Union[datetime, timedelta]] = ..., + expire_time: datetime | timedelta | None = ..., priority: int = ..., block: bool = ..., - state: Optional[T_State] = ..., - ) -> Type[Matcher]: ... + state: T_State | None = ..., + ) -> type[Matcher]: ... class MatcherGroup: def __init__( self, *, type: str = ..., - rule: Optional[Union[Rule, T_RuleChecker]] = ..., - permission: Optional[Union[Permission, T_PermissionChecker]] = ..., - handlers: Optional[List[Union[T_Handler, Dependent]]] = ..., + rule: Rule | T_RuleChecker | None = ..., + permission: Permission | T_PermissionChecker | None = ..., + handlers: list[T_Handler | Dependent] | None = ..., temp: bool = ..., - expire_time: Optional[Union[datetime, timedelta]] = ..., + expire_time: datetime | timedelta | None = ..., priority: int = ..., block: bool = ..., - state: Optional[T_State] = ..., + state: T_State | None = ..., ): ... def on( self, *, type: str = ..., - rule: Optional[Union[Rule, T_RuleChecker]] = ..., - permission: Optional[Union[Permission, T_PermissionChecker]] = ..., - handlers: Optional[List[Union[T_Handler, Dependent]]] = ..., + rule: Rule | T_RuleChecker | None = ..., + permission: Permission | T_PermissionChecker | None = ..., + handlers: list[T_Handler | Dependent] | None = ..., temp: bool = ..., - expire_time: Optional[Union[datetime, timedelta]] = ..., + expire_time: datetime | timedelta | None = ..., priority: int = ..., block: bool = ..., - state: Optional[T_State] = ..., - ) -> Type[Matcher]: ... + state: T_State | None = ..., + ) -> type[Matcher]: ... def on_metaevent( self, *, - rule: Optional[Union[Rule, T_RuleChecker]] = ..., - permission: Optional[Union[Permission, T_PermissionChecker]] = ..., - handlers: Optional[List[Union[T_Handler, Dependent]]] = ..., + rule: Rule | T_RuleChecker | None = ..., + permission: Permission | T_PermissionChecker | None = ..., + handlers: list[T_Handler | Dependent] | None = ..., temp: bool = ..., - expire_time: Optional[Union[datetime, timedelta]] = ..., + expire_time: datetime | timedelta | None = ..., priority: int = ..., block: bool = ..., - state: Optional[T_State] = ..., - ) -> Type[Matcher]: ... + state: T_State | None = ..., + ) -> type[Matcher]: ... def on_message( self, *, - rule: Optional[Union[Rule, T_RuleChecker]] = ..., - permission: Optional[Union[Permission, T_PermissionChecker]] = ..., - handlers: Optional[List[Union[T_Handler, Dependent]]] = ..., + rule: Rule | T_RuleChecker | None = ..., + permission: Permission | T_PermissionChecker | None = ..., + handlers: list[T_Handler | Dependent] | None = ..., temp: bool = ..., - expire_time: Optional[Union[datetime, timedelta]] = ..., + expire_time: datetime | timedelta | None = ..., priority: int = ..., block: bool = ..., - state: Optional[T_State] = ..., - ) -> Type[Matcher]: ... + state: T_State | None = ..., + ) -> type[Matcher]: ... def on_notice( self, *, - rule: Optional[Union[Rule, T_RuleChecker]] = ..., - permission: Optional[Union[Permission, T_PermissionChecker]] = ..., - handlers: Optional[List[Union[T_Handler, Dependent]]] = ..., + rule: Rule | T_RuleChecker | None = ..., + permission: Permission | T_PermissionChecker | None = ..., + handlers: list[T_Handler | Dependent] | None = ..., temp: bool = ..., - expire_time: Optional[Union[datetime, timedelta]] = ..., + expire_time: datetime | timedelta | None = ..., priority: int = ..., block: bool = ..., - state: Optional[T_State] = ..., - ) -> Type[Matcher]: ... + state: T_State | None = ..., + ) -> type[Matcher]: ... def on_request( self, *, - rule: Optional[Union[Rule, T_RuleChecker]] = ..., - permission: Optional[Union[Permission, T_PermissionChecker]] = ..., - handlers: Optional[List[Union[T_Handler, Dependent]]] = ..., + rule: Rule | T_RuleChecker | None = ..., + permission: Permission | T_PermissionChecker | None = ..., + handlers: list[T_Handler | Dependent] | None = ..., temp: bool = ..., - expire_time: Optional[Union[datetime, timedelta]] = ..., + expire_time: datetime | timedelta | None = ..., priority: int = ..., block: bool = ..., - state: Optional[T_State] = ..., - ) -> Type[Matcher]: ... + state: T_State | None = ..., + ) -> type[Matcher]: ... def on_startswith( self, - msg: Union[str, Tuple[str, ...]], + msg: str | tuple[str, ...], *, ignorecase: bool = ..., - rule: Optional[Union[Rule, T_RuleChecker]] = ..., - permission: Optional[Union[Permission, T_PermissionChecker]] = ..., - handlers: Optional[List[Union[T_Handler, Dependent]]] = ..., + rule: Rule | T_RuleChecker | None = ..., + permission: Permission | T_PermissionChecker | None = ..., + handlers: list[T_Handler | Dependent] | None = ..., temp: bool = ..., - expire_time: Optional[Union[datetime, timedelta]] = ..., + expire_time: datetime | timedelta | None = ..., priority: int = ..., block: bool = ..., - state: Optional[T_State] = ..., - ) -> Type[Matcher]: ... + state: T_State | None = ..., + ) -> type[Matcher]: ... def on_endswith( self, - msg: Union[str, Tuple[str, ...]], + msg: str | tuple[str, ...], *, ignorecase: bool = ..., - rule: Optional[Union[Rule, T_RuleChecker]] = ..., - permission: Optional[Union[Permission, T_PermissionChecker]] = ..., - handlers: Optional[List[Union[T_Handler, Dependent]]] = ..., + rule: Rule | T_RuleChecker | None = ..., + permission: Permission | T_PermissionChecker | None = ..., + handlers: list[T_Handler | Dependent] | None = ..., temp: bool = ..., - expire_time: Optional[Union[datetime, timedelta]] = ..., + expire_time: datetime | timedelta | None = ..., priority: int = ..., block: bool = ..., - state: Optional[T_State] = ..., - ) -> Type[Matcher]: ... + state: T_State | None = ..., + ) -> type[Matcher]: ... def on_fullmatch( self, - msg: Union[str, Tuple[str, ...]], + msg: str | tuple[str, ...], *, ignorecase: bool = ..., - rule: Optional[Union[Rule, T_RuleChecker]] = ..., - permission: Optional[Union[Permission, T_PermissionChecker]] = ..., - handlers: Optional[List[Union[T_Handler, Dependent]]] = ..., + rule: Rule | T_RuleChecker | None = ..., + permission: Permission | T_PermissionChecker | None = ..., + handlers: list[T_Handler | Dependent] | None = ..., temp: bool = ..., - expire_time: Optional[Union[datetime, timedelta]] = ..., + expire_time: datetime | timedelta | None = ..., priority: int = ..., block: bool = ..., - state: Optional[T_State] = ..., - ) -> Type[Matcher]: ... + state: T_State | None = ..., + ) -> type[Matcher]: ... def on_keyword( self, - keywords: Set[str], + keywords: set[str], *, - rule: Optional[Union[Rule, T_RuleChecker]] = ..., - permission: Optional[Union[Permission, T_PermissionChecker]] = ..., - handlers: Optional[List[Union[T_Handler, Dependent]]] = ..., + rule: Rule | T_RuleChecker | None = ..., + permission: Permission | T_PermissionChecker | None = ..., + handlers: list[T_Handler | Dependent] | None = ..., temp: bool = ..., - expire_time: Optional[Union[datetime, timedelta]] = ..., + expire_time: datetime | timedelta | None = ..., priority: int = ..., block: bool = ..., - state: Optional[T_State] = ..., - ) -> Type[Matcher]: ... + state: T_State | None = ..., + ) -> type[Matcher]: ... def on_command( self, - cmd: Union[str, Tuple[str, ...]], - aliases: Optional[Set[Union[str, Tuple[str, ...]]]] = ..., - force_whitespace: Optional[Union[str, bool]] = ..., + cmd: str | tuple[str, ...], + aliases: set[str | tuple[str, ...]] | None = ..., + force_whitespace: str | bool | None = ..., *, - rule: Optional[Union[Rule, T_RuleChecker]] = ..., - permission: Optional[Union[Permission, T_PermissionChecker]] = ..., - handlers: Optional[List[Union[T_Handler, Dependent]]] = ..., + rule: Rule | T_RuleChecker | None = ..., + permission: Permission | T_PermissionChecker | None = ..., + handlers: list[T_Handler | Dependent] | None = ..., temp: bool = ..., - expire_time: Optional[Union[datetime, timedelta]] = ..., + expire_time: datetime | timedelta | None = ..., priority: int = ..., block: bool = ..., - state: Optional[T_State] = ..., - ) -> Type[Matcher]: ... + state: T_State | None = ..., + ) -> type[Matcher]: ... def on_shell_command( self, - cmd: Union[str, Tuple[str, ...]], - aliases: Optional[Set[Union[str, Tuple[str, ...]]]] = ..., - parser: Optional[ArgumentParser] = ..., + cmd: str | tuple[str, ...], + aliases: set[str | tuple[str, ...]] | None = ..., + parser: ArgumentParser | None = ..., *, - rule: Optional[Union[Rule, T_RuleChecker]] = ..., - permission: Optional[Union[Permission, T_PermissionChecker]] = ..., - handlers: Optional[List[Union[T_Handler, Dependent]]] = ..., + rule: Rule | T_RuleChecker | None = ..., + permission: Permission | T_PermissionChecker | None = ..., + handlers: list[T_Handler | Dependent] | None = ..., temp: bool = ..., - expire_time: Optional[Union[datetime, timedelta]] = ..., + expire_time: datetime | timedelta | None = ..., priority: int = ..., block: bool = ..., - state: Optional[T_State] = ..., - ) -> Type[Matcher]: ... + state: T_State | None = ..., + ) -> type[Matcher]: ... def on_regex( self, pattern: str, - flags: Union[int, re.RegexFlag] = ..., + flags: int | re.RegexFlag = ..., *, - rule: Optional[Union[Rule, T_RuleChecker]] = ..., - permission: Optional[Union[Permission, T_PermissionChecker]] = ..., - handlers: Optional[List[Union[T_Handler, Dependent]]] = ..., + rule: Rule | T_RuleChecker | None = ..., + permission: Permission | T_PermissionChecker | None = ..., + handlers: list[T_Handler | Dependent] | None = ..., temp: bool = ..., - expire_time: Optional[Union[datetime, timedelta]] = ..., + expire_time: datetime | timedelta | None = ..., priority: int = ..., block: bool = ..., - state: Optional[T_State] = ..., - ) -> Type[Matcher]: ... + state: T_State | None = ..., + ) -> type[Matcher]: ... def on_type( self, - types: Union[Type[Event], Tuple[Type[Event]]], + types: type[Event] | tuple[type[Event]], *, - rule: Optional[Union[Rule, T_RuleChecker]] = ..., - permission: Optional[Union[Permission, T_PermissionChecker]] = ..., - handlers: Optional[List[Union[T_Handler, Dependent]]] = ..., + rule: Rule | T_RuleChecker | None = ..., + permission: Permission | T_PermissionChecker | None = ..., + handlers: list[T_Handler | Dependent] | None = ..., temp: bool = ..., - expire_time: Optional[Union[datetime, timedelta]] = ..., + expire_time: datetime | timedelta | None = ..., priority: int = ..., block: bool = ..., - state: Optional[T_State] = ..., - ) -> Type[Matcher]: ... + state: T_State | None = ..., + ) -> type[Matcher]: ... diff --git a/nonebot/plugins/single_session.py b/nonebot/plugins/single_session.py index d5b2578f..28134534 100644 --- a/nonebot/plugins/single_session.py +++ b/nonebot/plugins/single_session.py @@ -26,7 +26,7 @@ async def matcher_mutex(event: Event) -> AsyncGenerator[bool, None]: yield result else: current_event_id = id(event) - if event_id := _running_matcher.get(session_id, None): + if event_id := _running_matcher.get(session_id): result = event_id != current_event_id else: _running_matcher[session_id] = current_event_id diff --git a/nonebot/rule.py b/nonebot/rule.py index 8974e7ce..f7d8254c 100644 --- a/nonebot/rule.py +++ b/nonebot/rule.py @@ -1,7 +1,8 @@ """本模块是 {ref}`nonebot.matcher.Matcher.rule` 的类型定义。 -每个事件响应器 {ref}`nonebot.matcher.Matcher` 拥有一个匹配规则 {ref}`nonebot.rule.Rule` -其中是 `RuleChecker` 的集合,只有当所有 `RuleChecker` 检查结果为 `True` 时继续运行。 +每个{ref}`事件响应器 `拥有一个 +{ref}`nonebot.rule.Rule`,其中是 `RuleChecker` 的集合。 +只有当所有 `RuleChecker` 检查结果为 `True` 时继续运行。 FrontMatter: sidebar_position: 5 @@ -60,20 +61,19 @@ from nonebot.consts import ( T = TypeVar("T") -CMD_RESULT = TypedDict( - "CMD_RESULT", - { - "command": Optional[Tuple[str, ...]], - "raw_command": Optional[str], - "command_arg": Optional[Message], - "command_start": Optional[str], - "command_whitespace": Optional[str], - }, -) -TRIE_VALUE = NamedTuple( - "TRIE_VALUE", [("command_start", str), ("command", Tuple[str, ...])] -) +class CMD_RESULT(TypedDict): + command: Optional[Tuple[str, ...]] + raw_command: Optional[str] + command_arg: Optional[Message] + command_start: Optional[str] + command_whitespace: Optional[str] + + +class TRIE_VALUE(NamedTuple): + command_start: str + command: Tuple[str, ...] + parser_message: ContextVar[str] = ContextVar("parser_message") @@ -406,7 +406,7 @@ def command( force_whitespace: 是否强制命令后必须有指定空白符 用法: - 使用默认 `command_start`, `command_sep` 配置 + 使用默认 `command_start`, `command_sep` 配置情况下: 命令 `("test",)` 可以匹配: `/test` 开头的消息 命令 `("test", "sub")` 可以匹配: `/test.sub` 开头的消息 @@ -441,6 +441,8 @@ def command( class ArgumentParser(ArgParser): """`shell_like` 命令参数解析器,解析出错时不会退出程序。 + 支持 {ref}`nonebot.adapters.Message` 富文本解析。 + 用法: 用法与 `argparse.ArgumentParser` 相同, 参考文档: [argparse](https://docs.python.org/3/library/argparse.html) @@ -588,10 +590,14 @@ def shell_command( 根据配置里提供的 {ref}``command_start` `, {ref}``command_sep` ` 判断消息是否为命令。 - 可以通过 {ref}`nonebot.params.Command` 获取匹配成功的命令(例: `("test",)`), - 通过 {ref}`nonebot.params.RawCommand` 获取匹配成功的原始命令文本(例: `"/test"`), - 通过 {ref}`nonebot.params.ShellCommandArgv` 获取解析前的参数列表(例: `["arg", "-h"]`), - 通过 {ref}`nonebot.params.ShellCommandArgs` 获取解析后的参数字典(例: `{"arg": "arg", "h": True}`)。 + 可以通过 {ref}`nonebot.params.Command` 获取匹配成功的命令 + (例: `("test",)`), + 通过 {ref}`nonebot.params.RawCommand` 获取匹配成功的原始命令文本 + (例: `"/test"`), + 通过 {ref}`nonebot.params.ShellCommandArgv` 获取解析前的参数列表 + (例: `["arg", "-h"]`), + 通过 {ref}`nonebot.params.ShellCommandArgs` 获取解析后的参数字典 + (例: `{"arg": "arg", "h": True}`)。 :::warning 警告 如果参数解析失败,则通过 {ref}`nonebot.params.ShellCommandArgs` @@ -603,7 +609,8 @@ def shell_command( parser: {ref}`nonebot.rule.ArgumentParser` 对象 用法: - 使用默认 `command_start`, `command_sep` 配置,更多示例参考 `argparse` 标准库文档。 + 使用默认 `command_start`, `command_sep` 配置,更多示例参考 + [argparse](https://docs.python.org/3/library/argparse.html) 标准库文档。 ```python from nonebot.rule import ArgumentParser @@ -698,7 +705,8 @@ def regex(regex: str, flags: Union[int, re.RegexFlag] = 0) -> Rule: ::: :::tip 提示 - 正则表达式匹配使用 `EventMessage` 的 `str` 字符串,而非 `EventMessage` 的 `PlainText` 纯文本字符串 + 正则表达式匹配使用 `EventMessage` 的 `str` 字符串, + 而非 `EventMessage` 的 `PlainText` 纯文本字符串 ::: """ diff --git a/nonebot/typing.py b/nonebot/typing.py index a27513f6..10b5b2d3 100644 --- a/nonebot/typing.py +++ b/nonebot/typing.py @@ -1,17 +1,16 @@ """本模块定义了 NoneBot 模块中共享的一些类型。 -下面的文档中,「类型」部分使用 Python 的 Type Hint 语法, +使用 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 内置类型的别名。 - FrontMatter: sidebar_position: 11 description: nonebot.typing 模块 """ +from typing_extensions import ParamSpec, TypeAlias from typing import ( TYPE_CHECKING, Any, @@ -30,8 +29,9 @@ if TYPE_CHECKING: from nonebot.permission import Permission T = TypeVar("T") +P = ParamSpec("P") -T_Wrapped = TypeVar("T_Wrapped", bound=Callable) +T_Wrapped: TypeAlias = Callable[P, T] def overrides(InterfaceClass: object) -> Callable[[T_Wrapped], T_Wrapped]: @@ -45,13 +45,13 @@ def overrides(InterfaceClass: object) -> Callable[[T_Wrapped], T_Wrapped]: # state -T_State = Dict[Any, Any] +T_State: TypeAlias = Dict[Any, Any] """事件处理状态 State 类型""" -_DependentCallable = Union[Callable[..., T], Callable[..., Awaitable[T]]] +_DependentCallable: TypeAlias = Union[Callable[..., T], Callable[..., Awaitable[T]]] # driver hooks -T_BotConnectionHook = _DependentCallable[Any] +T_BotConnectionHook: TypeAlias = _DependentCallable[Any] """Bot 连接建立时钩子函数 依赖参数: @@ -60,7 +60,7 @@ T_BotConnectionHook = _DependentCallable[Any] - BotParam: Bot 对象 - DefaultParam: 带有默认值的参数 """ -T_BotDisconnectionHook = _DependentCallable[Any] +T_BotDisconnectionHook: TypeAlias = _DependentCallable[Any] """Bot 连接断开时钩子函数 依赖参数: @@ -71,15 +71,15 @@ T_BotDisconnectionHook = _DependentCallable[Any] """ # api hooks -T_CallingAPIHook = Callable[["Bot", str, Dict[str, Any]], Awaitable[Any]] +T_CallingAPIHook: TypeAlias = Callable[["Bot", str, Dict[str, Any]], Awaitable[Any]] """`bot.call_api` 钩子函数""" -T_CalledAPIHook = Callable[ +T_CalledAPIHook: TypeAlias = Callable[ ["Bot", Optional[Exception], str, Dict[str, Any], Any], Awaitable[Any] ] """`bot.call_api` 后执行的函数,参数分别为 bot, exception, api, data, result""" # event hooks -T_EventPreProcessor = _DependentCallable[Any] +T_EventPreProcessor: TypeAlias = _DependentCallable[Any] """事件预处理函数 EventPreProcessor 类型 依赖参数: @@ -90,7 +90,7 @@ T_EventPreProcessor = _DependentCallable[Any] - StateParam: State 对象 - DefaultParam: 带有默认值的参数 """ -T_EventPostProcessor = _DependentCallable[Any] +T_EventPostProcessor: TypeAlias = _DependentCallable[Any] """事件预处理函数 EventPostProcessor 类型 依赖参数: @@ -103,7 +103,7 @@ T_EventPostProcessor = _DependentCallable[Any] """ # matcher run hooks -T_RunPreProcessor = _DependentCallable[Any] +T_RunPreProcessor: TypeAlias = _DependentCallable[Any] """事件响应器运行前预处理函数 RunPreProcessor 类型 依赖参数: @@ -115,7 +115,7 @@ T_RunPreProcessor = _DependentCallable[Any] - MatcherParam: Matcher 对象 - DefaultParam: 带有默认值的参数 """ -T_RunPostProcessor = _DependentCallable[Any] +T_RunPostProcessor: TypeAlias = _DependentCallable[Any] """事件响应器运行后后处理函数 RunPostProcessor 类型 依赖参数: @@ -130,7 +130,7 @@ T_RunPostProcessor = _DependentCallable[Any] """ # rule, permission -T_RuleChecker = _DependentCallable[bool] +T_RuleChecker: TypeAlias = _DependentCallable[bool] """RuleChecker 即判断是否响应事件的处理函数。 依赖参数: @@ -141,7 +141,7 @@ T_RuleChecker = _DependentCallable[bool] - StateParam: State 对象 - DefaultParam: 带有默认值的参数 """ -T_PermissionChecker = _DependentCallable[bool] +T_PermissionChecker: TypeAlias = _DependentCallable[bool] """PermissionChecker 即判断事件是否满足权限的处理函数。 依赖参数: @@ -152,10 +152,11 @@ T_PermissionChecker = _DependentCallable[bool] - DefaultParam: 带有默认值的参数 """ -T_Handler = _DependentCallable[Any] +T_Handler: TypeAlias = _DependentCallable[Any] """Handler 处理函数。""" -T_TypeUpdater = _DependentCallable[str] -"""TypeUpdater 在 Matcher.pause, Matcher.reject 时被运行,用于更新响应的事件类型。默认会更新为 `message`。 +T_TypeUpdater: TypeAlias = _DependentCallable[str] +"""TypeUpdater 在 Matcher.pause, Matcher.reject 时被运行,用于更新响应的事件类型。 +默认会更新为 `message`。 依赖参数: @@ -166,8 +167,9 @@ T_TypeUpdater = _DependentCallable[str] - MatcherParam: Matcher 对象 - DefaultParam: 带有默认值的参数 """ -T_PermissionUpdater = _DependentCallable["Permission"] -"""PermissionUpdater 在 Matcher.pause, Matcher.reject 时被运行,用于更新会话对象权限。默认会更新为当前事件的触发对象。 +T_PermissionUpdater: TypeAlias = _DependentCallable["Permission"] +"""PermissionUpdater 在 Matcher.pause, Matcher.reject 时被运行,用于更新会话对象权限。 +默认会更新为当前事件的触发对象。 依赖参数: @@ -178,5 +180,5 @@ T_PermissionUpdater = _DependentCallable["Permission"] - MatcherParam: Matcher 对象 - DefaultParam: 带有默认值的参数 """ -T_DependencyCache = Dict[_DependentCallable[Any], "Task[Any]"] +T_DependencyCache: TypeAlias = Dict[_DependentCallable[Any], "Task[Any]"] """依赖缓存, 用于存储依赖函数的返回值""" diff --git a/nonebot/utils.py b/nonebot/utils.py index 8a13a8ab..650fc2df 100644 --- a/nonebot/utils.py +++ b/nonebot/utils.py @@ -63,7 +63,8 @@ def generic_check_issubclass( - 如果 cls 是 `typing.Union` 或 `types.UnionType` 类型, 则会检查其中的所有类型是否是 class_or_tuple 中一个类型的子类或 None。 - 如果 cls 是 `typing.TypeVar` 类型, - 则会检查其 `__bound__` 或 `__constraints__` 是否是 class_or_tuple 中一个类型的子类或 None。 + 则会检查其 `__bound__` 或 `__constraints__` + 是否是 class_or_tuple 中一个类型的子类或 None。 """ try: return issubclass(cls, class_or_tuple) @@ -171,6 +172,17 @@ async def run_coro_with_catch( exc: Tuple[Type[Exception], ...], return_on_err: Optional[R] = None, ) -> Optional[Union[T, R]]: + """运行协程并当遇到指定异常时返回指定值。 + + 参数: + coro: 要运行的协程 + exc: 要捕获的异常 + return_on_err: 当发生异常时返回的值 + + 返回: + 协程的返回值或发生异常时的指定值 + """ + try: return await coro except exc: @@ -210,7 +222,7 @@ def resolve_dot_notation( class DataclassEncoder(json.JSONEncoder): - """在JSON序列化 {ref}`nonebot.adapters.Message` (List[Dataclass]) 时使用的 `JSONEncoder`""" + """可以序列化 {ref}`nonebot.adapters.Message`(List[Dataclass]) 的 `JSONEncoder`""" @overrides(json.JSONEncoder) def default(self, o): @@ -228,9 +240,11 @@ def logger_wrapper(logger_name: str): 返回: 日志记录函数 - - level: 日志等级 - - message: 日志信息 - - exception: 异常信息 + 日志记录函数的参数: + + - level: 日志等级 + - message: 日志信息 + - exception: 异常信息 """ def log(level: str, message: str, exception: Optional[Exception] = None): diff --git a/poetry.lock b/poetry.lock index 0fd7441b..cba1446d 100644 --- a/poetry.lock +++ b/poetry.lock @@ -759,39 +759,36 @@ testing = ["pre-commit"] [[package]] name = "fastapi" -version = "0.95.2" +version = "0.98.0" description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" optional = true python-versions = ">=3.7" files = [ - {file = "fastapi-0.95.2-py3-none-any.whl", hash = "sha256:d374dbc4ef2ad9b803899bd3360d34c534adc574546e25314ab72c0c4411749f"}, - {file = "fastapi-0.95.2.tar.gz", hash = "sha256:4d9d3e8c71c73f11874bcf5e33626258d143252e329a01002f767306c64fb982"}, + {file = "fastapi-0.98.0-py3-none-any.whl", hash = "sha256:f4165fb1fe3610c52cb1b8282c1480de9c34bc270f56a965aa93a884c350d605"}, + {file = "fastapi-0.98.0.tar.gz", hash = "sha256:0d3c18886f652038262b5898fec6b09f4ca92ee23e9d9b1d1d24e429f84bf27b"}, ] [package.dependencies] -pydantic = ">=1.6.2,<1.7 || >1.7,<1.7.1 || >1.7.1,<1.7.2 || >1.7.2,<1.7.3 || >1.7.3,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0" +pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0" starlette = ">=0.27.0,<0.28.0" [package.extras] all = ["email-validator (>=1.1.1)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "python-multipart (>=0.0.5)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] -dev = ["pre-commit (>=2.17.0,<3.0.0)", "ruff (==0.0.138)", "uvicorn[standard] (>=0.12.0,<0.21.0)"] -doc = ["mdx-include (>=1.4.1,<2.0.0)", "mkdocs (>=1.1.2,<2.0.0)", "mkdocs-markdownextradata-plugin (>=0.1.7,<0.3.0)", "mkdocs-material (>=8.1.4,<9.0.0)", "pyyaml (>=5.3.1,<7.0.0)", "typer-cli (>=0.0.13,<0.0.14)", "typer[all] (>=0.6.1,<0.8.0)"] -test = ["anyio[trio] (>=3.2.1,<4.0.0)", "black (==23.1.0)", "coverage[toml] (>=6.5.0,<8.0)", "databases[sqlite] (>=0.3.2,<0.7.0)", "email-validator (>=1.1.1,<2.0.0)", "flask (>=1.1.2,<3.0.0)", "httpx (>=0.23.0,<0.24.0)", "isort (>=5.0.6,<6.0.0)", "mypy (==0.982)", "orjson (>=3.2.1,<4.0.0)", "passlib[bcrypt] (>=1.7.2,<2.0.0)", "peewee (>=3.13.3,<4.0.0)", "pytest (>=7.1.3,<8.0.0)", "python-jose[cryptography] (>=3.3.0,<4.0.0)", "python-multipart (>=0.0.5,<0.0.7)", "pyyaml (>=5.3.1,<7.0.0)", "ruff (==0.0.138)", "sqlalchemy (>=1.3.18,<1.4.43)", "types-orjson (==3.6.2)", "types-ujson (==5.7.0.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0,<6.0.0)"] [[package]] name = "filelock" -version = "3.12.0" +version = "3.12.2" description = "A platform independent file lock." optional = false python-versions = ">=3.7" files = [ - {file = "filelock-3.12.0-py3-none-any.whl", hash = "sha256:ad98852315c2ab702aeb628412cbf7e95b7ce8c3bf9565670b4eaecf1db370a9"}, - {file = "filelock-3.12.0.tar.gz", hash = "sha256:fc03ae43288c013d2ea83c8597001b1129db351aad9c57fe2409327916b8e718"}, + {file = "filelock-3.12.2-py3-none-any.whl", hash = "sha256:cbb791cdea2a72f23da6ac5b5269ab0a0d161e9ef0100e653b69049a7706d1ec"}, + {file = "filelock-3.12.2.tar.gz", hash = "sha256:002740518d8aa59a26b0c76e10fb8c6e15eae825d34b6fdf670333fd7b938d81"}, ] [package.extras] -docs = ["furo (>=2023.3.27)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.2.3)", "diff-cover (>=7.5)", "pytest (>=7.3.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)", "pytest-timeout (>=2.1)"] +docs = ["furo (>=2023.5.20)", "sphinx (>=7.0.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "diff-cover (>=7.5)", "pytest (>=7.3.1)", "pytest-cov (>=4.1)", "pytest-mock (>=3.10)", "pytest-timeout (>=2.1)"] [[package]] name = "frozenlist" @@ -1073,13 +1070,13 @@ files = [ [[package]] name = "importlib-metadata" -version = "6.6.0" +version = "6.7.0" description = "Read metadata from Python packages" optional = false python-versions = ">=3.7" files = [ - {file = "importlib_metadata-6.6.0-py3-none-any.whl", hash = "sha256:43dd286a2cd8995d5eaef7fee2066340423b818ed3fd70adf0bad5f1fac53fed"}, - {file = "importlib_metadata-6.6.0.tar.gz", hash = "sha256:92501cdf9cc66ebd3e612f1b4f0c0765dfa42f0fa38ffb319b6bd84dd675d705"}, + {file = "importlib_metadata-6.7.0-py3-none-any.whl", hash = "sha256:cb52082e659e97afc5dac71e79de97d8681de3aa07ff18578330904a9d18e5b5"}, + {file = "importlib_metadata-6.7.0.tar.gz", hash = "sha256:1aaf550d4f73e5d6783e7acb77aec43d49da8017410afae93822cc9cca98c4d4"}, ] [package.dependencies] @@ -1088,7 +1085,7 @@ zipp = ">=0.5" [package.extras] docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] perf = ["ipython"] -testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)"] +testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] [[package]] name = "iniconfig" @@ -1146,53 +1143,6 @@ MarkupSafe = ">=2.0" [package.extras] i18n = ["Babel (>=2.7)"] -[[package]] -name = "libcst" -version = "0.4.10" -description = "A concrete syntax tree with AST-like properties for Python 3.5, 3.6, 3.7, 3.8, 3.9, and 3.10 programs." -optional = false -python-versions = ">=3.7" -files = [ - {file = "libcst-0.4.10-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8fa0ec646ed7bce984d0ee9dbf514af278050bdb16a4fb986e916ace534eebc6"}, - {file = "libcst-0.4.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3cb3b7821eac00713844cda079583230c546a589b22ed5f03f2ddc4f985c384b"}, - {file = "libcst-0.4.10-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e7acfa747112ae40b032739661abd7c81aff37191294f7c2dab8bbd72372e78f"}, - {file = "libcst-0.4.10-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1312e293b864ef3cb4b09534ed5f104c2dc45b680233c68bf76237295041c781"}, - {file = "libcst-0.4.10-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76884b1afe475e8e68e704bf26eb9f9a2867029643e58f2f26a0286e3b6e998e"}, - {file = "libcst-0.4.10-cp310-cp310-win_amd64.whl", hash = "sha256:1069b808a711db5cd47538f27eb2c73206317aa0d8b5a3500b23aab24f86eb2e"}, - {file = "libcst-0.4.10-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:50be085346a35812535c7f876319689e15a7bfd1bd8efae8fd70589281d944b6"}, - {file = "libcst-0.4.10-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bb9f10e5763e361e8bd8ff765fc0f1bcf744f242ff8b6d3e50ffec4dda3972ac"}, - {file = "libcst-0.4.10-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cfeeabb528b5df7b4be1817b584ce79e9a1a66687bd72f6de9c22272462812f1"}, - {file = "libcst-0.4.10-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5648aeae8c90a2abab1f7b1bf205769a0179ed2cfe1ea7f681f6885e87b8b193"}, - {file = "libcst-0.4.10-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a144f20aff4643b00374facf8409d30c7935db8176e5b2a07e1fd44004db2c1f"}, - {file = "libcst-0.4.10-cp311-cp311-win_amd64.whl", hash = "sha256:a10adc2e8ea2dda2b70eabec631ead2fc4a7a7ab633d6c2b690823c698b8431a"}, - {file = "libcst-0.4.10-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:58fe90458a26a55358207f74abf8a05dff51d662069f070b4bd308a000a80c09"}, - {file = "libcst-0.4.10-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:999fbbe467f61cbce9e6e054f86cd1c5ffa3740fd3dc8ebdd600db379f699256"}, - {file = "libcst-0.4.10-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83ee7e7be4efac4c140a97d772e1f6b3553f98fa5f46ad78df5dfe51e5a4aa4d"}, - {file = "libcst-0.4.10-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:158478e8f45578fb26621b3dc0fe275f9e004297e9afdcf08936ecda05681174"}, - {file = "libcst-0.4.10-cp37-cp37m-win_amd64.whl", hash = "sha256:5ed101fee1af7abea3684fcff7fab5b170ceea4040756f54c15c870539daec66"}, - {file = "libcst-0.4.10-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:349f2b4ee4b982fe254c65c78d941fc96299f3c422b79f95ef8c7bba2b7f0f90"}, - {file = "libcst-0.4.10-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7cfa4d4beb84d0d63247aca27f1a15c63984512274c5b23040f8b4ba511036d7"}, - {file = "libcst-0.4.10-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:24582506da24e31f2644f862f11413a6b80fbad68d15194bfcc3f7dfebf2ec5e"}, - {file = "libcst-0.4.10-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cdf2d0157438d3d52d310b0b6be31ff99bed19de489b2ebd3e2a4cd9946da45"}, - {file = "libcst-0.4.10-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a677103d2f1ab0e50bc3a7cc6c96c7d64bcbac826d785e4cbf5ee9aaa9fcfa25"}, - {file = "libcst-0.4.10-cp38-cp38-win_amd64.whl", hash = "sha256:a8fdfd4a7d301adb785aa4b98e4a7cca45c5ff8cfb460b485d081efcfaaeeab7"}, - {file = "libcst-0.4.10-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b1569d87536bed4e9c11dd5c94a137dc0bce2a2b05961489c6016bf4521bb7cf"}, - {file = "libcst-0.4.10-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:72dff8783ac79cd10f2bd2fde0b28f262e9a22718ae26990948ba6131b85ca8b"}, - {file = "libcst-0.4.10-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76adc53660ef094ff83f77a2550a7e00d1cab8e5e63336e071c17c09b5a89fe2"}, - {file = "libcst-0.4.10-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3e9d9fdd9a9b9b8991936ff1c07527ce7ef396c8233280ba9a7137e72c2e48e"}, - {file = "libcst-0.4.10-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e1b4cbaf7b1cdad5fa3eababe42d5b46c0d52afe13c5ba4eac2495fc57630ea"}, - {file = "libcst-0.4.10-cp39-cp39-win_amd64.whl", hash = "sha256:bcbd07cec3d7a7be6f0299b0c246e085e3d6cc8af367e2c96059183b97c2e2fe"}, - {file = "libcst-0.4.10.tar.gz", hash = "sha256:b98a829d96e8b209fb761b00cd1bacc27c70eae77d00e57976e5ae2c718c3f81"}, -] - -[package.dependencies] -pyyaml = ">=5.2" -typing-extensions = ">=3.7.4.2" -typing-inspect = ">=0.4.0" - -[package.extras] -dev = ["Sphinx (>=5.1.1)", "black (==23.1.0)", "build (>=0.10.0)", "coverage (>=4.5.4)", "fixit (==0.1.1)", "flake8 (>=3.7.8,<5)", "hypothesis (>=4.36.0)", "hypothesmith (>=0.0.4)", "jinja2 (==3.1.2)", "jupyter (>=1.0.0)", "maturin (>=0.8.3,<0.14)", "nbsphinx (>=0.4.2)", "prompt-toolkit (>=2.0.9)", "pyre-check (==0.9.10)", "setuptools-rust (>=1.5.2)", "setuptools-scm (>=6.0.1)", "slotscheck (>=0.7.1)", "sphinx-rtd-theme (>=0.4.3)", "ufmt (==2.1.0)", "usort (==1.0.6)"] - [[package]] name = "loguru" version = "0.7.0" @@ -1213,61 +1163,61 @@ dev = ["Sphinx (==5.3.0)", "colorama (==0.4.5)", "colorama (==0.4.6)", "freezegu [[package]] name = "markupsafe" -version = "2.1.2" +version = "2.1.3" description = "Safely add untrusted strings to HTML/XML markup." optional = false python-versions = ">=3.7" files = [ - {file = "MarkupSafe-2.1.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:665a36ae6f8f20a4676b53224e33d456a6f5a72657d9c83c2aa00765072f31f7"}, - {file = "MarkupSafe-2.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:340bea174e9761308703ae988e982005aedf427de816d1afe98147668cc03036"}, - {file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22152d00bf4a9c7c83960521fc558f55a1adbc0631fbb00a9471e097b19d72e1"}, - {file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28057e985dace2f478e042eaa15606c7efccb700797660629da387eb289b9323"}, - {file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca244fa73f50a800cf8c3ebf7fd93149ec37f5cb9596aa8873ae2c1d23498601"}, - {file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d9d971ec1e79906046aa3ca266de79eac42f1dbf3612a05dc9368125952bd1a1"}, - {file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7e007132af78ea9df29495dbf7b5824cb71648d7133cf7848a2a5dd00d36f9ff"}, - {file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7313ce6a199651c4ed9d7e4cfb4aa56fe923b1adf9af3b420ee14e6d9a73df65"}, - {file = "MarkupSafe-2.1.2-cp310-cp310-win32.whl", hash = "sha256:c4a549890a45f57f1ebf99c067a4ad0cb423a05544accaf2b065246827ed9603"}, - {file = "MarkupSafe-2.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:835fb5e38fd89328e9c81067fd642b3593c33e1e17e2fdbf77f5676abb14a156"}, - {file = "MarkupSafe-2.1.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2ec4f2d48ae59bbb9d1f9d7efb9236ab81429a764dedca114f5fdabbc3788013"}, - {file = "MarkupSafe-2.1.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:608e7073dfa9e38a85d38474c082d4281f4ce276ac0010224eaba11e929dd53a"}, - {file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65608c35bfb8a76763f37036547f7adfd09270fbdbf96608be2bead319728fcd"}, - {file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2bfb563d0211ce16b63c7cb9395d2c682a23187f54c3d79bfec33e6705473c6"}, - {file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da25303d91526aac3672ee6d49a2f3db2d9502a4a60b55519feb1a4c7714e07d"}, - {file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9cad97ab29dfc3f0249b483412c85c8ef4766d96cdf9dcf5a1e3caa3f3661cf1"}, - {file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:085fd3201e7b12809f9e6e9bc1e5c96a368c8523fad5afb02afe3c051ae4afcc"}, - {file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1bea30e9bf331f3fef67e0a3877b2288593c98a21ccb2cf29b74c581a4eb3af0"}, - {file = "MarkupSafe-2.1.2-cp311-cp311-win32.whl", hash = "sha256:7df70907e00c970c60b9ef2938d894a9381f38e6b9db73c5be35e59d92e06625"}, - {file = "MarkupSafe-2.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:e55e40ff0cc8cc5c07996915ad367fa47da6b3fc091fdadca7f5403239c5fec3"}, - {file = "MarkupSafe-2.1.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a6e40afa7f45939ca356f348c8e23048e02cb109ced1eb8420961b2f40fb373a"}, - {file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf877ab4ed6e302ec1d04952ca358b381a882fbd9d1b07cccbfd61783561f98a"}, - {file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63ba06c9941e46fa389d389644e2d8225e0e3e5ebcc4ff1ea8506dce646f8c8a"}, - {file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f1cd098434e83e656abf198f103a8207a8187c0fc110306691a2e94a78d0abb2"}, - {file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:55f44b440d491028addb3b88f72207d71eeebfb7b5dbf0643f7c023ae1fba619"}, - {file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:a6f2fcca746e8d5910e18782f976489939d54a91f9411c32051b4aab2bd7c513"}, - {file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0b462104ba25f1ac006fdab8b6a01ebbfbce9ed37fd37fd4acd70c67c973e460"}, - {file = "MarkupSafe-2.1.2-cp37-cp37m-win32.whl", hash = "sha256:7668b52e102d0ed87cb082380a7e2e1e78737ddecdde129acadb0eccc5423859"}, - {file = "MarkupSafe-2.1.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6d6607f98fcf17e534162f0709aaad3ab7a96032723d8ac8750ffe17ae5a0666"}, - {file = "MarkupSafe-2.1.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a806db027852538d2ad7555b203300173dd1b77ba116de92da9afbc3a3be3eed"}, - {file = "MarkupSafe-2.1.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a4abaec6ca3ad8660690236d11bfe28dfd707778e2442b45addd2f086d6ef094"}, - {file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f03a532d7dee1bed20bc4884194a16160a2de9ffc6354b3878ec9682bb623c54"}, - {file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4cf06cdc1dda95223e9d2d3c58d3b178aa5dacb35ee7e3bbac10e4e1faacb419"}, - {file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22731d79ed2eb25059ae3df1dfc9cb1546691cc41f4e3130fe6bfbc3ecbbecfa"}, - {file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f8ffb705ffcf5ddd0e80b65ddf7bed7ee4f5a441ea7d3419e861a12eaf41af58"}, - {file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8db032bf0ce9022a8e41a22598eefc802314e81b879ae093f36ce9ddf39ab1ba"}, - {file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2298c859cfc5463f1b64bd55cb3e602528db6fa0f3cfd568d3605c50678f8f03"}, - {file = "MarkupSafe-2.1.2-cp38-cp38-win32.whl", hash = "sha256:50c42830a633fa0cf9e7d27664637532791bfc31c731a87b202d2d8ac40c3ea2"}, - {file = "MarkupSafe-2.1.2-cp38-cp38-win_amd64.whl", hash = "sha256:bb06feb762bade6bf3c8b844462274db0c76acc95c52abe8dbed28ae3d44a147"}, - {file = "MarkupSafe-2.1.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:99625a92da8229df6d44335e6fcc558a5037dd0a760e11d84be2260e6f37002f"}, - {file = "MarkupSafe-2.1.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8bca7e26c1dd751236cfb0c6c72d4ad61d986e9a41bbf76cb445f69488b2a2bd"}, - {file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40627dcf047dadb22cd25ea7ecfe9cbf3bbbad0482ee5920b582f3809c97654f"}, - {file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40dfd3fefbef579ee058f139733ac336312663c6706d1163b82b3003fb1925c4"}, - {file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:090376d812fb6ac5f171e5938e82e7f2d7adc2b629101cec0db8b267815c85e2"}, - {file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2e7821bffe00aa6bd07a23913b7f4e01328c3d5cc0b40b36c0bd81d362faeb65"}, - {file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:c0a33bc9f02c2b17c3ea382f91b4db0e6cde90b63b296422a939886a7a80de1c"}, - {file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b8526c6d437855442cdd3d87eede9c425c4445ea011ca38d937db299382e6fa3"}, - {file = "MarkupSafe-2.1.2-cp39-cp39-win32.whl", hash = "sha256:137678c63c977754abe9086a3ec011e8fd985ab90631145dfb9294ad09c102a7"}, - {file = "MarkupSafe-2.1.2-cp39-cp39-win_amd64.whl", hash = "sha256:0576fe974b40a400449768941d5d0858cc624e3249dfd1e0c33674e5c7ca7aed"}, - {file = "MarkupSafe-2.1.2.tar.gz", hash = "sha256:abcabc8c2b26036d62d4c746381a6f7cf60aafcc653198ad678306986b09450d"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-win32.whl", hash = "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-win32.whl", hash = "sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-win_amd64.whl", hash = "sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-win32.whl", hash = "sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-win_amd64.whl", hash = "sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-win32.whl", hash = "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-win_amd64.whl", hash = "sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba"}, + {file = "MarkupSafe-2.1.3.tar.gz", hash = "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad"}, ] [[package]] @@ -1366,13 +1316,13 @@ files = [ [[package]] name = "nb-autodoc" -version = "1.0.0a5" -description = "Powerful API Documentation Generator." +version = "1.0.0a7" +description = "Python API documentation tool supporting the modern PEPs and typing features." optional = false python-versions = ">=3.8" files = [ - {file = "nb-autodoc-1.0.0a5.tar.gz", hash = "sha256:9341a2a231f9c1e97a040ee8701ff2e800ba742a1f1e548f7c92fbaa5d618e8b"}, - {file = "nb_autodoc-1.0.0a5-py3-none-any.whl", hash = "sha256:2158758d1d1cc959082f201719f0d343659306ef776546cd60f5b932b0f03488"}, + {file = "nb-autodoc-1.0.0a7.tar.gz", hash = "sha256:16cf127a3574dcd1e7e495ce992406bb2783245062033fef54b741fdf9b29f7e"}, + {file = "nb_autodoc-1.0.0a7-py3-none-any.whl", hash = "sha256:789a17c0fa5e4c071cf65402d59444828b56b245aa7ec01c80640ce6bbe347b3"}, ] [package.dependencies] @@ -1395,13 +1345,13 @@ setuptools = "*" [[package]] name = "nonebug" -version = "0.3.3" +version = "0.3.4" description = "nonebot2 test framework" optional = false python-versions = ">=3.8,<4.0" files = [ - {file = "nonebug-0.3.3-py3-none-any.whl", hash = "sha256:c3e53e9fe0859083512b78b1af5c29c2ba73b86957fac6a028f094a64a04ea5a"}, - {file = "nonebug-0.3.3.tar.gz", hash = "sha256:3ef520e60c9af97fc4f4dbddcc46723aedb8a127b84369b49d2e9a40bea5b799"}, + {file = "nonebug-0.3.4-py3-none-any.whl", hash = "sha256:d6ebbde934d463141497e3162e26371b7e266d39f8cac0aa1bccc0e4542dd48b"}, + {file = "nonebug-0.3.4.tar.gz", hash = "sha256:11d106dff3fe0d5fa029b9745f701770bcc484be048e72722bb17bb00f84753d"}, ] [package.dependencies] @@ -1452,39 +1402,39 @@ files = [ [[package]] name = "pathspec" -version = "0.9.0" +version = "0.11.1" description = "Utility library for gitignore style pattern matching of file paths." optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +python-versions = ">=3.7" files = [ - {file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"}, - {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"}, + {file = "pathspec-0.11.1-py3-none-any.whl", hash = "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293"}, + {file = "pathspec-0.11.1.tar.gz", hash = "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687"}, ] [[package]] name = "platformdirs" -version = "3.5.1" +version = "3.8.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." optional = false python-versions = ">=3.7" files = [ - {file = "platformdirs-3.5.1-py3-none-any.whl", hash = "sha256:e2378146f1964972c03c085bb5662ae80b2b8c06226c54b2ff4aa9483e8a13a5"}, - {file = "platformdirs-3.5.1.tar.gz", hash = "sha256:412dae91f52a6f84830f39a8078cecd0e866cb72294a5c66808e74d5e88d251f"}, + {file = "platformdirs-3.8.0-py3-none-any.whl", hash = "sha256:ca9ed98ce73076ba72e092b23d3c93ea6c4e186b3f1c3dad6edd98ff6ffcca2e"}, + {file = "platformdirs-3.8.0.tar.gz", hash = "sha256:b0cabcb11063d21a0b261d557acb0a9d2126350e63b70cdf7db6347baea456dc"}, ] [package.extras] -docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.2.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] +docs = ["furo (>=2023.5.20)", "proselint (>=0.13)", "sphinx (>=7.0.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4.1)", "pytest-mock (>=3.10)"] [[package]] name = "pluggy" -version = "1.0.0" +version = "1.2.0" description = "plugin and hook calling mechanisms for python" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, - {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, + {file = "pluggy-1.2.0-py3-none-any.whl", hash = "sha256:c2fd55a7d7a3863cba1a013e4e2414658b1d07b6bc57b3919e0c63c9abb99849"}, + {file = "pluggy-1.2.0.tar.gz", hash = "sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3"}, ] [package.extras] @@ -1493,13 +1443,13 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "pre-commit" -version = "3.3.2" +version = "3.3.3" description = "A framework for managing and maintaining multi-language pre-commit hooks." optional = false python-versions = ">=3.8" files = [ - {file = "pre_commit-3.3.2-py2.py3-none-any.whl", hash = "sha256:8056bc52181efadf4aac792b1f4f255dfd2fb5a350ded7335d251a68561e8cb6"}, - {file = "pre_commit-3.3.2.tar.gz", hash = "sha256:66e37bec2d882de1f17f88075047ef8962581f83c234ac08da21a0c58953d1f0"}, + {file = "pre_commit-3.3.3-py2.py3-none-any.whl", hash = "sha256:10badb65d6a38caff29703362271d7dca483d01da88f9d7e05d0b97171c136cb"}, + {file = "pre_commit-3.3.3.tar.gz", hash = "sha256:a2256f489cd913d575c145132ae196fe335da32d91a8294b7afe6622335dd023"}, ] [package.dependencies] @@ -1601,24 +1551,6 @@ cffi = ">=1.5.0" [package.extras] idna = ["idna (>=2.1)"] -[[package]] -name = "pycln" -version = "2.1.4" -description = "A formatter for finding and removing unused import statements." -optional = false -python-versions = ">=3.6.2,<4" -files = [ - {file = "pycln-2.1.4-py3-none-any.whl", hash = "sha256:e541becc3f831e17f89285e7d6a430c6b7f59b434aaa6e46ed08fe8e944f16fc"}, - {file = "pycln-2.1.4.tar.gz", hash = "sha256:223008181056dcde37b4d6ecece488d17f902a2af7fd9bb2ec9d679477d0ccfc"}, -] - -[package.dependencies] -libcst = {version = ">=0.3.10,<0.5.0", markers = "python_version >= \"3.7\""} -pathspec = ">=0.9.0,<0.10.0" -pyyaml = ">=5.3.1,<7.0.0" -tomlkit = ">=0.11.1,<0.12.0" -typer = ">=0.4.1,<0.10.0" - [[package]] name = "pycparser" version = "2.21" @@ -1632,47 +1564,47 @@ files = [ [[package]] name = "pydantic" -version = "1.10.8" +version = "1.10.9" description = "Data validation and settings management using python type hints" optional = false python-versions = ">=3.7" files = [ - {file = "pydantic-1.10.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1243d28e9b05003a89d72e7915fdb26ffd1d39bdd39b00b7dbe4afae4b557f9d"}, - {file = "pydantic-1.10.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c0ab53b609c11dfc0c060d94335993cc2b95b2150e25583bec37a49b2d6c6c3f"}, - {file = "pydantic-1.10.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9613fadad06b4f3bc5db2653ce2f22e0de84a7c6c293909b48f6ed37b83c61f"}, - {file = "pydantic-1.10.8-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:df7800cb1984d8f6e249351139667a8c50a379009271ee6236138a22a0c0f319"}, - {file = "pydantic-1.10.8-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:0c6fafa0965b539d7aab0a673a046466d23b86e4b0e8019d25fd53f4df62c277"}, - {file = "pydantic-1.10.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e82d4566fcd527eae8b244fa952d99f2ca3172b7e97add0b43e2d97ee77f81ab"}, - {file = "pydantic-1.10.8-cp310-cp310-win_amd64.whl", hash = "sha256:ab523c31e22943713d80d8d342d23b6f6ac4b792a1e54064a8d0cf78fd64e800"}, - {file = "pydantic-1.10.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:666bdf6066bf6dbc107b30d034615d2627e2121506c555f73f90b54a463d1f33"}, - {file = "pydantic-1.10.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:35db5301b82e8661fa9c505c800d0990bc14e9f36f98932bb1d248c0ac5cada5"}, - {file = "pydantic-1.10.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f90c1e29f447557e9e26afb1c4dbf8768a10cc676e3781b6a577841ade126b85"}, - {file = "pydantic-1.10.8-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:93e766b4a8226e0708ef243e843105bf124e21331694367f95f4e3b4a92bbb3f"}, - {file = "pydantic-1.10.8-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:88f195f582851e8db960b4a94c3e3ad25692c1c1539e2552f3df7a9e972ef60e"}, - {file = "pydantic-1.10.8-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:34d327c81e68a1ecb52fe9c8d50c8a9b3e90d3c8ad991bfc8f953fb477d42fb4"}, - {file = "pydantic-1.10.8-cp311-cp311-win_amd64.whl", hash = "sha256:d532bf00f381bd6bc62cabc7d1372096b75a33bc197a312b03f5838b4fb84edd"}, - {file = "pydantic-1.10.8-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7d5b8641c24886d764a74ec541d2fc2c7fb19f6da2a4001e6d580ba4a38f7878"}, - {file = "pydantic-1.10.8-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b1f6cb446470b7ddf86c2e57cd119a24959af2b01e552f60705910663af09a4"}, - {file = "pydantic-1.10.8-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c33b60054b2136aef8cf190cd4c52a3daa20b2263917c49adad20eaf381e823b"}, - {file = "pydantic-1.10.8-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1952526ba40b220b912cdc43c1c32bcf4a58e3f192fa313ee665916b26befb68"}, - {file = "pydantic-1.10.8-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:bb14388ec45a7a0dc429e87def6396f9e73c8c77818c927b6a60706603d5f2ea"}, - {file = "pydantic-1.10.8-cp37-cp37m-win_amd64.whl", hash = "sha256:16f8c3e33af1e9bb16c7a91fc7d5fa9fe27298e9f299cff6cb744d89d573d62c"}, - {file = "pydantic-1.10.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1ced8375969673929809d7f36ad322934c35de4af3b5e5b09ec967c21f9f7887"}, - {file = "pydantic-1.10.8-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:93e6bcfccbd831894a6a434b0aeb1947f9e70b7468f274154d03d71fabb1d7c6"}, - {file = "pydantic-1.10.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:191ba419b605f897ede9892f6c56fb182f40a15d309ef0142212200a10af4c18"}, - {file = "pydantic-1.10.8-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:052d8654cb65174d6f9490cc9b9a200083a82cf5c3c5d3985db765757eb3b375"}, - {file = "pydantic-1.10.8-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ceb6a23bf1ba4b837d0cfe378329ad3f351b5897c8d4914ce95b85fba96da5a1"}, - {file = "pydantic-1.10.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f2e754d5566f050954727c77f094e01793bcb5725b663bf628fa6743a5a9108"}, - {file = "pydantic-1.10.8-cp38-cp38-win_amd64.whl", hash = "sha256:6a82d6cda82258efca32b40040228ecf43a548671cb174a1e81477195ed3ed56"}, - {file = "pydantic-1.10.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3e59417ba8a17265e632af99cc5f35ec309de5980c440c255ab1ca3ae96a3e0e"}, - {file = "pydantic-1.10.8-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:84d80219c3f8d4cad44575e18404099c76851bc924ce5ab1c4c8bb5e2a2227d0"}, - {file = "pydantic-1.10.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e4148e635994d57d834be1182a44bdb07dd867fa3c2d1b37002000646cc5459"}, - {file = "pydantic-1.10.8-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:12f7b0bf8553e310e530e9f3a2f5734c68699f42218bf3568ef49cd9b0e44df4"}, - {file = "pydantic-1.10.8-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:42aa0c4b5c3025483240a25b09f3c09a189481ddda2ea3a831a9d25f444e03c1"}, - {file = "pydantic-1.10.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:17aef11cc1b997f9d574b91909fed40761e13fac438d72b81f902226a69dac01"}, - {file = "pydantic-1.10.8-cp39-cp39-win_amd64.whl", hash = "sha256:66a703d1983c675a6e0fed8953b0971c44dba48a929a2000a493c3772eb61a5a"}, - {file = "pydantic-1.10.8-py3-none-any.whl", hash = "sha256:7456eb22ed9aaa24ff3e7b4757da20d9e5ce2a81018c1b3ebd81a0b88a18f3b2"}, - {file = "pydantic-1.10.8.tar.gz", hash = "sha256:1410275520dfa70effadf4c21811d755e7ef9bb1f1d077a21958153a92c8d9ca"}, + {file = "pydantic-1.10.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e692dec4a40bfb40ca530e07805b1208c1de071a18d26af4a2a0d79015b352ca"}, + {file = "pydantic-1.10.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3c52eb595db83e189419bf337b59154bdcca642ee4b2a09e5d7797e41ace783f"}, + {file = "pydantic-1.10.9-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:939328fd539b8d0edf244327398a667b6b140afd3bf7e347cf9813c736211896"}, + {file = "pydantic-1.10.9-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b48d3d634bca23b172f47f2335c617d3fcb4b3ba18481c96b7943a4c634f5c8d"}, + {file = "pydantic-1.10.9-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:f0b7628fb8efe60fe66fd4adadd7ad2304014770cdc1f4934db41fe46cc8825f"}, + {file = "pydantic-1.10.9-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e1aa5c2410769ca28aa9a7841b80d9d9a1c5f223928ca8bec7e7c9a34d26b1d4"}, + {file = "pydantic-1.10.9-cp310-cp310-win_amd64.whl", hash = "sha256:eec39224b2b2e861259d6f3c8b6290d4e0fbdce147adb797484a42278a1a486f"}, + {file = "pydantic-1.10.9-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d111a21bbbfd85c17248130deac02bbd9b5e20b303338e0dbe0faa78330e37e0"}, + {file = "pydantic-1.10.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2e9aec8627a1a6823fc62fb96480abe3eb10168fd0d859ee3d3b395105ae19a7"}, + {file = "pydantic-1.10.9-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:07293ab08e7b4d3c9d7de4949a0ea571f11e4557d19ea24dd3ae0c524c0c334d"}, + {file = "pydantic-1.10.9-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7ee829b86ce984261d99ff2fd6e88f2230068d96c2a582f29583ed602ef3fc2c"}, + {file = "pydantic-1.10.9-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4b466a23009ff5cdd7076eb56aca537c745ca491293cc38e72bf1e0e00de5b91"}, + {file = "pydantic-1.10.9-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7847ca62e581e6088d9000f3c497267868ca2fa89432714e21a4fb33a04d52e8"}, + {file = "pydantic-1.10.9-cp311-cp311-win_amd64.whl", hash = "sha256:7845b31959468bc5b78d7b95ec52fe5be32b55d0d09983a877cca6aedc51068f"}, + {file = "pydantic-1.10.9-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:517a681919bf880ce1dac7e5bc0c3af1e58ba118fd774da2ffcd93c5f96eaece"}, + {file = "pydantic-1.10.9-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67195274fd27780f15c4c372f4ba9a5c02dad6d50647b917b6a92bf00b3d301a"}, + {file = "pydantic-1.10.9-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2196c06484da2b3fded1ab6dbe182bdabeb09f6318b7fdc412609ee2b564c49a"}, + {file = "pydantic-1.10.9-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:6257bb45ad78abacda13f15bde5886efd6bf549dd71085e64b8dcf9919c38b60"}, + {file = "pydantic-1.10.9-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:3283b574b01e8dbc982080d8287c968489d25329a463b29a90d4157de4f2baaf"}, + {file = "pydantic-1.10.9-cp37-cp37m-win_amd64.whl", hash = "sha256:5f8bbaf4013b9a50e8100333cc4e3fa2f81214033e05ac5aa44fa24a98670a29"}, + {file = "pydantic-1.10.9-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b9cd67fb763248cbe38f0593cd8611bfe4b8ad82acb3bdf2b0898c23415a1f82"}, + {file = "pydantic-1.10.9-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f50e1764ce9353be67267e7fd0da08349397c7db17a562ad036aa7c8f4adfdb6"}, + {file = "pydantic-1.10.9-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:73ef93e5e1d3c8e83f1ff2e7fdd026d9e063c7e089394869a6e2985696693766"}, + {file = "pydantic-1.10.9-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:128d9453d92e6e81e881dd7e2484e08d8b164da5507f62d06ceecf84bf2e21d3"}, + {file = "pydantic-1.10.9-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ad428e92ab68798d9326bb3e5515bc927444a3d71a93b4a2ca02a8a5d795c572"}, + {file = "pydantic-1.10.9-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fab81a92f42d6d525dd47ced310b0c3e10c416bbfae5d59523e63ea22f82b31e"}, + {file = "pydantic-1.10.9-cp38-cp38-win_amd64.whl", hash = "sha256:963671eda0b6ba6926d8fc759e3e10335e1dc1b71ff2a43ed2efd6996634dafb"}, + {file = "pydantic-1.10.9-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:970b1bdc6243ef663ba5c7e36ac9ab1f2bfecb8ad297c9824b542d41a750b298"}, + {file = "pydantic-1.10.9-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7e1d5290044f620f80cf1c969c542a5468f3656de47b41aa78100c5baa2b8276"}, + {file = "pydantic-1.10.9-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83fcff3c7df7adff880622a98022626f4f6dbce6639a88a15a3ce0f96466cb60"}, + {file = "pydantic-1.10.9-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0da48717dc9495d3a8f215e0d012599db6b8092db02acac5e0d58a65248ec5bc"}, + {file = "pydantic-1.10.9-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:0a2aabdc73c2a5960e87c3ffebca6ccde88665616d1fd6d3db3178ef427b267a"}, + {file = "pydantic-1.10.9-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9863b9420d99dfa9c064042304868e8ba08e89081428a1c471858aa2af6f57c4"}, + {file = "pydantic-1.10.9-cp39-cp39-win_amd64.whl", hash = "sha256:e7c9900b43ac14110efa977be3da28931ffc74c27e96ee89fbcaaf0b0fe338e1"}, + {file = "pydantic-1.10.9-py3-none-any.whl", hash = "sha256:6cafde02f6699ce4ff643417d1a9223716ec25e228ddc3b436fe7e2d25a1f305"}, + {file = "pydantic-1.10.9.tar.gz", hash = "sha256:95c70da2cd3b6ddf3b9645ecaa8d98f3d80c606624b6d245558d202cd23ea3be"}, ] [package.dependencies] @@ -1696,13 +1628,13 @@ files = [ [[package]] name = "pytest" -version = "7.3.1" +version = "7.4.0" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.7" files = [ - {file = "pytest-7.3.1-py3-none-any.whl", hash = "sha256:3799fa815351fea3a5e96ac7e503a96fa51cc9942c3753cda7651b93c1cfa362"}, - {file = "pytest-7.3.1.tar.gz", hash = "sha256:434afafd78b1d78ed0addf160ad2b77a30d35d4bdf8af234fe621919d9ed15e3"}, + {file = "pytest-7.4.0-py3-none-any.whl", hash = "sha256:78bf16451a2eb8c7a2ea98e32dc119fd2aa758f1d5d66dbf0a59d69a3969df32"}, + {file = "pytest-7.4.0.tar.gz", hash = "sha256:b4bf8c45bd59934ed84001ad51e11b4ee40d40a1229d2c79f9c592b0a3f6bd8a"}, ] [package.dependencies] @@ -1714,7 +1646,7 @@ pluggy = ">=0.12,<2.0" tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} [package.extras] -testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] +testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] [[package]] name = "pytest-asyncio" @@ -1882,15 +1814,41 @@ urllib3 = ">=1.21.1,<3" socks = ["PySocks (>=1.5.6,!=1.5.7)"] use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] +[[package]] +name = "ruff" +version = "0.0.272" +description = "An extremely fast Python linter, written in Rust." +optional = false +python-versions = ">=3.7" +files = [ + {file = "ruff-0.0.272-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:ae9b57546e118660175d45d264b87e9b4c19405c75b587b6e4d21e6a17bf4fdf"}, + {file = "ruff-0.0.272-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:1609b864a8d7ee75a8c07578bdea0a7db75a144404e75ef3162e0042bfdc100d"}, + {file = "ruff-0.0.272-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee76b4f05fcfff37bd6ac209d1370520d509ea70b5a637bdf0a04d0c99e13dff"}, + {file = "ruff-0.0.272-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:48eccf225615e106341a641f826b15224b8a4240b84269ead62f0afd6d7e2d95"}, + {file = "ruff-0.0.272-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:677284430ac539bb23421a2b431b4ebc588097ef3ef918d0e0a8d8ed31fea216"}, + {file = "ruff-0.0.272-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:9c4bfb75456a8e1efe14c52fcefb89cfb8f2a0d31ed8d804b82c6cf2dc29c42c"}, + {file = "ruff-0.0.272-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:86bc788245361a8148ff98667da938a01e1606b28a45e50ac977b09d3ad2c538"}, + {file = "ruff-0.0.272-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:27b2ea68d2aa69fff1b20b67636b1e3e22a6a39e476c880da1282c3e4bf6ee5a"}, + {file = "ruff-0.0.272-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd2bbe337a3f84958f796c77820d55ac2db1e6753f39d1d1baed44e07f13f96d"}, + {file = "ruff-0.0.272-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:d5a208f8ef0e51d4746930589f54f9f92f84bb69a7d15b1de34ce80a7681bc00"}, + {file = "ruff-0.0.272-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:905ff8f3d6206ad56fcd70674453527b9011c8b0dc73ead27618426feff6908e"}, + {file = "ruff-0.0.272-py3-none-musllinux_1_2_i686.whl", hash = "sha256:19643d448f76b1eb8a764719072e9c885968971bfba872e14e7257e08bc2f2b7"}, + {file = "ruff-0.0.272-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:691d72a00a99707a4e0b2846690961157aef7b17b6b884f6b4420a9f25cd39b5"}, + {file = "ruff-0.0.272-py3-none-win32.whl", hash = "sha256:dc406e5d756d932da95f3af082814d2467943631a587339ee65e5a4f4fbe83eb"}, + {file = "ruff-0.0.272-py3-none-win_amd64.whl", hash = "sha256:a37ec80e238ead2969b746d7d1b6b0d31aa799498e9ba4281ab505b93e1f4b28"}, + {file = "ruff-0.0.272-py3-none-win_arm64.whl", hash = "sha256:06b8ee4eb8711ab119db51028dd9f5384b44728c23586424fd6e241a5b9c4a3b"}, + {file = "ruff-0.0.272.tar.gz", hash = "sha256:273a01dc8c3c4fd4c2af7ea7a67c8d39bb09bce466e640dd170034da75d14cab"}, +] + [[package]] name = "setuptools" -version = "67.8.0" +version = "68.0.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.7" files = [ - {file = "setuptools-67.8.0-py3-none-any.whl", hash = "sha256:5df61bf30bb10c6f756eb19e7c9f3b473051f48db77fddbe06ff2ca307df9a6f"}, - {file = "setuptools-67.8.0.tar.gz", hash = "sha256:62642358adc77ffa87233bc4d2354c4b2682d214048f500964dbe760ccedf102"}, + {file = "setuptools-68.0.0-py3-none-any.whl", hash = "sha256:11e52c67415a381d10d6b462ced9cfb97066179f0e871399e006c4ab101fc85f"}, + {file = "setuptools-68.0.0.tar.gz", hash = "sha256:baf1fdb41c6da4cd2eae722e135500da913332ab3f2f5c7d33af9b492acb5235"}, ] [package.extras] @@ -1949,73 +1907,26 @@ files = [ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] -[[package]] -name = "tomlkit" -version = "0.11.8" -description = "Style preserving TOML library" -optional = false -python-versions = ">=3.7" -files = [ - {file = "tomlkit-0.11.8-py3-none-any.whl", hash = "sha256:8c726c4c202bdb148667835f68d68780b9a003a9ec34167b6c673b38eff2a171"}, - {file = "tomlkit-0.11.8.tar.gz", hash = "sha256:9330fc7faa1db67b541b28e62018c17d20be733177d290a13b24c62d1614e0c3"}, -] - -[[package]] -name = "typer" -version = "0.9.0" -description = "Typer, build great CLIs. Easy to code. Based on Python type hints." -optional = false -python-versions = ">=3.6" -files = [ - {file = "typer-0.9.0-py3-none-any.whl", hash = "sha256:5d96d986a21493606a358cae4461bd8cdf83cbf33a5aa950ae629ca3b51467ee"}, - {file = "typer-0.9.0.tar.gz", hash = "sha256:50922fd79aea2f4751a8e0408ff10d2662bd0c8bbfa84755a699f3bada2978b2"}, -] - -[package.dependencies] -click = ">=7.1.1,<9.0.0" -typing-extensions = ">=3.7.4.3" - -[package.extras] -all = ["colorama (>=0.4.3,<0.5.0)", "rich (>=10.11.0,<14.0.0)", "shellingham (>=1.3.0,<2.0.0)"] -dev = ["autoflake (>=1.3.1,<2.0.0)", "flake8 (>=3.8.3,<4.0.0)", "pre-commit (>=2.17.0,<3.0.0)"] -doc = ["cairosvg (>=2.5.2,<3.0.0)", "mdx-include (>=1.4.1,<2.0.0)", "mkdocs (>=1.1.2,<2.0.0)", "mkdocs-material (>=8.1.4,<9.0.0)", "pillow (>=9.3.0,<10.0.0)"] -test = ["black (>=22.3.0,<23.0.0)", "coverage (>=6.2,<7.0)", "isort (>=5.0.6,<6.0.0)", "mypy (==0.910)", "pytest (>=4.4.0,<8.0.0)", "pytest-cov (>=2.10.0,<5.0.0)", "pytest-sugar (>=0.9.4,<0.10.0)", "pytest-xdist (>=1.32.0,<4.0.0)", "rich (>=10.11.0,<14.0.0)", "shellingham (>=1.3.0,<2.0.0)"] - [[package]] name = "typing-extensions" -version = "4.6.2" +version = "4.6.3" description = "Backported and Experimental Type Hints for Python 3.7+" optional = false python-versions = ">=3.7" files = [ - {file = "typing_extensions-4.6.2-py3-none-any.whl", hash = "sha256:3a8b36f13dd5fdc5d1b16fe317f5668545de77fa0b8e02006381fd49d731ab98"}, - {file = "typing_extensions-4.6.2.tar.gz", hash = "sha256:06006244c70ac8ee83fa8282cb188f697b8db25bc8b4df07be1873c43897060c"}, + {file = "typing_extensions-4.6.3-py3-none-any.whl", hash = "sha256:88a4153d8505aabbb4e13aacb7c486c2b4a33ca3b3f807914a9b4c844c471c26"}, + {file = "typing_extensions-4.6.3.tar.gz", hash = "sha256:d91d5919357fe7f681a9f2b5b4cb2a5f1ef0a1e9f59c4d8ff0d3491e05c0ffd5"}, ] -[[package]] -name = "typing-inspect" -version = "0.9.0" -description = "Runtime inspection utilities for typing module." -optional = false -python-versions = "*" -files = [ - {file = "typing_inspect-0.9.0-py3-none-any.whl", hash = "sha256:9ee6fc59062311ef8547596ab6b955e1b8aa46242d854bfc78f4f6b0eff35f9f"}, - {file = "typing_inspect-0.9.0.tar.gz", hash = "sha256:b23fc42ff6f6ef6954e4852c1fb512cdd18dbea03134f91f856a95ccc9461f78"}, -] - -[package.dependencies] -mypy-extensions = ">=0.3.0" -typing-extensions = ">=3.7.4" - [[package]] name = "urllib3" -version = "2.0.2" +version = "2.0.3" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.7" files = [ - {file = "urllib3-2.0.2-py3-none-any.whl", hash = "sha256:d055c2f9d38dc53c808f6fdc8eab7360b6fdbbde02340ed25cfbcd817c62469e"}, - {file = "urllib3-2.0.2.tar.gz", hash = "sha256:61717a1095d7e155cdb737ac7bb2f4324a858a1e2e6466f6d03ff630ca68d3cc"}, + {file = "urllib3-2.0.3-py3-none-any.whl", hash = "sha256:48e7fafa40319d358848e1bc6809b208340fafe2096f1725d05d67443d0483d1"}, + {file = "urllib3-2.0.3.tar.gz", hash = "sha256:bee28b5e56addb8226c96f7f13ac28cb4c301dd5ea8a6ca179c0b9835e032825"}, ] [package.extras] @@ -2095,23 +2006,23 @@ test = ["Cython (>=0.29.32,<0.30.0)", "aiohttp", "flake8 (>=3.9.2,<3.10.0)", "my [[package]] name = "virtualenv" -version = "20.23.0" +version = "20.23.1" description = "Virtual Python Environment builder" optional = false python-versions = ">=3.7" files = [ - {file = "virtualenv-20.23.0-py3-none-any.whl", hash = "sha256:6abec7670e5802a528357fdc75b26b9f57d5d92f29c5462ba0fbe45feacc685e"}, - {file = "virtualenv-20.23.0.tar.gz", hash = "sha256:a85caa554ced0c0afbd0d638e7e2d7b5f92d23478d05d17a76daeac8f279f924"}, + {file = "virtualenv-20.23.1-py3-none-any.whl", hash = "sha256:34da10f14fea9be20e0fd7f04aba9732f84e593dac291b757ce42e3368a39419"}, + {file = "virtualenv-20.23.1.tar.gz", hash = "sha256:8ff19a38c1021c742148edc4f81cb43d7f8c6816d2ede2ab72af5b84c749ade1"}, ] [package.dependencies] distlib = ">=0.3.6,<1" -filelock = ">=3.11,<4" -platformdirs = ">=3.2,<4" +filelock = ">=3.12,<4" +platformdirs = ">=3.5.1,<4" [package.extras] -docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=22.12)"] -test = ["covdefaults (>=2.3)", "coverage (>=7.2.3)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.3.1)", "pytest-env (>=0.8.1)", "pytest-freezegun (>=0.4.2)", "pytest-mock (>=3.10)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=67.7.1)", "time-machine (>=2.9)"] +docs = ["furo (>=2023.5.20)", "proselint (>=0.13)", "sphinx (>=7.0.1)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] +test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.3.1)", "pytest-env (>=0.8.1)", "pytest-freezer (>=0.4.6)", "pytest-mock (>=3.10)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=67.8)", "time-machine (>=2.9)"] [[package]] name = "watchfiles" @@ -2395,4 +2306,4 @@ websockets = ["websockets"] [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "cf0a75f5173e6eb0fa3cd9d8901d4149e104094d08bce7e298d6f8c92954803d" +content-hash = "70f20d112a2bbc1300d2cca814b516f45a190d9837b53d90b9cdb005f64eb180" diff --git a/pyproject.toml b/pyproject.toml index ad2fc24d..8b9fd96e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,7 +43,7 @@ httpx = { version = ">=0.20.0,<1.0.0", extras = ["http2"], optional = true } uvicorn = { version = ">=0.20.0,<1.0.0", extras = ["standard"], optional = true } [tool.poetry.group.dev.dependencies] -pycln = "^2.1.2" +ruff = "^0.0.272" isort = "^5.10.1" black = "^23.1.0" nonemoji = "^0.1.2" @@ -92,9 +92,16 @@ force_sort_within_sections = true src_paths = ["nonebot", "tests"] extra_standard_library = ["typing_extensions"] -[tool.pycln] -path = "." -all = false +[tool.ruff] +select = ["E", "W", "F", "UP", "C", "T", "PYI", "PT", "Q"] +ignore = ["E402", "C901"] + +line-length = 88 +target-version = "py38" + +[tool.ruff.flake8-pytest-style] +fixture-parentheses = false +mark-parentheses = false [tool.pyright] reportShadowedImports = false diff --git a/tests/plugins/_hidden.py b/tests/plugins/_hidden.py index 2cfffa40..934ac3c9 100644 --- a/tests/plugins/_hidden.py +++ b/tests/plugins/_hidden.py @@ -1 +1,3 @@ -assert False +import pytest + +pytest.fail("should not be imported") diff --git a/tests/plugins/nested/__init__.py b/tests/plugins/nested/__init__.py index 6f514513..a62dbd0a 100644 --- a/tests/plugins/nested/__init__.py +++ b/tests/plugins/nested/__init__.py @@ -1,6 +1,5 @@ from pathlib import Path -import nonebot from nonebot.plugin import PluginManager, _managers manager = PluginManager( diff --git a/tests/plugins/nested/plugins/nested_subplugin.py b/tests/plugins/nested/plugins/nested_subplugin.py index 927f0709..e4c8d8fb 100644 --- a/tests/plugins/nested/plugins/nested_subplugin.py +++ b/tests/plugins/nested/plugins/nested_subplugin.py @@ -1 +1 @@ -from .nested_subplugin2 import a # nopycln: import +from .nested_subplugin2 import a # noqa: F401 diff --git a/tests/plugins/param/param_arg.py b/tests/plugins/param/param_arg.py index b2c7c4b0..b137ce91 100644 --- a/tests/plugins/param/param_arg.py +++ b/tests/plugins/param/param_arg.py @@ -1,4 +1,4 @@ -from nonebot.adapters import Event, Message +from nonebot.adapters import Message from nonebot.params import Arg, ArgStr, ArgPlainText diff --git a/tests/plugins/plugin/__init__.py b/tests/plugins/plugin/__init__.py index e8604447..7db755b4 100644 --- a/tests/plugins/plugin/__init__.py +++ b/tests/plugins/plugin/__init__.py @@ -1 +1 @@ -from . import matchers +from . import matchers as matchers diff --git a/tests/plugins/require.py b/tests/plugins/require.py index 8a9084d3..b4225e29 100644 --- a/tests/plugins/require.py +++ b/tests/plugins/require.py @@ -4,4 +4,5 @@ test_require = require("export").test from plugins.export import test -assert test is test_require and test() == "export", "Export Require Error" +assert test is test_require, "Export Require Error" +assert test() == "export", "Export Require Error" diff --git a/tests/test_driver.py b/tests/test_driver.py index d09d3bbf..66394710 100644 --- a/tests/test_driver.py +++ b/tests/test_driver.py @@ -176,7 +176,8 @@ async def test_http_client(driver: Driver, server_url: URL): content="test", ) response = await driver.request(request) - assert response.status_code == 200 and response.content + assert response.status_code == 200 + assert response.content data = json.loads(response.content) assert data["method"] == "POST" assert data["args"] == {"param": "test"} @@ -187,7 +188,8 @@ async def test_http_client(driver: Driver, server_url: URL): # post with data body request = Request("POST", server_url, data={"form": "test"}) response = await driver.request(request) - assert response.status_code == 200 and response.content + assert response.status_code == 200 + assert response.content data = json.loads(response.content) assert data["method"] == "POST" assert data["form"] == {"form": "test"} @@ -195,7 +197,8 @@ async def test_http_client(driver: Driver, server_url: URL): # post with json body request = Request("POST", server_url, json={"json": "test"}) response = await driver.request(request) - assert response.status_code == 200 and response.content + assert response.status_code == 200 + assert response.content data = json.loads(response.content) assert data["method"] == "POST" assert data["json"] == {"json": "test"} @@ -208,7 +211,8 @@ async def test_http_client(driver: Driver, server_url: URL): files={"test": ("test.txt", b"test")}, ) response = await driver.request(request) - assert response.status_code == 200 and response.content + assert response.status_code == 200 + assert response.content data = json.loads(response.content) assert data["method"] == "POST" assert data["form"] == {"form": "test"} @@ -219,7 +223,7 @@ async def test_http_client(driver: Driver, server_url: URL): @pytest.mark.asyncio @pytest.mark.parametrize( - "driver, driver_type", + ("driver", "driver_type"), [ pytest.param( "nonebot.drivers.fastapi:Driver+nonebot.drivers.aiohttp:Mixin", diff --git a/tests/test_init.py b/tests/test_init.py index 2257e415..9040c2d0 100644 --- a/tests/test_init.py +++ b/tests/test_init.py @@ -34,7 +34,7 @@ async def test_init(): async def test_get_driver(app: App, monkeypatch: pytest.MonkeyPatch): with monkeypatch.context() as m: m.setattr(nonebot, "_driver", None) - with pytest.raises(ValueError): + with pytest.raises(ValueError, match="initialized"): get_driver() @@ -63,7 +63,7 @@ async def test_get_adapter(app: App, monkeypatch: pytest.MonkeyPatch): assert get_adapters() == {adapter_name: adapter} assert get_adapter(adapter_name) is adapter assert get_adapter(adapter.__class__) is adapter - with pytest.raises(ValueError): + with pytest.raises(ValueError, match="registered"): get_adapter("not exist") @@ -74,7 +74,8 @@ async def test_run(app: App, monkeypatch: pytest.MonkeyPatch): def mock_run(*args, **kwargs): nonlocal runned runned = True - assert args == ("arg",) and kwargs == {"kwarg": "kwarg"} + assert args == ("arg",) + assert kwargs == {"kwarg": "kwarg"} driver = get_driver() @@ -89,7 +90,7 @@ async def test_run(app: App, monkeypatch: pytest.MonkeyPatch): async def test_get_bot(app: App, monkeypatch: pytest.MonkeyPatch): driver = get_driver() - with pytest.raises(ValueError): + with pytest.raises(ValueError, match="no bots"): get_bot() with monkeypatch.context() as m: diff --git a/tests/test_matcher/test_matcher.py b/tests/test_matcher/test_matcher.py index 72f8dc7a..2e58f69b 100644 --- a/tests/test_matcher/test_matcher.py +++ b/tests/test_matcher/test_matcher.py @@ -120,7 +120,7 @@ async def test_matcher_overload(app: App): async def test_matcher_destroy(app: App): from plugins.matcher.matcher_process import test_destroy - async with app.test_matcher(test_destroy) as ctx: + async with app.test_matcher(test_destroy): assert len(matchers) == 1 assert len(matchers[test_destroy.priority]) == 1 assert matchers[test_destroy.priority][0] is test_destroy diff --git a/tests/test_param.py b/tests/test_param.py index 8abf2dde..1ee0997b 100644 --- a/tests/test_param.py +++ b/tests/test_param.py @@ -33,6 +33,8 @@ from nonebot.consts import ( CMD_WHITESPACE_KEY, ) +UNKNOWN_PARAM = "Unknown parameter" + @pytest.mark.asyncio async def test_depend(app: App): @@ -50,7 +52,8 @@ async def test_depend(app: App): async with app.test_dependent(depends, allow_types=[DependParam]) as ctx: ctx.should_return(1) - assert len(runned) == 1 and runned[0] == 1 + assert len(runned) == 1 + assert runned[0] == 1 runned.clear() @@ -59,7 +62,8 @@ async def test_depend(app: App): event_next = make_fake_event()() ctx.receive_event(bot, event_next) - assert len(runned) == 2 and runned[0] == runned[1] == 1 + assert len(runned) == 2 + assert runned[0] == runned[1] == 1 runned.clear() @@ -105,16 +109,15 @@ async def test_bot(app: App): ctx.pass_params(bot=bot) ctx.should_return(bot) - with pytest.raises(ValueError): - async with app.test_dependent(not_legacy_bot, allow_types=[BotParam]) as ctx: - ... + with pytest.raises(ValueError, match=UNKNOWN_PARAM): + app.test_dependent(not_legacy_bot, allow_types=[BotParam]) async with app.test_dependent(sub_bot, allow_types=[BotParam]) as ctx: bot = ctx.create_bot(base=FooBot) ctx.pass_params(bot=bot) ctx.should_return(bot) - with pytest.raises(TypeMisMatch): + with pytest.raises(TypeMisMatch): # noqa: PT012 async with app.test_dependent(sub_bot, allow_types=[BotParam]) as ctx: bot = ctx.create_bot() ctx.pass_params(bot=bot) @@ -134,9 +137,8 @@ async def test_bot(app: App): ctx.pass_params(bot=bot) ctx.should_return(bot) - with pytest.raises(ValueError): - async with app.test_dependent(not_bot, allow_types=[BotParam]) as ctx: - ... + with pytest.raises(ValueError, match=UNKNOWN_PARAM): + app.test_dependent(not_bot, allow_types=[BotParam]) @pytest.mark.asyncio @@ -169,17 +171,14 @@ async def test_event(app: App): ctx.pass_params(event=fake_event) ctx.should_return(fake_event) - with pytest.raises(ValueError): - async with app.test_dependent( - not_legacy_event, allow_types=[EventParam] - ) as ctx: - ... + with pytest.raises(ValueError, match=UNKNOWN_PARAM): + app.test_dependent(not_legacy_event, allow_types=[EventParam]) async with app.test_dependent(sub_event, allow_types=[EventParam]) as ctx: ctx.pass_params(event=fake_fooevent) ctx.should_return(fake_fooevent) - with pytest.raises(TypeMisMatch): + with pytest.raises(TypeMisMatch): # noqa: PT012 async with app.test_dependent(sub_event, allow_types=[EventParam]) as ctx: ctx.pass_params(event=fake_event) @@ -195,9 +194,8 @@ async def test_event(app: App): ctx.pass_params(event=fake_event) ctx.should_return(fake_event) - with pytest.raises(ValueError): - async with app.test_dependent(not_event, allow_types=[EventParam]) as ctx: - ... + with pytest.raises(ValueError, match=UNKNOWN_PARAM): + app.test_dependent(not_event, allow_types=[EventParam]) async with app.test_dependent( event_type, allow_types=[EventParam, DependParam] @@ -274,11 +272,8 @@ async def test_state(app: App): ctx.pass_params(state=fake_state) ctx.should_return(fake_state) - with pytest.raises(ValueError): - async with app.test_dependent( - not_legacy_state, allow_types=[StateParam] - ) as ctx: - ... + with pytest.raises(ValueError, match=UNKNOWN_PARAM): + app.test_dependent(not_legacy_state, allow_types=[StateParam]) async with app.test_dependent( command, allow_types=[StateParam, DependParam] @@ -398,17 +393,14 @@ async def test_matcher(app: App): ctx.pass_params(matcher=fake_matcher) ctx.should_return(fake_matcher) - with pytest.raises(ValueError): - async with app.test_dependent( - not_legacy_matcher, allow_types=[MatcherParam] - ) as ctx: - ... + with pytest.raises(ValueError, match=UNKNOWN_PARAM): + app.test_dependent(not_legacy_matcher, allow_types=[MatcherParam]) async with app.test_dependent(sub_matcher, allow_types=[MatcherParam]) as ctx: ctx.pass_params(matcher=foo_matcher) ctx.should_return(foo_matcher) - with pytest.raises(TypeMisMatch): + with pytest.raises(TypeMisMatch): # noqa: PT012 async with app.test_dependent(sub_matcher, allow_types=[MatcherParam]) as ctx: ctx.pass_params(matcher=fake_matcher) @@ -426,9 +418,8 @@ async def test_matcher(app: App): ctx.pass_params(matcher=fake_matcher) ctx.should_return(fake_matcher) - with pytest.raises(ValueError): - async with app.test_dependent(not_matcher, allow_types=[MatcherParam]) as ctx: - ... + with pytest.raises(ValueError, match=UNKNOWN_PARAM): + app.test_dependent(not_matcher, allow_types=[MatcherParam]) event = make_fake_event()() fake_matcher.set_receive("test", event) diff --git a/tests/test_permission.py b/tests/test_permission.py index 13c01a44..43342727 100644 --- a/tests/test_permission.py +++ b/tests/test_permission.py @@ -47,15 +47,15 @@ async def test_permission(app: App): async with app.test_api() as ctx: bot = ctx.create_bot() - assert await Permission(falsy)(bot, event) == False - assert await Permission(truthy)(bot, event) == True - assert await Permission(skipped)(bot, event) == False - assert await Permission(truthy, falsy)(bot, event) == True - assert await Permission(truthy, skipped)(bot, event) == True + assert await Permission(falsy)(bot, event) is False + assert await Permission(truthy)(bot, event) is True + assert await Permission(skipped)(bot, event) is False + assert await Permission(truthy, falsy)(bot, event) is True + assert await Permission(truthy, skipped)(bot, event) is True @pytest.mark.asyncio -@pytest.mark.parametrize("type, expected", [("message", True), ("notice", False)]) +@pytest.mark.parametrize(("type", "expected"), [("message", True), ("notice", False)]) async def test_message(type: str, expected: bool): dependent = list(MESSAGE.checkers)[0] checker = dependent.call @@ -67,7 +67,7 @@ async def test_message(type: str, expected: bool): @pytest.mark.asyncio -@pytest.mark.parametrize("type, expected", [("message", False), ("notice", True)]) +@pytest.mark.parametrize(("type", "expected"), [("message", False), ("notice", True)]) async def test_notice(type: str, expected: bool): dependent = list(NOTICE.checkers)[0] checker = dependent.call @@ -79,7 +79,7 @@ async def test_notice(type: str, expected: bool): @pytest.mark.asyncio -@pytest.mark.parametrize("type, expected", [("message", False), ("request", True)]) +@pytest.mark.parametrize(("type", "expected"), [("message", False), ("request", True)]) async def test_request(type: str, expected: bool): dependent = list(REQUEST.checkers)[0] checker = dependent.call @@ -91,7 +91,9 @@ async def test_request(type: str, expected: bool): @pytest.mark.asyncio -@pytest.mark.parametrize("type, expected", [("message", False), ("meta_event", True)]) +@pytest.mark.parametrize( + ("type", "expected"), [("message", False), ("meta_event", True)] +) async def test_metaevent(type: str, expected: bool): dependent = list(METAEVENT.checkers)[0] checker = dependent.call @@ -104,7 +106,7 @@ async def test_metaevent(type: str, expected: bool): @pytest.mark.asyncio @pytest.mark.parametrize( - "type, user_id, expected", + ("type", "user_id", "expected"), [ ("message", "test", True), ("message", "foo", False), @@ -128,7 +130,7 @@ async def test_superuser(app: App, type: str, user_id: str, expected: bool): @pytest.mark.asyncio @pytest.mark.parametrize( - "session_ids, session_id, expected", + ("session_ids", "session_id", "expected"), [ (("user", "foo"), "user", True), (("user", "foo"), "bar", False), diff --git a/tests/test_plugin/test_load.py b/tests/test_plugin/test_load.py index 64aabb85..fcbf3586 100644 --- a/tests/test_plugin/test_load.py +++ b/tests/test_plugin/test_load.py @@ -49,7 +49,9 @@ async def test_load_nested_plugin(): parent_plugin = nonebot.get_plugin("nested") sub_plugin = nonebot.get_plugin("nested_subplugin") sub_plugin2 = nonebot.get_plugin("nested_subplugin2") - assert parent_plugin and sub_plugin and sub_plugin2 + assert parent_plugin + assert sub_plugin + assert sub_plugin2 assert sub_plugin.parent_plugin is parent_plugin assert sub_plugin2.parent_plugin is parent_plugin assert parent_plugin.sub_plugins == {sub_plugin, sub_plugin2} @@ -67,7 +69,7 @@ async def test_load_json(): async def test_load_toml(): nonebot.load_from_toml("./plugins.toml") - with pytest.raises(ValueError): + with pytest.raises(ValueError, match="Cannot find"): nonebot.load_from_toml("./plugins.empty.toml") with pytest.raises(TypeError): diff --git a/tests/test_plugin/test_on.py b/tests/test_plugin/test_on.py index a46a218b..55cc9233 100644 --- a/tests/test_plugin/test_on.py +++ b/tests/test_plugin/test_on.py @@ -20,7 +20,7 @@ from nonebot.rule import ( @pytest.mark.asyncio @pytest.mark.parametrize( - "matcher_name, pre_rule_factory, has_permission", + ("matcher_name", "pre_rule_factory", "has_permission"), [ pytest.param("matcher_on", None, True), pytest.param("matcher_on_metaevent", None, False), diff --git a/tests/test_rule.py b/tests/test_rule.py index aa85725c..c3e5be5d 100644 --- a/tests/test_rule.py +++ b/tests/test_rule.py @@ -74,11 +74,11 @@ async def test_rule(app: App): async with app.test_api() as ctx: bot = ctx.create_bot() - assert await Rule(falsy)(bot, event, {}) == False - assert await Rule(truthy)(bot, event, {}) == True - assert await Rule(skipped)(bot, event, {}) == False - assert await Rule(truthy, falsy)(bot, event, {}) == False - assert await Rule(truthy, skipped)(bot, event, {}) == False + assert await Rule(falsy)(bot, event, {}) is False + assert await Rule(truthy)(bot, event, {}) is True + assert await Rule(skipped)(bot, event, {}) is False + assert await Rule(truthy, falsy)(bot, event, {}) is False + assert await Rule(truthy, skipped)(bot, event, {}) is False @pytest.mark.asyncio @@ -118,7 +118,7 @@ async def test_trie(app: App): @pytest.mark.asyncio @pytest.mark.parametrize( - "msg, ignorecase, type, text, expected", + ("msg", "ignorecase", "type", "text", "expected"), [ ("prefix", False, "message", "prefix_", True), ("prefix", False, "message", "Prefix_", False), @@ -158,7 +158,7 @@ async def test_startswith( @pytest.mark.asyncio @pytest.mark.parametrize( - "msg, ignorecase, type, text, expected", + ("msg", "ignorecase", "type", "text", "expected"), [ ("suffix", False, "message", "_suffix", True), ("suffix", False, "message", "_Suffix", False), @@ -198,7 +198,7 @@ async def test_endswith( @pytest.mark.asyncio @pytest.mark.parametrize( - "msg, ignorecase, type, text, expected", + ("msg", "ignorecase", "type", "text", "expected"), [ ("fullmatch", False, "message", "fullmatch", True), ("fullmatch", False, "message", "Fullmatch", False), @@ -238,7 +238,7 @@ async def test_fullmatch( @pytest.mark.asyncio @pytest.mark.parametrize( - "kws, type, text, expected", + ("kws", "type", "text", "expected"), [ (("key",), "message", "_key_", True), (("key", "foo"), "message", "_foo_", True), @@ -270,26 +270,26 @@ async def test_keyword( @pytest.mark.asyncio @pytest.mark.parametrize( - "cmds, force_whitespace, cmd, whitespace, arg_text, expected", + ("cmds", "force_whitespace", "cmd", "whitespace", "arg_text", "expected"), [ # command tests - [(("help",),), None, ("help",), None, None, True], - [(("help",),), None, ("foo",), None, None, False], - [(("help", "foo"),), None, ("help", "foo"), None, None, True], - [(("help", "foo"),), None, ("help", "bar"), None, None, False], - [(("help",), ("foo",)), None, ("help",), None, None, True], - [(("help",), ("foo",)), None, ("bar",), None, None, False], + ((("help",),), None, ("help",), None, None, True), + ((("help",),), None, ("foo",), None, None, False), + ((("help", "foo"),), None, ("help", "foo"), None, None, True), + ((("help", "foo"),), None, ("help", "bar"), None, None, False), + ((("help",), ("foo",)), None, ("help",), None, None, True), + ((("help",), ("foo",)), None, ("bar",), None, None, False), # whitespace tests - [(("help",),), True, ("help",), " ", "arg", True], - [(("help",),), True, ("help",), None, "arg", False], - [(("help",),), True, ("help",), None, None, True], - [(("help",),), False, ("help",), " ", "arg", False], - [(("help",),), False, ("help",), None, "arg", True], - [(("help",),), False, ("help",), None, None, True], - [(("help",),), " ", ("help",), " ", "arg", True], - [(("help",),), " ", ("help",), "\n", "arg", False], - [(("help",),), " ", ("help",), None, "arg", False], - [(("help",),), " ", ("help",), None, None, True], + ((("help",),), True, ("help",), " ", "arg", True), + ((("help",),), True, ("help",), None, "arg", False), + ((("help",),), True, ("help",), None, None, True), + ((("help",),), False, ("help",), " ", "arg", False), + ((("help",),), False, ("help",), None, "arg", True), + ((("help",),), False, ("help",), None, None, True), + ((("help",),), " ", ("help",), " ", "arg", True), + ((("help",),), " ", ("help",), "\n", "arg", False), + ((("help",),), " ", ("help",), None, "arg", False), + ((("help",),), " ", ("help",), None, None, True), ], ) async def test_command( @@ -424,7 +424,7 @@ async def test_shell_command(): @pytest.mark.asyncio @pytest.mark.parametrize( - "pattern, type, text, expected, matched", + ("pattern", "type", "text", "expected", "matched"), [ ( r"(?Pkey\d)", diff --git a/tests/test_single_session.py b/tests/test_single_session.py index 1a2bc67f..cdc35099 100644 --- a/tests/test_single_session.py +++ b/tests/test_single_session.py @@ -16,21 +16,21 @@ async def test_matcher_mutex(): event_3 = make_fake_event(_session_id=None)() async with am(event) as ctx: - assert ctx == False + assert ctx is False assert not _running_matcher async with am(event) as ctx: async with am(event_1) as ctx_1: - assert ctx == False - assert ctx_1 == True + assert ctx is False + assert ctx_1 is True assert not _running_matcher async with am(event) as ctx: async with am(event_2) as ctx_2: - assert ctx == False - assert ctx_2 == False + assert ctx is False + assert ctx_2 is False assert not _running_matcher async with am(event_3) as ctx_3: - assert ctx_3 == False + assert ctx_3 is False assert not _running_matcher diff --git a/tests/test_utils.py b/tests/test_utils.py index 607dbdfa..fbcdeaff 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -118,7 +118,9 @@ def test_dataclass_encoder(): ms = FakeMessageSegment.nested(FakeMessage(FakeMessageSegment.text("text"))) s = json.dumps(ms, cls=DataclassEncoder) - assert ( - s - == '{"type": "node", "data": {"content": [{"type": "text", "data": {"text": "text"}}]}}' + assert s == ( + "{" + '"type": "node", ' + '"data": {"content": [{"type": "text", "data": {"text": "text"}}]}' + "}" )