🧑‍💻 Develop: 添加 ruff RUF 规则 (#2598)

Co-authored-by: Ju4tCode <42488585+yanyongyu@users.noreply.github.com>
This commit is contained in:
uy/sun 2024-03-07 14:57:26 +08:00 committed by GitHub
parent 92ba99c34c
commit 9ff7f4baba
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 118 additions and 99 deletions

View File

@ -7,7 +7,7 @@ ci:
autoupdate_commit_msg: ":arrow_up: auto update by pre-commit hooks" autoupdate_commit_msg: ":arrow_up: auto update by pre-commit hooks"
repos: repos:
- repo: https://github.com/astral-sh/ruff-pre-commit - repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.2.0 rev: v0.3.0
hooks: hooks:
- id: ruff - id: ruff
args: [--fix, --exit-non-zero-on-fix] args: [--fix, --exit-non-zero-on-fix]

View File

@ -1,7 +1,7 @@
import abc import abc
import asyncio import asyncio
from functools import partial 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.log import logger
from nonebot.config import Config from nonebot.config import Config
@ -27,9 +27,9 @@ class Bot(abc.ABC):
self_id: 机器人 ID self_id: 机器人 ID
""" """
_calling_api_hook: Set[T_CallingAPIHook] = set() _calling_api_hook: ClassVar[Set[T_CallingAPIHook]] = set()
"""call_api 时执行的函数""" """call_api 时执行的函数"""
_called_api_hook: Set[T_CalledAPIHook] = set() _called_api_hook: ClassVar[Set[T_CalledAPIHook]] = set()
"""call_api 后执行的函数""" """call_api 后执行的函数"""
def __init__(self, adapter: "Adapter", self_id: str): def __init__(self, adapter: "Adapter", self_id: str):

View File

@ -20,7 +20,7 @@ class Event(abc.ABC, BaseModel):
class Config(ConfigDict): class Config(ConfigDict):
extra = "allow" # type: ignore extra = "allow" # type: ignore
json_encoders = {Message: DataclassEncoder} json_encoders = {Message: DataclassEncoder} # noqa: RUF012
if not PYDANTIC_V2: # pragma: pydantic-v1 if not PYDANTIC_V2: # pragma: pydantic-v1

View File

@ -25,7 +25,7 @@ from _string import formatter_field_name_split # type: ignore
if TYPE_CHECKING: if TYPE_CHECKING:
from .message import Message, MessageSegment from .message import Message, MessageSegment
def formatter_field_name_split( # noqa: F811 def formatter_field_name_split(
field_name: str, field_name: str,
) -> Tuple[str, List[Tuple[bool, str]]]: ... ) -> Tuple[str, List[Tuple[bool, str]]]: ...

View File

@ -2,7 +2,7 @@ import abc
import asyncio import asyncio
from typing_extensions import TypeAlias from typing_extensions import TypeAlias
from contextlib import AsyncExitStack, asynccontextmanager 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.log import logger
from nonebot.config import Env, Config from nonebot.config import Env, Config
@ -36,11 +36,11 @@ class Driver(abc.ABC):
config: 包含配置信息的 Config 对象 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 连接建立时执行的函数"""
_bot_disconnection_hook: Set[Dependent[Any]] = set() _bot_disconnection_hook: ClassVar[Set[Dependent[Any]]] = set()
"""Bot 连接断开时执行的函数""" """Bot 连接断开时执行的函数"""
def __init__(self, env: Env, config: Config): def __init__(self, env: Env, config: Config):

View File

@ -141,7 +141,7 @@ class Matcher(metaclass=MatcherMeta):
"""事件响应器匹配规则""" """事件响应器匹配规则"""
permission: ClassVar[Permission] = Permission() permission: ClassVar[Permission] = Permission()
"""事件响应器触发权限""" """事件响应器触发权限"""
handlers: List[Dependent[Any]] = [] handlers: ClassVar[List[Dependent[Any]]] = []
"""事件响应器拥有的事件处理函数列表""" """事件响应器拥有的事件处理函数列表"""
priority: ClassVar[int] = 1 priority: ClassVar[int] = 1
"""事件响应器优先级""" """事件响应器优先级"""
@ -171,7 +171,7 @@ class Matcher(metaclass=MatcherMeta):
) )
def __init__(self): def __init__(self):
self.handlers = self.handlers.copy() self.remain_handlers: List[Dependent[Any]] = self.handlers.copy()
self.state = self._default_state.copy() self.state = self._default_state.copy()
def __repr__(self) -> str: def __repr__(self) -> str:
@ -457,7 +457,7 @@ class Matcher(metaclass=MatcherMeta):
parameterless: 非参数类型依赖列表 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)) matcher.set_target(RECEIVE_KEY.format(id=id))
if matcher.get_target() == RECEIVE_KEY.format(id=id): if matcher.get_target() == RECEIVE_KEY.format(id=id):
matcher.set_receive(id, event) matcher.set_receive(id, event)
@ -775,7 +775,7 @@ class Matcher(metaclass=MatcherMeta):
async def resolve_reject(self): async def resolve_reject(self):
handler = current_handler.get() handler = current_handler.get()
self.handlers.insert(0, handler) self.remain_handlers.insert(0, handler)
if REJECT_CACHE_TARGET in self.state: if REJECT_CACHE_TARGET in self.state:
self.state[REJECT_TARGET] = self.state[REJECT_CACHE_TARGET] self.state[REJECT_TARGET] = self.state[REJECT_CACHE_TARGET]
@ -809,8 +809,8 @@ class Matcher(metaclass=MatcherMeta):
# Refresh preprocess state # Refresh preprocess state
self.state.update(state) self.state.update(state)
while self.handlers: while self.remain_handlers:
handler = self.handlers.pop(0) handler = self.remain_handlers.pop(0)
current_handler.set(handler) current_handler.set(handler)
logger.debug(f"Running handler {handler}") logger.debug(f"Running handler {handler}")
try: try:
@ -852,7 +852,7 @@ class Matcher(metaclass=MatcherMeta):
type_, type_,
Rule(), Rule(),
permission, permission,
self.handlers, self.remain_handlers,
temp=True, temp=True,
priority=0, priority=0,
block=True, block=True,
@ -872,7 +872,7 @@ class Matcher(metaclass=MatcherMeta):
type_, type_,
Rule(), Rule(),
permission, permission,
self.handlers, self.remain_handlers,
temp=True, temp=True,
priority=0, priority=0,
block=True, block=True,

View File

@ -1,7 +1,7 @@
import asyncio import asyncio
from typing_extensions import Self from typing_extensions import Self
from contextlib import AsyncExitStack 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.dependencies import Dependent
from nonebot.utils import run_coro_with_catch 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 nonebot.typing import T_DependencyCache, T_PermissionChecker
from .adapter import Bot, Event from .adapter import Bot, Event
from .params import BotParam, EventParam, DependParam, DefaultParam from .params import Param, BotParam, EventParam, DependParam, DefaultParam
class Permission: class Permission:
@ -30,7 +30,7 @@ class Permission:
__slots__ = ("checkers",) __slots__ = ("checkers",)
HANDLER_PARAM_TYPES = [ HANDLER_PARAM_TYPES: ClassVar[List[Type[Param]]] = [
DependParam, DependParam,
BotParam, BotParam,
EventParam, EventParam,
@ -146,7 +146,7 @@ class User:
@classmethod @classmethod
def _clean_permission(cls, perm: Permission) -> Optional[Permission]: def _clean_permission(cls, perm: Permission) -> Optional[Permission]:
if len(perm.checkers) == 1 and isinstance( 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 user_perm.perm
return perm return perm

View File

@ -1,13 +1,13 @@
import asyncio import asyncio
from contextlib import AsyncExitStack 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.dependencies import Dependent
from nonebot.exception import SkippedException from nonebot.exception import SkippedException
from nonebot.typing import T_State, T_RuleChecker, T_DependencyCache from nonebot.typing import T_State, T_RuleChecker, T_DependencyCache
from .adapter import Bot, Event from .adapter import Bot, Event
from .params import BotParam, EventParam, StateParam, DependParam, DefaultParam from .params import Param, BotParam, EventParam, StateParam, DependParam, DefaultParam
class Rule: class Rule:
@ -28,7 +28,7 @@ class Rule:
__slots__ = ("checkers",) __slots__ = ("checkers",)
HANDLER_PARAM_TYPES = [ HANDLER_PARAM_TYPES: ClassVar[List[Type[Param]]] = [
DependParam, DependParam,
BotParam, BotParam,
EventParam, EventParam,

View File

@ -236,7 +236,7 @@ class PluginLoader(SourceFileLoader):
break break
# enter plugin context # enter plugin context
_plugin_token = _current_plugin_chain.set(parent_plugins + (plugin,)) _plugin_token = _current_plugin_chain.set((*parent_plugins, plugin))
try: try:
super().exec_module(module) super().exec_module(module)

64
poetry.lock generated
View File

@ -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]] [[package]]
name = "aiodns" name = "aiodns"
@ -757,13 +757,13 @@ testing = ["hatch", "pre-commit", "pytest", "tox"]
[[package]] [[package]]
name = "fastapi" name = "fastapi"
version = "0.109.2" version = "0.110.0"
description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production"
optional = true optional = true
python-versions = ">=3.8" python-versions = ">=3.8"
files = [ files = [
{file = "fastapi-0.109.2-py3-none-any.whl", hash = "sha256:2c9bab24667293b501cad8dd388c05240c850b58ec5876ee3283c47d6e1e3a4d"}, {file = "fastapi-0.110.0-py3-none-any.whl", hash = "sha256:87a1f6fb632a218222c5984be540055346a8f5d8a68e8f6fb647b1dc9934de4b"},
{file = "fastapi-0.109.2.tar.gz", hash = "sha256:f3817eac96fe4f65a2ebb4baa000f394e55f5fccdaf7f75250804bc58f354f73"}, {file = "fastapi-0.110.0.tar.gz", hash = "sha256:266775f0dcc95af9d3ef39bad55cff525329a931d5fd51930aadd4f428bf7ff3"},
] ]
[package.dependencies] [package.dependencies]
@ -1631,13 +1631,13 @@ files = [
[[package]] [[package]]
name = "pydantic" name = "pydantic"
version = "2.6.2" version = "2.6.3"
description = "Data validation using Python type hints" description = "Data validation using Python type hints"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
files = [ files = [
{file = "pydantic-2.6.2-py3-none-any.whl", hash = "sha256:37a5432e54b12fecaa1049c5195f3d860a10e01bdfd24f1840ef14bd0d3aeab3"}, {file = "pydantic-2.6.3-py3-none-any.whl", hash = "sha256:72c6034df47f46ccdf81869fddb81aade68056003900a8724a4f160700016a2a"},
{file = "pydantic-2.6.2.tar.gz", hash = "sha256:a09be1c3d28f3abe37f8a78af58284b236a92ce520105ddc91a6d29ea1176ba7"}, {file = "pydantic-2.6.3.tar.gz", hash = "sha256:e07805c4c7f5c6826e33a1d4c9d47950d7eaf34868e2690f8594d2e30241f11f"},
] ]
[package.dependencies] [package.dependencies]
@ -1953,28 +1953,28 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
[[package]] [[package]]
name = "ruff" name = "ruff"
version = "0.2.2" version = "0.3.1"
description = "An extremely fast Python linter and code formatter, written in Rust." description = "An extremely fast Python linter and code formatter, written in Rust."
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ 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.3.1-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:6b82e3937d0d76554cd5796bc3342a7d40de44494d29ff490022d7a52c501744"},
{file = "ruff-0.2.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:d450b7fbff85913f866a5384d8912710936e2b96da74541c82c1b458472ddb39"}, {file = "ruff-0.3.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ae7954c8f692b70e6a206087ae3988acc9295d84c550f8d90b66c62424c16771"},
{file = "ruff-0.2.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ecd46e3106850a5c26aee114e562c329f9a1fbe9e4821b008c4404f64ff9ce73"}, {file = "ruff-0.3.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b730f56ccf91225da0f06cfe421e83b8cc27b2a79393db9c3df02ed7e2bbc01"},
{file = "ruff-0.2.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e22676a5b875bd72acd3d11d5fa9075d3a5f53b877fe7b4793e4673499318ba"}, {file = "ruff-0.3.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c78bfa85637668f47bd82aa2ae17de2b34221ac23fea30926f6409f9e37fc927"},
{file = "ruff-0.2.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1695700d1e25a99d28f7a1636d85bafcc5030bba9d0578c0781ba1790dbcf51c"}, {file = "ruff-0.3.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6abaad602d6e6daaec444cbf4d9364df0a783e49604c21499f75bb92237d4af"},
{file = "ruff-0.2.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:b0c232af3d0bd8f521806223723456ffebf8e323bd1e4e82b0befb20ba18388e"}, {file = "ruff-0.3.1-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:5f0c21b6914c3c9a25a59497cbb1e5b6c2d8d9beecc9b8e03ee986e24eee072e"},
{file = "ruff-0.2.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f63d96494eeec2fc70d909393bcd76c69f35334cdbd9e20d089fb3f0640216ca"}, {file = "ruff-0.3.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:434c3fc72e6311c85cd143c4c448b0e60e025a9ac1781e63ba222579a8c29200"},
{file = "ruff-0.2.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6a61ea0ff048e06de273b2e45bd72629f470f5da8f71daf09fe481278b175001"}, {file = "ruff-0.3.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78a7025e6312cbba496341da5062e7cdd47d95f45c1b903e635cdeb1ba5ec2b9"},
{file = "ruff-0.2.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e1439c8f407e4f356470e54cdecdca1bd5439a0673792dbe34a2b0a551a2fe3"}, {file = "ruff-0.3.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:52b02bb46f1a79b0c1fa93f6495bc7e77e4ef76e6c28995b4974a20ed09c0833"},
{file = "ruff-0.2.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:940de32dc8853eba0f67f7198b3e79bc6ba95c2edbfdfac2144c8235114d6726"}, {file = "ruff-0.3.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:11b5699c42f7d0b771c633d620f2cb22e727fb226273aba775a91784a9ed856c"},
{file = "ruff-0.2.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:0c126da55c38dd917621552ab430213bdb3273bb10ddb67bc4b761989210eb6e"}, {file = "ruff-0.3.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:54e5dca3e411772b51194b3102b5f23b36961e8ede463776b289b78180df71a0"},
{file = "ruff-0.2.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:3b65494f7e4bed2e74110dac1f0d17dc8e1f42faaa784e7c58a98e335ec83d7e"}, {file = "ruff-0.3.1-py3-none-musllinux_1_2_i686.whl", hash = "sha256:951efb610c5844e668bbec4f71cf704f8645cf3106e13f283413969527ebfded"},
{file = "ruff-0.2.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:1ec49be4fe6ddac0503833f3ed8930528e26d1e60ad35c2446da372d16651ce9"}, {file = "ruff-0.3.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:09c7333b25e983aabcf6e38445252cff0b4745420fc3bda45b8fce791cc7e9ce"},
{file = "ruff-0.2.2-py3-none-win32.whl", hash = "sha256:d920499b576f6c68295bc04e7b17b6544d9d05f196bb3aac4358792ef6f34325"}, {file = "ruff-0.3.1-py3-none-win32.whl", hash = "sha256:d937f9b99ebf346e0606c3faf43c1e297a62ad221d87ef682b5bdebe199e01f6"},
{file = "ruff-0.2.2-py3-none-win_amd64.whl", hash = "sha256:cc9a91ae137d687f43a44c900e5d95e9617cb37d4c989e462980ba27039d239d"}, {file = "ruff-0.3.1-py3-none-win_amd64.whl", hash = "sha256:c0318a512edc9f4e010bbaab588b5294e78c5cdc9b02c3d8ab2d77c7ae1903e3"},
{file = "ruff-0.2.2-py3-none-win_arm64.whl", hash = "sha256:c9d15fc41e6054bfc7200478720570078f0b41c9ae4f010bcc16bd6f4d1aacdd"}, {file = "ruff-0.3.1-py3-none-win_arm64.whl", hash = "sha256:d3b60e44240f7e903e6dbae3139a65032ea4c6f2ad99b6265534ff1b83c20afa"},
{file = "ruff-0.2.2.tar.gz", hash = "sha256:e62ed7f36b3068a30ba39193a14274cd706bc486fad521276458022f7bccb31d"}, {file = "ruff-0.3.1.tar.gz", hash = "sha256:d30db97141fc2134299e6e983a6727922c9e03c031ae4883a6d69461de722ae7"},
] ]
[[package]] [[package]]
@ -1995,13 +1995,13 @@ testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jar
[[package]] [[package]]
name = "sniffio" name = "sniffio"
version = "1.3.0" version = "1.3.1"
description = "Sniff out which async library your code is running under" description = "Sniff out which async library your code is running under"
optional = true optional = true
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"}, {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"},
{file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"}, {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"},
] ]
[[package]] [[package]]
@ -2049,13 +2049,13 @@ files = [
[[package]] [[package]]
name = "typing-extensions" name = "typing-extensions"
version = "4.9.0" version = "4.10.0"
description = "Backported and Experimental Type Hints for Python 3.8+" description = "Backported and Experimental Type Hints for Python 3.8+"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
files = [ files = [
{file = "typing_extensions-4.9.0-py3-none-any.whl", hash = "sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd"}, {file = "typing_extensions-4.10.0-py3-none-any.whl", hash = "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475"},
{file = "typing_extensions-4.9.0.tar.gz", hash = "sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783"}, {file = "typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb"},
] ]
[[package]] [[package]]
@ -2518,4 +2518,4 @@ websockets = ["websockets"]
[metadata] [metadata]
lock-version = "2.0" lock-version = "2.0"
python-versions = "^3.8" python-versions = "^3.8"
content-hash = "740f50b322feb17536a68f1d5b25599174afb36de5fd0aa0eac6a75d2e155902" content-hash = "7ca525ddb55760c80c17925d88ae4eabf0c7beb7f61c4d3f75810080a11b9cea"

View File

@ -44,7 +44,7 @@ uvicorn = { version = ">=0.20.0,<1.0.0", extras = [
], optional = true } ], optional = true }
[tool.poetry.group.dev.dependencies] [tool.poetry.group.dev.dependencies]
ruff = "^0.2.0" ruff = "^0.3.0"
isort = "^5.10.1" isort = "^5.10.1"
black = "^24.0.0" black = "^24.0.0"
nonemoji = "^0.1.2" nonemoji = "^0.1.2"
@ -90,8 +90,27 @@ line-length = 88
target-version = "py38" target-version = "py38"
[tool.ruff.lint] [tool.ruff.lint]
select = ["E", "W", "F", "UP", "C", "T", "PYI", "PT", "Q"] select = [
ignore = ["E402", "C901", "UP037"] "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] [tool.ruff.lint.flake8-pytest-style]
fixture-parentheses = false fixture-parentheses = false

View File

@ -32,8 +32,8 @@ async def gen_async():
@dataclass @dataclass
class ClassDependency: class ClassDependency:
x: int = Depends(gen_sync) x: int = Depends(gen_sync) # noqa: RUF009
y: int = Depends(gen_async) y: int = Depends(gen_async) # noqa: RUF009
class FooBot(Bot): ... class FooBot(Bot): ...

View File

@ -1,7 +1,7 @@
from typing import List, Union, Optional from typing import List, Union, Optional
import pytest import pytest
from pydantic import BaseModel from pydantic import Field, BaseModel
from nonebot.config import DOTENV_TYPE, BaseSettings, SettingsError from nonebot.config import DOTENV_TYPE, BaseSettings, SettingsError
@ -18,7 +18,7 @@ class Example(BaseSettings):
_env_nested_delimiter: Optional[str] = "__" _env_nested_delimiter: Optional[str] = "__"
simple: str = "" simple: str = ""
complex: List[int] = [1] complex: List[int] = Field(default=[1])
complex_none: Optional[List[int]] = None complex_none: Optional[List[int]] = None
complex_union: Union[int, List[int]] = 1 complex_union: Union[int, List[int]] = 1
nested: Simple = Simple() nested: Simple = Simple()

View File

@ -409,9 +409,9 @@ async def test_bot_connect_hook(app: App, driver: Driver):
disconn_should_be_called = True 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") 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") pytest.fail("on_bot_disconnect hook not registered")
async with app.test_api() as ctx: async with app.test_api() as ctx:

View File

@ -244,7 +244,7 @@ async def test_default_permission_updater(app: App):
matcher = test_permission_updater() matcher = test_permission_updater()
new_perm = await matcher.update_permission(bot, event) new_perm = await matcher.update_permission(bot, event)
assert len(new_perm.checkers) == 1 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 isinstance(checker, User)
assert checker.users == ("test",) assert checker.users == ("test",)
assert checker.perm is default_permission 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")() 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 isinstance(user_permission, User)
assert user_permission.perm is default_permission assert user_permission.perm is default_permission
async with app.test_api() as ctx: async with app.test_api() as ctx:
@ -266,7 +266,7 @@ async def test_user_permission_updater(app: App):
matcher = test_user_permission_updater() matcher = test_user_permission_updater()
new_perm = await matcher.update_permission(bot, event) new_perm = await matcher.update_permission(bot, event)
assert len(new_perm.checkers) == 1 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 isinstance(checker, User)
assert checker.users == ("test",) assert checker.users == ("test",)
assert checker.perm is default_permission assert checker.perm is default_permission

View File

@ -212,7 +212,7 @@ async def test_event(app: App):
ctx.pass_params(event=fake_fooevent) ctx.pass_params(event=fake_fooevent)
ctx.should_return(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: async with app.test_dependent(sub_event, allow_types=[EventParam]) as ctx:
ctx.pass_params(event=fake_event) ctx.pass_params(event=fake_event)
@ -436,7 +436,7 @@ async def test_matcher(app: App):
ctx.pass_params(matcher=foo_matcher) ctx.pass_params(matcher=foo_matcher)
ctx.should_return(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: async with app.test_dependent(sub_matcher, allow_types=[MatcherParam]) as ctx:
ctx.pass_params(matcher=fake_matcher) ctx.pass_params(matcher=fake_matcher)

View File

@ -57,7 +57,7 @@ async def test_permission(app: App):
@pytest.mark.asyncio @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): async def test_message(type: str, expected: bool):
dependent = list(MESSAGE.checkers)[0] dependent = next(iter(MESSAGE.checkers))
checker = dependent.call checker = dependent.call
assert isinstance(checker, Message) assert isinstance(checker, Message)
@ -69,7 +69,7 @@ async def test_message(type: str, expected: bool):
@pytest.mark.asyncio @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): async def test_notice(type: str, expected: bool):
dependent = list(NOTICE.checkers)[0] dependent = next(iter(NOTICE.checkers))
checker = dependent.call checker = dependent.call
assert isinstance(checker, Notice) assert isinstance(checker, Notice)
@ -81,7 +81,7 @@ async def test_notice(type: str, expected: bool):
@pytest.mark.asyncio @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): async def test_request(type: str, expected: bool):
dependent = list(REQUEST.checkers)[0] dependent = next(iter(REQUEST.checkers))
checker = dependent.call checker = dependent.call
assert isinstance(checker, Request) assert isinstance(checker, Request)
@ -95,7 +95,7 @@ async def test_request(type: str, expected: bool):
("type", "expected"), [("message", False), ("meta_event", True)] ("type", "expected"), [("message", False), ("meta_event", True)]
) )
async def test_metaevent(type: str, expected: bool): async def test_metaevent(type: str, expected: bool):
dependent = list(METAEVENT.checkers)[0] dependent = next(iter(METAEVENT.checkers))
checker = dependent.call checker = dependent.call
assert isinstance(checker, MetaEvent) 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): 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 checker = dependent.call
assert isinstance(checker, SuperUser) 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( async def test_user(
app: App, session_ids: Tuple[str, ...], session_id: Optional[str], expected: bool 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 checker = dependent.call
assert isinstance(checker, User) assert isinstance(checker, User)

View File

@ -170,7 +170,7 @@ async def test_startswith(
expected: bool, expected: bool,
): ):
test_startswith = startswith(msg, ignorecase) test_startswith = startswith(msg, ignorecase)
dependent = list(test_startswith.checkers)[0] dependent = next(iter(test_startswith.checkers))
checker = dependent.call checker = dependent.call
msg = (msg,) if isinstance(msg, str) else msg msg = (msg,) if isinstance(msg, str) else msg
@ -210,7 +210,7 @@ async def test_endswith(
expected: bool, expected: bool,
): ):
test_endswith = endswith(msg, ignorecase) test_endswith = endswith(msg, ignorecase)
dependent = list(test_endswith.checkers)[0] dependent = next(iter(test_endswith.checkers))
checker = dependent.call checker = dependent.call
msg = (msg,) if isinstance(msg, str) else msg msg = (msg,) if isinstance(msg, str) else msg
@ -250,7 +250,7 @@ async def test_fullmatch(
expected: bool, expected: bool,
): ):
test_fullmatch = fullmatch(msg, ignorecase) test_fullmatch = fullmatch(msg, ignorecase)
dependent = list(test_fullmatch.checkers)[0] dependent = next(iter(test_fullmatch.checkers))
checker = dependent.call checker = dependent.call
msg = (msg,) if isinstance(msg, str) else msg msg = (msg,) if isinstance(msg, str) else msg
@ -285,7 +285,7 @@ async def test_keyword(
expected: bool, expected: bool,
): ):
test_keyword = keyword(*kws) test_keyword = keyword(*kws)
dependent = list(test_keyword.checkers)[0] dependent = next(iter(test_keyword.checkers))
checker = dependent.call checker = dependent.call
assert isinstance(checker, KeywordsRule) assert isinstance(checker, KeywordsRule)
@ -331,7 +331,7 @@ async def test_command(
expected: bool, expected: bool,
): ):
test_command = command(*cmds, force_whitespace=force_whitespace) test_command = command(*cmds, force_whitespace=force_whitespace)
dependent = list(test_command.checkers)[0] dependent = next(iter(test_command.checkers))
checker = dependent.call checker = dependent.call
assert isinstance(checker, CommandRule) assert isinstance(checker, CommandRule)
@ -352,7 +352,7 @@ async def test_shell_command():
MessageSegment = Message.get_segment_class() MessageSegment = Message.get_segment_class()
test_not_cmd = shell_command(CMD) test_not_cmd = shell_command(CMD)
dependent = list(test_not_cmd.checkers)[0] dependent = next(iter(test_not_cmd.checkers))
checker = dependent.call checker = dependent.call
assert isinstance(checker, ShellCommandRule) assert isinstance(checker, ShellCommandRule)
message = Message() message = Message()
@ -361,7 +361,7 @@ async def test_shell_command():
assert not await dependent(event=event, state=state) assert not await dependent(event=event, state=state)
test_no_parser = shell_command(CMD) test_no_parser = shell_command(CMD)
dependent = list(test_no_parser.checkers)[0] dependent = next(iter(test_no_parser.checkers))
checker = dependent.call checker = dependent.call
assert isinstance(checker, ShellCommandRule) assert isinstance(checker, ShellCommandRule)
message = Message() message = Message()
@ -375,7 +375,7 @@ async def test_shell_command():
parser.add_argument("-a", required=True) parser.add_argument("-a", required=True)
test_simple_parser = shell_command(CMD, parser=parser) 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 checker = dependent.call
assert isinstance(checker, ShellCommandRule) assert isinstance(checker, ShellCommandRule)
message = Message("-a 1") message = Message("-a 1")
@ -386,7 +386,7 @@ async def test_shell_command():
assert state[SHELL_ARGS] == Namespace(a="1") assert state[SHELL_ARGS] == Namespace(a="1")
test_parser_help = shell_command(CMD, parser=parser) 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 checker = dependent.call
assert isinstance(checker, ShellCommandRule) assert isinstance(checker, ShellCommandRule)
message = Message("-h") message = Message("-h")
@ -399,7 +399,7 @@ async def test_shell_command():
assert state[SHELL_ARGS].message == parser.format_help() assert state[SHELL_ARGS].message == parser.format_help()
test_parser_error = shell_command(CMD, parser=parser) 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 checker = dependent.call
assert isinstance(checker, ShellCommandRule) assert isinstance(checker, ShellCommandRule)
message = Message() message = Message()
@ -412,7 +412,7 @@ async def test_shell_command():
assert state[SHELL_ARGS].message.startswith(parser.format_usage() + "test: error:") assert state[SHELL_ARGS].message.startswith(parser.format_usage() + "test: error:")
test_parser_remain_args = shell_command(CMD, parser=parser) 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 checker = dependent.call
assert isinstance(checker, ShellCommandRule) assert isinstance(checker, ShellCommandRule)
message = MessageSegment.text("-a 1 2") + MessageSegment.image("test") 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:") assert state[SHELL_ARGS].message.startswith(parser.format_usage() + "test: error:")
test_message_parser = shell_command(CMD, parser=parser) 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 checker = dependent.call
assert isinstance(checker, ShellCommandRule) assert isinstance(checker, ShellCommandRule)
message = MessageSegment.text("-a") + MessageSegment.image("test") message = MessageSegment.text("-a") + MessageSegment.image("test")
@ -440,7 +440,7 @@ async def test_shell_command():
parser.add_argument("-a", required=True) parser.add_argument("-a", required=True)
test_not_exit = shell_command(CMD, parser=parser) 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 checker = dependent.call
assert isinstance(checker, ShellCommandRule) assert isinstance(checker, ShellCommandRule)
message = Message() message = Message()
@ -476,7 +476,7 @@ async def test_regex(
matched: Optional[Match[str]], matched: Optional[Match[str]],
): ):
test_regex = regex(pattern) test_regex = regex(pattern)
dependent = list(test_regex.checkers)[0] dependent = next(iter(test_regex.checkers))
checker = dependent.call checker = dependent.call
assert isinstance(checker, RegexRule) assert isinstance(checker, RegexRule)
@ -499,7 +499,7 @@ async def test_regex(
@pytest.mark.parametrize("expected", [True, False]) @pytest.mark.parametrize("expected", [True, False])
async def test_to_me(expected: bool): async def test_to_me(expected: bool):
test_to_me = to_me() test_to_me = to_me()
dependent = list(test_to_me.checkers)[0] dependent = next(iter(test_to_me.checkers))
checker = dependent.call checker = dependent.call
assert isinstance(checker, ToMeRule) assert isinstance(checker, ToMeRule)
@ -515,7 +515,7 @@ async def test_is_type():
Event3 = make_fake_event() Event3 = make_fake_event()
test_type = is_type(Event1, Event2) test_type = is_type(Event1, Event2)
dependent = list(test_type.checkers)[0] dependent = next(iter(test_type.checkers))
checker = dependent.call checker = dependent.call
assert isinstance(checker, IsTypeRule) assert isinstance(checker, IsTypeRule)

View File

@ -4980,7 +4980,7 @@ fs.realpath@^1.0.0:
resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
fsevents@~2.3.2: fsevents@~2.3.2, fsevents@~2.3.3:
version "2.3.3" version "2.3.3"
resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
@ -7620,11 +7620,11 @@ pure-color@^1.2.0:
integrity sha512-QFADYnsVoBMw1srW7OVKEYjG+MbIa49s54w1MA1EDY6r2r/sTcKKYqRX1f4GYvnXP7eN/Pe9HFcX+hwzmrXRHA== integrity sha512-QFADYnsVoBMw1srW7OVKEYjG+MbIa49s54w1MA1EDY6r2r/sTcKKYqRX1f4GYvnXP7eN/Pe9HFcX+hwzmrXRHA==
pyright@^1.1.317: pyright@^1.1.317:
version "1.1.350" version "1.1.352"
resolved "https://registry.npmjs.org/pyright/-/pyright-1.1.350.tgz#2cf74b3df1a3ecc270d3de6a62bd53a23a34e065" resolved "https://registry.npmjs.org/pyright/-/pyright-1.1.352.tgz#2feb37438bc79ddf2bc1fdcc139f4ba088719f14"
integrity sha512-9AMEsPGFzyYzwYCU3QuTUk/AEfVO3hlKtvF0kybBnwGiFuYsmwx02/Hlra7ROX+jtmDStL8qiHCPoYy0rCz/uA== integrity sha512-X7fuuB24n3RIVCEPovrAadYJjxeB5RccArug+/oLwQnsHbSaDUQVHHkF/PJHkKpaIPX/RboG+EW8uCNUp1RnwQ==
optionalDependencies: optionalDependencies:
fsevents "~2.3.2" fsevents "~2.3.3"
qs@6.11.0: qs@6.11.0:
version "6.11.0" version "6.11.0"