From 9ff7f4baba0c6ab2b55dade6a430a0f87d3a99d8 Mon Sep 17 00:00:00 2001 From: uy/sun Date: Thu, 7 Mar 2024 14:57:26 +0800 Subject: [PATCH] =?UTF-8?q?:technologist:=20Develop:=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=20ruff=20RUF=20=E8=A7=84=E5=88=99=20(#2598)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ju4tCode <42488585+yanyongyu@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- nonebot/internal/adapter/bot.py | 6 +-- nonebot/internal/adapter/event.py | 2 +- nonebot/internal/adapter/template.py | 2 +- nonebot/internal/driver/abstract.py | 8 ++-- nonebot/internal/matcher/matcher.py | 16 +++---- nonebot/internal/permission.py | 8 ++-- nonebot/internal/rule.py | 6 +-- nonebot/plugin/manager.py | 2 +- poetry.lock | 64 ++++++++++++++-------------- pyproject.toml | 25 +++++++++-- tests/plugins/param/param_depend.py | 4 +- tests/test_config.py | 4 +- tests/test_driver.py | 4 +- tests/test_matcher/test_matcher.py | 6 +-- tests/test_param.py | 4 +- tests/test_permission.py | 12 +++--- tests/test_rule.py | 32 +++++++------- yarn.lock | 10 ++--- 19 files changed, 118 insertions(+), 99 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1a2ced72..5741248c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,7 +7,7 @@ ci: autoupdate_commit_msg: ":arrow_up: auto update by pre-commit hooks" repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.2.0 + rev: v0.3.0 hooks: - id: ruff args: [--fix, --exit-non-zero-on-fix] diff --git a/nonebot/internal/adapter/bot.py b/nonebot/internal/adapter/bot.py index 690a8e65..663d91cc 100644 --- a/nonebot/internal/adapter/bot.py +++ b/nonebot/internal/adapter/bot.py @@ -1,7 +1,7 @@ import abc import asyncio from functools import partial -from typing import TYPE_CHECKING, Any, Set, Union, Optional, Protocol +from typing import TYPE_CHECKING, Any, Set, Union, ClassVar, Optional, Protocol from nonebot.log import logger from nonebot.config import Config @@ -27,9 +27,9 @@ class Bot(abc.ABC): self_id: 机器人 ID """ - _calling_api_hook: Set[T_CallingAPIHook] = set() + _calling_api_hook: ClassVar[Set[T_CallingAPIHook]] = set() """call_api 时执行的函数""" - _called_api_hook: Set[T_CalledAPIHook] = set() + _called_api_hook: ClassVar[Set[T_CalledAPIHook]] = set() """call_api 后执行的函数""" def __init__(self, adapter: "Adapter", self_id: str): diff --git a/nonebot/internal/adapter/event.py b/nonebot/internal/adapter/event.py index 635e7d70..a8b71e8c 100644 --- a/nonebot/internal/adapter/event.py +++ b/nonebot/internal/adapter/event.py @@ -20,7 +20,7 @@ class Event(abc.ABC, BaseModel): class Config(ConfigDict): extra = "allow" # type: ignore - json_encoders = {Message: DataclassEncoder} + json_encoders = {Message: DataclassEncoder} # noqa: RUF012 if not PYDANTIC_V2: # pragma: pydantic-v1 diff --git a/nonebot/internal/adapter/template.py b/nonebot/internal/adapter/template.py index fd05b055..9dcb2e0c 100644 --- a/nonebot/internal/adapter/template.py +++ b/nonebot/internal/adapter/template.py @@ -25,7 +25,7 @@ from _string import formatter_field_name_split # type: ignore if TYPE_CHECKING: from .message import Message, MessageSegment - def formatter_field_name_split( # noqa: F811 + def formatter_field_name_split( field_name: str, ) -> Tuple[str, List[Tuple[bool, str]]]: ... diff --git a/nonebot/internal/driver/abstract.py b/nonebot/internal/driver/abstract.py index e7191495..59aac425 100644 --- a/nonebot/internal/driver/abstract.py +++ b/nonebot/internal/driver/abstract.py @@ -2,7 +2,7 @@ import abc import asyncio from typing_extensions import TypeAlias from contextlib import AsyncExitStack, asynccontextmanager -from typing import TYPE_CHECKING, Any, Set, Dict, Type, AsyncGenerator +from typing import TYPE_CHECKING, Any, Set, Dict, Type, ClassVar, AsyncGenerator from nonebot.log import logger from nonebot.config import Env, Config @@ -36,11 +36,11 @@ class Driver(abc.ABC): config: 包含配置信息的 Config 对象 """ - _adapters: Dict[str, "Adapter"] = {} + _adapters: ClassVar[Dict[str, "Adapter"]] = {} """已注册的适配器列表""" - _bot_connection_hook: Set[Dependent[Any]] = set() + _bot_connection_hook: ClassVar[Set[Dependent[Any]]] = set() """Bot 连接建立时执行的函数""" - _bot_disconnection_hook: Set[Dependent[Any]] = set() + _bot_disconnection_hook: ClassVar[Set[Dependent[Any]]] = set() """Bot 连接断开时执行的函数""" def __init__(self, env: Env, config: Config): diff --git a/nonebot/internal/matcher/matcher.py b/nonebot/internal/matcher/matcher.py index bfcd6310..5410017f 100644 --- a/nonebot/internal/matcher/matcher.py +++ b/nonebot/internal/matcher/matcher.py @@ -141,7 +141,7 @@ class Matcher(metaclass=MatcherMeta): """事件响应器匹配规则""" permission: ClassVar[Permission] = Permission() """事件响应器触发权限""" - handlers: List[Dependent[Any]] = [] + handlers: ClassVar[List[Dependent[Any]]] = [] """事件响应器拥有的事件处理函数列表""" priority: ClassVar[int] = 1 """事件响应器优先级""" @@ -171,7 +171,7 @@ class Matcher(metaclass=MatcherMeta): ) def __init__(self): - self.handlers = self.handlers.copy() + self.remain_handlers: List[Dependent[Any]] = self.handlers.copy() self.state = self._default_state.copy() def __repr__(self) -> str: @@ -457,7 +457,7 @@ class Matcher(metaclass=MatcherMeta): parameterless: 非参数类型依赖列表 """ - async def _receive(event: Event, matcher: "Matcher") -> Union[None, NoReturn]: + async def _receive(event: Event, matcher: "Matcher") -> None: matcher.set_target(RECEIVE_KEY.format(id=id)) if matcher.get_target() == RECEIVE_KEY.format(id=id): matcher.set_receive(id, event) @@ -775,7 +775,7 @@ class Matcher(metaclass=MatcherMeta): async def resolve_reject(self): handler = current_handler.get() - self.handlers.insert(0, handler) + self.remain_handlers.insert(0, handler) if REJECT_CACHE_TARGET in self.state: self.state[REJECT_TARGET] = self.state[REJECT_CACHE_TARGET] @@ -809,8 +809,8 @@ class Matcher(metaclass=MatcherMeta): # Refresh preprocess state self.state.update(state) - while self.handlers: - handler = self.handlers.pop(0) + while self.remain_handlers: + handler = self.remain_handlers.pop(0) current_handler.set(handler) logger.debug(f"Running handler {handler}") try: @@ -852,7 +852,7 @@ class Matcher(metaclass=MatcherMeta): type_, Rule(), permission, - self.handlers, + self.remain_handlers, temp=True, priority=0, block=True, @@ -872,7 +872,7 @@ class Matcher(metaclass=MatcherMeta): type_, Rule(), permission, - self.handlers, + self.remain_handlers, temp=True, priority=0, block=True, diff --git a/nonebot/internal/permission.py b/nonebot/internal/permission.py index 2386f38b..200dae49 100644 --- a/nonebot/internal/permission.py +++ b/nonebot/internal/permission.py @@ -1,7 +1,7 @@ import asyncio from typing_extensions import Self from contextlib import AsyncExitStack -from typing import Set, Tuple, Union, NoReturn, Optional +from typing import Set, List, Type, Tuple, Union, ClassVar, NoReturn, Optional from nonebot.dependencies import Dependent from nonebot.utils import run_coro_with_catch @@ -9,7 +9,7 @@ from nonebot.exception import SkippedException from nonebot.typing import T_DependencyCache, T_PermissionChecker from .adapter import Bot, Event -from .params import BotParam, EventParam, DependParam, DefaultParam +from .params import Param, BotParam, EventParam, DependParam, DefaultParam class Permission: @@ -30,7 +30,7 @@ class Permission: __slots__ = ("checkers",) - HANDLER_PARAM_TYPES = [ + HANDLER_PARAM_TYPES: ClassVar[List[Type[Param]]] = [ DependParam, BotParam, EventParam, @@ -146,7 +146,7 @@ class User: @classmethod def _clean_permission(cls, perm: Permission) -> Optional[Permission]: if len(perm.checkers) == 1 and isinstance( - user_perm := tuple(perm.checkers)[0].call, cls + user_perm := next(iter(perm.checkers)).call, cls ): return user_perm.perm return perm diff --git a/nonebot/internal/rule.py b/nonebot/internal/rule.py index c35a78ff..1db0ac51 100644 --- a/nonebot/internal/rule.py +++ b/nonebot/internal/rule.py @@ -1,13 +1,13 @@ import asyncio from contextlib import AsyncExitStack -from typing import Set, Union, NoReturn, Optional +from typing import Set, List, Type, Union, ClassVar, NoReturn, Optional from nonebot.dependencies import Dependent from nonebot.exception import SkippedException from nonebot.typing import T_State, T_RuleChecker, T_DependencyCache from .adapter import Bot, Event -from .params import BotParam, EventParam, StateParam, DependParam, DefaultParam +from .params import Param, BotParam, EventParam, StateParam, DependParam, DefaultParam class Rule: @@ -28,7 +28,7 @@ class Rule: __slots__ = ("checkers",) - HANDLER_PARAM_TYPES = [ + HANDLER_PARAM_TYPES: ClassVar[List[Type[Param]]] = [ DependParam, BotParam, EventParam, diff --git a/nonebot/plugin/manager.py b/nonebot/plugin/manager.py index adbc5b67..20eba65f 100644 --- a/nonebot/plugin/manager.py +++ b/nonebot/plugin/manager.py @@ -236,7 +236,7 @@ class PluginLoader(SourceFileLoader): break # enter plugin context - _plugin_token = _current_plugin_chain.set(parent_plugins + (plugin,)) + _plugin_token = _current_plugin_chain.set((*parent_plugins, plugin)) try: super().exec_module(module) diff --git a/poetry.lock b/poetry.lock index e7d637dc..f80e5c95 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. [[package]] name = "aiodns" @@ -757,13 +757,13 @@ testing = ["hatch", "pre-commit", "pytest", "tox"] [[package]] name = "fastapi" -version = "0.109.2" +version = "0.110.0" description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" optional = true python-versions = ">=3.8" files = [ - {file = "fastapi-0.109.2-py3-none-any.whl", hash = "sha256:2c9bab24667293b501cad8dd388c05240c850b58ec5876ee3283c47d6e1e3a4d"}, - {file = "fastapi-0.109.2.tar.gz", hash = "sha256:f3817eac96fe4f65a2ebb4baa000f394e55f5fccdaf7f75250804bc58f354f73"}, + {file = "fastapi-0.110.0-py3-none-any.whl", hash = "sha256:87a1f6fb632a218222c5984be540055346a8f5d8a68e8f6fb647b1dc9934de4b"}, + {file = "fastapi-0.110.0.tar.gz", hash = "sha256:266775f0dcc95af9d3ef39bad55cff525329a931d5fd51930aadd4f428bf7ff3"}, ] [package.dependencies] @@ -1631,13 +1631,13 @@ files = [ [[package]] name = "pydantic" -version = "2.6.2" +version = "2.6.3" description = "Data validation using Python type hints" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic-2.6.2-py3-none-any.whl", hash = "sha256:37a5432e54b12fecaa1049c5195f3d860a10e01bdfd24f1840ef14bd0d3aeab3"}, - {file = "pydantic-2.6.2.tar.gz", hash = "sha256:a09be1c3d28f3abe37f8a78af58284b236a92ce520105ddc91a6d29ea1176ba7"}, + {file = "pydantic-2.6.3-py3-none-any.whl", hash = "sha256:72c6034df47f46ccdf81869fddb81aade68056003900a8724a4f160700016a2a"}, + {file = "pydantic-2.6.3.tar.gz", hash = "sha256:e07805c4c7f5c6826e33a1d4c9d47950d7eaf34868e2690f8594d2e30241f11f"}, ] [package.dependencies] @@ -1953,28 +1953,28 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "ruff" -version = "0.2.2" +version = "0.3.1" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" files = [ - {file = "ruff-0.2.2-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:0a9efb032855ffb3c21f6405751d5e147b0c6b631e3ca3f6b20f917572b97eb6"}, - {file = "ruff-0.2.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:d450b7fbff85913f866a5384d8912710936e2b96da74541c82c1b458472ddb39"}, - {file = "ruff-0.2.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ecd46e3106850a5c26aee114e562c329f9a1fbe9e4821b008c4404f64ff9ce73"}, - {file = "ruff-0.2.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e22676a5b875bd72acd3d11d5fa9075d3a5f53b877fe7b4793e4673499318ba"}, - {file = "ruff-0.2.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1695700d1e25a99d28f7a1636d85bafcc5030bba9d0578c0781ba1790dbcf51c"}, - {file = "ruff-0.2.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:b0c232af3d0bd8f521806223723456ffebf8e323bd1e4e82b0befb20ba18388e"}, - {file = "ruff-0.2.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f63d96494eeec2fc70d909393bcd76c69f35334cdbd9e20d089fb3f0640216ca"}, - {file = "ruff-0.2.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6a61ea0ff048e06de273b2e45bd72629f470f5da8f71daf09fe481278b175001"}, - {file = "ruff-0.2.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e1439c8f407e4f356470e54cdecdca1bd5439a0673792dbe34a2b0a551a2fe3"}, - {file = "ruff-0.2.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:940de32dc8853eba0f67f7198b3e79bc6ba95c2edbfdfac2144c8235114d6726"}, - {file = "ruff-0.2.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:0c126da55c38dd917621552ab430213bdb3273bb10ddb67bc4b761989210eb6e"}, - {file = "ruff-0.2.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:3b65494f7e4bed2e74110dac1f0d17dc8e1f42faaa784e7c58a98e335ec83d7e"}, - {file = "ruff-0.2.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:1ec49be4fe6ddac0503833f3ed8930528e26d1e60ad35c2446da372d16651ce9"}, - {file = "ruff-0.2.2-py3-none-win32.whl", hash = "sha256:d920499b576f6c68295bc04e7b17b6544d9d05f196bb3aac4358792ef6f34325"}, - {file = "ruff-0.2.2-py3-none-win_amd64.whl", hash = "sha256:cc9a91ae137d687f43a44c900e5d95e9617cb37d4c989e462980ba27039d239d"}, - {file = "ruff-0.2.2-py3-none-win_arm64.whl", hash = "sha256:c9d15fc41e6054bfc7200478720570078f0b41c9ae4f010bcc16bd6f4d1aacdd"}, - {file = "ruff-0.2.2.tar.gz", hash = "sha256:e62ed7f36b3068a30ba39193a14274cd706bc486fad521276458022f7bccb31d"}, + {file = "ruff-0.3.1-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:6b82e3937d0d76554cd5796bc3342a7d40de44494d29ff490022d7a52c501744"}, + {file = "ruff-0.3.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ae7954c8f692b70e6a206087ae3988acc9295d84c550f8d90b66c62424c16771"}, + {file = "ruff-0.3.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b730f56ccf91225da0f06cfe421e83b8cc27b2a79393db9c3df02ed7e2bbc01"}, + {file = "ruff-0.3.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c78bfa85637668f47bd82aa2ae17de2b34221ac23fea30926f6409f9e37fc927"}, + {file = "ruff-0.3.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6abaad602d6e6daaec444cbf4d9364df0a783e49604c21499f75bb92237d4af"}, + {file = "ruff-0.3.1-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:5f0c21b6914c3c9a25a59497cbb1e5b6c2d8d9beecc9b8e03ee986e24eee072e"}, + {file = "ruff-0.3.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:434c3fc72e6311c85cd143c4c448b0e60e025a9ac1781e63ba222579a8c29200"}, + {file = "ruff-0.3.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78a7025e6312cbba496341da5062e7cdd47d95f45c1b903e635cdeb1ba5ec2b9"}, + {file = "ruff-0.3.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:52b02bb46f1a79b0c1fa93f6495bc7e77e4ef76e6c28995b4974a20ed09c0833"}, + {file = "ruff-0.3.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:11b5699c42f7d0b771c633d620f2cb22e727fb226273aba775a91784a9ed856c"}, + {file = "ruff-0.3.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:54e5dca3e411772b51194b3102b5f23b36961e8ede463776b289b78180df71a0"}, + {file = "ruff-0.3.1-py3-none-musllinux_1_2_i686.whl", hash = "sha256:951efb610c5844e668bbec4f71cf704f8645cf3106e13f283413969527ebfded"}, + {file = "ruff-0.3.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:09c7333b25e983aabcf6e38445252cff0b4745420fc3bda45b8fce791cc7e9ce"}, + {file = "ruff-0.3.1-py3-none-win32.whl", hash = "sha256:d937f9b99ebf346e0606c3faf43c1e297a62ad221d87ef682b5bdebe199e01f6"}, + {file = "ruff-0.3.1-py3-none-win_amd64.whl", hash = "sha256:c0318a512edc9f4e010bbaab588b5294e78c5cdc9b02c3d8ab2d77c7ae1903e3"}, + {file = "ruff-0.3.1-py3-none-win_arm64.whl", hash = "sha256:d3b60e44240f7e903e6dbae3139a65032ea4c6f2ad99b6265534ff1b83c20afa"}, + {file = "ruff-0.3.1.tar.gz", hash = "sha256:d30db97141fc2134299e6e983a6727922c9e03c031ae4883a6d69461de722ae7"}, ] [[package]] @@ -1995,13 +1995,13 @@ testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jar [[package]] name = "sniffio" -version = "1.3.0" +version = "1.3.1" description = "Sniff out which async library your code is running under" optional = true python-versions = ">=3.7" files = [ - {file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"}, - {file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"}, + {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, + {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, ] [[package]] @@ -2049,13 +2049,13 @@ files = [ [[package]] name = "typing-extensions" -version = "4.9.0" +version = "4.10.0" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" files = [ - {file = "typing_extensions-4.9.0-py3-none-any.whl", hash = "sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd"}, - {file = "typing_extensions-4.9.0.tar.gz", hash = "sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783"}, + {file = "typing_extensions-4.10.0-py3-none-any.whl", hash = "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475"}, + {file = "typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb"}, ] [[package]] @@ -2518,4 +2518,4 @@ websockets = ["websockets"] [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "740f50b322feb17536a68f1d5b25599174afb36de5fd0aa0eac6a75d2e155902" +content-hash = "7ca525ddb55760c80c17925d88ae4eabf0c7beb7f61c4d3f75810080a11b9cea" diff --git a/pyproject.toml b/pyproject.toml index dfac6d53..ea02c2a7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,7 +44,7 @@ uvicorn = { version = ">=0.20.0,<1.0.0", extras = [ ], optional = true } [tool.poetry.group.dev.dependencies] -ruff = "^0.2.0" +ruff = "^0.3.0" isort = "^5.10.1" black = "^24.0.0" nonemoji = "^0.1.2" @@ -90,8 +90,27 @@ line-length = 88 target-version = "py38" [tool.ruff.lint] -select = ["E", "W", "F", "UP", "C", "T", "PYI", "PT", "Q"] -ignore = ["E402", "C901", "UP037"] +select = [ + "F", # Pyflakes + "W", # pycodestyle warnings + "E", # pycodestyle errors + "UP", # pyupgrade + "ASYNC", # flake8-async + "C4", # flake8-comprehensions + "T10", # flake8-debugger + "T20", # flake8-print + "PYI", # flake8-pyi + "PT", # flake8-pytest-style + "Q", # flake8-quotes + "RUF", # Ruff-specific rules +] +ignore = [ + "E402", # module-import-not-at-top-of-file + "UP037", # quoted-annotation + "RUF001", # ambiguous-unicode-character-string + "RUF002", # ambiguous-unicode-character-docstring + "RUF003", # ambiguous-unicode-character-comment +] [tool.ruff.lint.flake8-pytest-style] fixture-parentheses = false diff --git a/tests/plugins/param/param_depend.py b/tests/plugins/param/param_depend.py index 8599f845..205a2a53 100644 --- a/tests/plugins/param/param_depend.py +++ b/tests/plugins/param/param_depend.py @@ -32,8 +32,8 @@ async def gen_async(): @dataclass class ClassDependency: - x: int = Depends(gen_sync) - y: int = Depends(gen_async) + x: int = Depends(gen_sync) # noqa: RUF009 + y: int = Depends(gen_async) # noqa: RUF009 class FooBot(Bot): ... diff --git a/tests/test_config.py b/tests/test_config.py index 15748502..57fc4afc 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -1,7 +1,7 @@ from typing import List, Union, Optional import pytest -from pydantic import BaseModel +from pydantic import Field, BaseModel from nonebot.config import DOTENV_TYPE, BaseSettings, SettingsError @@ -18,7 +18,7 @@ class Example(BaseSettings): _env_nested_delimiter: Optional[str] = "__" simple: str = "" - complex: List[int] = [1] + complex: List[int] = Field(default=[1]) complex_none: Optional[List[int]] = None complex_union: Union[int, List[int]] = 1 nested: Simple = Simple() diff --git a/tests/test_driver.py b/tests/test_driver.py index 958536b7..8b30da18 100644 --- a/tests/test_driver.py +++ b/tests/test_driver.py @@ -409,9 +409,9 @@ async def test_bot_connect_hook(app: App, driver: Driver): disconn_should_be_called = True - if conn_hook not in {hook.call for hook in conn_hooks}: + if conn_hook not in {hook.call for hook in conn_hooks}: # type: ignore pytest.fail("on_bot_connect hook not registered") - if disconn_hook not in {hook.call for hook in disconn_hooks}: + if disconn_hook not in {hook.call for hook in disconn_hooks}: # type: ignore pytest.fail("on_bot_disconnect hook not registered") async with app.test_api() as ctx: diff --git a/tests/test_matcher/test_matcher.py b/tests/test_matcher/test_matcher.py index 89fc1df6..36bc36d0 100644 --- a/tests/test_matcher/test_matcher.py +++ b/tests/test_matcher/test_matcher.py @@ -244,7 +244,7 @@ async def test_default_permission_updater(app: App): matcher = test_permission_updater() new_perm = await matcher.update_permission(bot, event) assert len(new_perm.checkers) == 1 - checker = list(new_perm.checkers)[0].call + checker = next(iter(new_perm.checkers)).call assert isinstance(checker, User) assert checker.users == ("test",) assert checker.perm is default_permission @@ -258,7 +258,7 @@ async def test_user_permission_updater(app: App): ) event = make_fake_event(_session_id="test")() - user_permission = list(test_user_permission_updater.permission.checkers)[0].call + user_permission = next(iter(test_user_permission_updater.permission.checkers)).call assert isinstance(user_permission, User) assert user_permission.perm is default_permission async with app.test_api() as ctx: @@ -266,7 +266,7 @@ async def test_user_permission_updater(app: App): matcher = test_user_permission_updater() new_perm = await matcher.update_permission(bot, event) assert len(new_perm.checkers) == 1 - checker = list(new_perm.checkers)[0].call + checker = next(iter(new_perm.checkers)).call assert isinstance(checker, User) assert checker.users == ("test",) assert checker.perm is default_permission diff --git a/tests/test_param.py b/tests/test_param.py index 65674259..8a8b9008 100644 --- a/tests/test_param.py +++ b/tests/test_param.py @@ -212,7 +212,7 @@ async def test_event(app: App): ctx.pass_params(event=fake_fooevent) ctx.should_return(fake_fooevent) - with pytest.raises(TypeMisMatch): # noqa: PT012 + with pytest.raises(TypeMisMatch): async with app.test_dependent(sub_event, allow_types=[EventParam]) as ctx: ctx.pass_params(event=fake_event) @@ -436,7 +436,7 @@ async def test_matcher(app: App): ctx.pass_params(matcher=foo_matcher) ctx.should_return(foo_matcher) - with pytest.raises(TypeMisMatch): # noqa: PT012 + with pytest.raises(TypeMisMatch): async with app.test_dependent(sub_matcher, allow_types=[MatcherParam]) as ctx: ctx.pass_params(matcher=fake_matcher) diff --git a/tests/test_permission.py b/tests/test_permission.py index 43342727..ff1c89a3 100644 --- a/tests/test_permission.py +++ b/tests/test_permission.py @@ -57,7 +57,7 @@ async def test_permission(app: App): @pytest.mark.asyncio @pytest.mark.parametrize(("type", "expected"), [("message", True), ("notice", False)]) async def test_message(type: str, expected: bool): - dependent = list(MESSAGE.checkers)[0] + dependent = next(iter(MESSAGE.checkers)) checker = dependent.call assert isinstance(checker, Message) @@ -69,7 +69,7 @@ async def test_message(type: str, expected: bool): @pytest.mark.asyncio @pytest.mark.parametrize(("type", "expected"), [("message", False), ("notice", True)]) async def test_notice(type: str, expected: bool): - dependent = list(NOTICE.checkers)[0] + dependent = next(iter(NOTICE.checkers)) checker = dependent.call assert isinstance(checker, Notice) @@ -81,7 +81,7 @@ async def test_notice(type: str, expected: bool): @pytest.mark.asyncio @pytest.mark.parametrize(("type", "expected"), [("message", False), ("request", True)]) async def test_request(type: str, expected: bool): - dependent = list(REQUEST.checkers)[0] + dependent = next(iter(REQUEST.checkers)) checker = dependent.call assert isinstance(checker, Request) @@ -95,7 +95,7 @@ async def test_request(type: str, expected: bool): ("type", "expected"), [("message", False), ("meta_event", True)] ) async def test_metaevent(type: str, expected: bool): - dependent = list(METAEVENT.checkers)[0] + dependent = next(iter(METAEVENT.checkers)) checker = dependent.call assert isinstance(checker, MetaEvent) @@ -116,7 +116,7 @@ async def test_metaevent(type: str, expected: bool): ], ) async def test_superuser(app: App, type: str, user_id: str, expected: bool): - dependent = list(SUPERUSER.checkers)[0] + dependent = next(iter(SUPERUSER.checkers)) checker = dependent.call assert isinstance(checker, SuperUser) @@ -140,7 +140,7 @@ async def test_superuser(app: App, type: str, user_id: str, expected: bool): async def test_user( app: App, session_ids: Tuple[str, ...], session_id: Optional[str], expected: bool ): - dependent = list(USER(*session_ids).checkers)[0] + dependent = next(iter(USER(*session_ids).checkers)) checker = dependent.call assert isinstance(checker, User) diff --git a/tests/test_rule.py b/tests/test_rule.py index 4bf1a22f..be05c1a6 100644 --- a/tests/test_rule.py +++ b/tests/test_rule.py @@ -170,7 +170,7 @@ async def test_startswith( expected: bool, ): test_startswith = startswith(msg, ignorecase) - dependent = list(test_startswith.checkers)[0] + dependent = next(iter(test_startswith.checkers)) checker = dependent.call msg = (msg,) if isinstance(msg, str) else msg @@ -210,7 +210,7 @@ async def test_endswith( expected: bool, ): test_endswith = endswith(msg, ignorecase) - dependent = list(test_endswith.checkers)[0] + dependent = next(iter(test_endswith.checkers)) checker = dependent.call msg = (msg,) if isinstance(msg, str) else msg @@ -250,7 +250,7 @@ async def test_fullmatch( expected: bool, ): test_fullmatch = fullmatch(msg, ignorecase) - dependent = list(test_fullmatch.checkers)[0] + dependent = next(iter(test_fullmatch.checkers)) checker = dependent.call msg = (msg,) if isinstance(msg, str) else msg @@ -285,7 +285,7 @@ async def test_keyword( expected: bool, ): test_keyword = keyword(*kws) - dependent = list(test_keyword.checkers)[0] + dependent = next(iter(test_keyword.checkers)) checker = dependent.call assert isinstance(checker, KeywordsRule) @@ -331,7 +331,7 @@ async def test_command( expected: bool, ): test_command = command(*cmds, force_whitespace=force_whitespace) - dependent = list(test_command.checkers)[0] + dependent = next(iter(test_command.checkers)) checker = dependent.call assert isinstance(checker, CommandRule) @@ -352,7 +352,7 @@ async def test_shell_command(): MessageSegment = Message.get_segment_class() test_not_cmd = shell_command(CMD) - dependent = list(test_not_cmd.checkers)[0] + dependent = next(iter(test_not_cmd.checkers)) checker = dependent.call assert isinstance(checker, ShellCommandRule) message = Message() @@ -361,7 +361,7 @@ async def test_shell_command(): assert not await dependent(event=event, state=state) test_no_parser = shell_command(CMD) - dependent = list(test_no_parser.checkers)[0] + dependent = next(iter(test_no_parser.checkers)) checker = dependent.call assert isinstance(checker, ShellCommandRule) message = Message() @@ -375,7 +375,7 @@ async def test_shell_command(): parser.add_argument("-a", required=True) test_simple_parser = shell_command(CMD, parser=parser) - dependent = list(test_simple_parser.checkers)[0] + dependent = next(iter(test_simple_parser.checkers)) checker = dependent.call assert isinstance(checker, ShellCommandRule) message = Message("-a 1") @@ -386,7 +386,7 @@ async def test_shell_command(): assert state[SHELL_ARGS] == Namespace(a="1") test_parser_help = shell_command(CMD, parser=parser) - dependent = list(test_parser_help.checkers)[0] + dependent = next(iter(test_parser_help.checkers)) checker = dependent.call assert isinstance(checker, ShellCommandRule) message = Message("-h") @@ -399,7 +399,7 @@ async def test_shell_command(): assert state[SHELL_ARGS].message == parser.format_help() test_parser_error = shell_command(CMD, parser=parser) - dependent = list(test_parser_error.checkers)[0] + dependent = next(iter(test_parser_error.checkers)) checker = dependent.call assert isinstance(checker, ShellCommandRule) message = Message() @@ -412,7 +412,7 @@ async def test_shell_command(): assert state[SHELL_ARGS].message.startswith(parser.format_usage() + "test: error:") test_parser_remain_args = shell_command(CMD, parser=parser) - dependent = list(test_parser_remain_args.checkers)[0] + dependent = next(iter(test_parser_remain_args.checkers)) checker = dependent.call assert isinstance(checker, ShellCommandRule) message = MessageSegment.text("-a 1 2") + MessageSegment.image("test") @@ -425,7 +425,7 @@ async def test_shell_command(): assert state[SHELL_ARGS].message.startswith(parser.format_usage() + "test: error:") test_message_parser = shell_command(CMD, parser=parser) - dependent = list(test_message_parser.checkers)[0] + dependent = next(iter(test_message_parser.checkers)) checker = dependent.call assert isinstance(checker, ShellCommandRule) message = MessageSegment.text("-a") + MessageSegment.image("test") @@ -440,7 +440,7 @@ async def test_shell_command(): parser.add_argument("-a", required=True) test_not_exit = shell_command(CMD, parser=parser) - dependent = list(test_not_exit.checkers)[0] + dependent = next(iter(test_not_exit.checkers)) checker = dependent.call assert isinstance(checker, ShellCommandRule) message = Message() @@ -476,7 +476,7 @@ async def test_regex( matched: Optional[Match[str]], ): test_regex = regex(pattern) - dependent = list(test_regex.checkers)[0] + dependent = next(iter(test_regex.checkers)) checker = dependent.call assert isinstance(checker, RegexRule) @@ -499,7 +499,7 @@ async def test_regex( @pytest.mark.parametrize("expected", [True, False]) async def test_to_me(expected: bool): test_to_me = to_me() - dependent = list(test_to_me.checkers)[0] + dependent = next(iter(test_to_me.checkers)) checker = dependent.call assert isinstance(checker, ToMeRule) @@ -515,7 +515,7 @@ async def test_is_type(): Event3 = make_fake_event() test_type = is_type(Event1, Event2) - dependent = list(test_type.checkers)[0] + dependent = next(iter(test_type.checkers)) checker = dependent.call assert isinstance(checker, IsTypeRule) diff --git a/yarn.lock b/yarn.lock index eaaa8d76..5fbc8b29 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4980,7 +4980,7 @@ fs.realpath@^1.0.0: resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== -fsevents@~2.3.2: +fsevents@~2.3.2, fsevents@~2.3.3: version "2.3.3" resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== @@ -7620,11 +7620,11 @@ pure-color@^1.2.0: integrity sha512-QFADYnsVoBMw1srW7OVKEYjG+MbIa49s54w1MA1EDY6r2r/sTcKKYqRX1f4GYvnXP7eN/Pe9HFcX+hwzmrXRHA== pyright@^1.1.317: - version "1.1.350" - resolved "https://registry.npmjs.org/pyright/-/pyright-1.1.350.tgz#2cf74b3df1a3ecc270d3de6a62bd53a23a34e065" - integrity sha512-9AMEsPGFzyYzwYCU3QuTUk/AEfVO3hlKtvF0kybBnwGiFuYsmwx02/Hlra7ROX+jtmDStL8qiHCPoYy0rCz/uA== + version "1.1.352" + resolved "https://registry.npmjs.org/pyright/-/pyright-1.1.352.tgz#2feb37438bc79ddf2bc1fdcc139f4ba088719f14" + integrity sha512-X7fuuB24n3RIVCEPovrAadYJjxeB5RccArug+/oLwQnsHbSaDUQVHHkF/PJHkKpaIPX/RboG+EW8uCNUp1RnwQ== optionalDependencies: - fsevents "~2.3.2" + fsevents "~2.3.3" qs@6.11.0: version "6.11.0"