💥 Remove: 移除 Python 3.9 支持 (#3860)

This commit is contained in:
呵呵です
2026-02-18 00:11:36 +08:00
committed by GitHub
parent f719a6b41b
commit 63cde5da77
56 changed files with 603 additions and 1144 deletions

View File

@@ -24,10 +24,8 @@ from typing import (
IO,
TYPE_CHECKING,
NamedTuple,
Optional,
TypedDict,
TypeVar,
Union,
cast,
overload,
)
@@ -61,11 +59,11 @@ T = TypeVar("T")
class CMD_RESULT(TypedDict):
command: Optional[tuple[str, ...]]
raw_command: Optional[str]
command_arg: Optional[Message]
command_start: Optional[str]
command_whitespace: Optional[str]
command: tuple[str, ...] | None
raw_command: str | None
command_arg: Message | None
command_start: str | None
command_whitespace: str | None
class TRIE_VALUE(NamedTuple):
@@ -179,7 +177,7 @@ class StartswithRule:
return False
def startswith(msg: Union[str, tuple[str, ...]], ignorecase: bool = False) -> Rule:
def startswith(msg: str | tuple[str, ...], ignorecase: bool = False) -> Rule:
"""匹配消息纯文本开头。
参数:
@@ -234,7 +232,7 @@ class EndswithRule:
return False
def endswith(msg: Union[str, tuple[str, ...]], ignorecase: bool = False) -> Rule:
def endswith(msg: str | tuple[str, ...], ignorecase: bool = False) -> Rule:
"""匹配消息纯文本结尾。
参数:
@@ -288,7 +286,7 @@ class FullmatchRule:
return False
def fullmatch(msg: Union[str, tuple[str, ...]], ignorecase: bool = False) -> Rule:
def fullmatch(msg: str | tuple[str, ...], ignorecase: bool = False) -> Rule:
"""完全匹配消息。
参数:
@@ -360,7 +358,7 @@ class CommandRule:
def __init__(
self,
cmds: list[tuple[str, ...]],
force_whitespace: Optional[Union[str, bool]] = None,
force_whitespace: str | bool | None = None,
):
self.cmds = tuple(cmds)
self.force_whitespace = force_whitespace
@@ -378,9 +376,9 @@ class CommandRule:
async def __call__(
self,
cmd: Optional[tuple[str, ...]] = Command(),
cmd_arg: Optional[Message] = CommandArg(),
cmd_whitespace: Optional[str] = CommandWhitespace(),
cmd: tuple[str, ...] | None = Command(),
cmd_arg: Message | None = CommandArg(),
cmd_whitespace: str | None = CommandWhitespace(),
) -> bool:
if cmd not in self.cmds:
return False
@@ -392,8 +390,8 @@ class CommandRule:
def command(
*cmds: Union[str, tuple[str, ...]],
force_whitespace: Optional[Union[str, bool]] = None,
*cmds: str | tuple[str, ...],
force_whitespace: str | bool | None = None,
) -> Rule:
"""匹配消息命令。
@@ -456,36 +454,36 @@ class ArgumentParser(ArgParser):
@overload
def parse_known_args(
self,
args: Optional[Sequence[Union[str, MessageSegment]]] = None,
args: Sequence[str | MessageSegment] | None = None,
namespace: None = None,
) -> tuple[Namespace, list[Union[str, MessageSegment]]]: ...
) -> tuple[Namespace, list[str | MessageSegment]]: ...
@overload
def parse_known_args(
self, args: Optional[Sequence[Union[str, MessageSegment]]], namespace: T
) -> tuple[T, list[Union[str, MessageSegment]]]: ...
self, args: Sequence[str | MessageSegment] | None, namespace: T
) -> tuple[T, list[str | MessageSegment]]: ...
@overload
def parse_known_args(
self, *, namespace: T
) -> tuple[T, list[Union[str, MessageSegment]]]: ...
) -> tuple[T, list[str | MessageSegment]]: ...
def parse_known_args( # pyright: ignore[reportIncompatibleMethodOverride]
self,
args: Optional[Sequence[Union[str, MessageSegment]]] = None,
namespace: Optional[T] = None,
) -> tuple[Union[Namespace, T], list[Union[str, MessageSegment]]]: ...
args: Sequence[str | MessageSegment] | None = None,
namespace: T | None = None,
) -> tuple[Namespace | T, list[str | MessageSegment]]: ...
@overload
def parse_args(
self,
args: Optional[Sequence[Union[str, MessageSegment]]] = None,
args: Sequence[str | MessageSegment] | None = None,
namespace: None = None,
) -> Namespace: ...
@overload
def parse_args(
self, args: Optional[Sequence[Union[str, MessageSegment]]], namespace: T
self, args: Sequence[str | MessageSegment] | None, namespace: T
) -> T: ...
@overload
@@ -493,29 +491,29 @@ class ArgumentParser(ArgParser):
def parse_args(
self,
args: Optional[Sequence[Union[str, MessageSegment]]] = None,
namespace: Optional[T] = None,
) -> Union[Namespace, T]:
args: Sequence[str | MessageSegment] | None = None,
namespace: T | None = None,
) -> Namespace | T:
result, argv = self.parse_known_args(args, namespace)
if argv:
msg = gettext("unrecognized arguments: %s")
self.error(msg % " ".join(map(str, argv)))
return cast(Union[Namespace, T], result)
return cast(Namespace | T, result)
def _parse_optional(
self, arg_string: Union[str, MessageSegment]
) -> Optional[tuple[Optional[Action], str, Optional[str]]]:
self, arg_string: str | MessageSegment
) -> tuple[Action | None, str, str | None] | None:
return (
super()._parse_optional(arg_string) if isinstance(arg_string, str) else None
)
def _print_message(self, message: str, file: Optional[IO[str]] = None): # type: ignore
def _print_message(self, message: str, file: IO[str] | None = None): # type: ignore
if (msg := parser_message.get(None)) is not None:
parser_message.set(msg + message)
else:
super()._print_message(message, file)
def exit(self, status: int = 0, message: Optional[str] = None):
def exit(self, status: int = 0, message: str | None = None):
if message:
self._print_message(message)
raise ParserExit(status=status, message=parser_message.get(None))
@@ -531,7 +529,7 @@ class ShellCommandRule:
__slots__ = ("cmds", "parser")
def __init__(self, cmds: list[tuple[str, ...]], parser: Optional[ArgumentParser]):
def __init__(self, cmds: list[tuple[str, ...]], parser: ArgumentParser | None):
self.cmds = tuple(cmds)
self.parser = parser
@@ -551,8 +549,8 @@ class ShellCommandRule:
async def __call__(
self,
state: T_State,
cmd: Optional[tuple[str, ...]] = Command(),
msg: Optional[Message] = CommandArg(),
cmd: tuple[str, ...] | None = Command(),
msg: Message | None = CommandArg(),
) -> bool:
if cmd not in self.cmds or msg is None:
return False
@@ -589,7 +587,7 @@ class ShellCommandRule:
def shell_command(
*cmds: Union[str, tuple[str, ...]], parser: Optional[ArgumentParser] = None
*cmds: str | tuple[str, ...], parser: ArgumentParser | None = None
) -> Rule:
"""匹配 `shell_like` 形式的消息命令。
@@ -695,7 +693,7 @@ class RegexRule:
return False
def regex(regex: str, flags: Union[int, re.RegexFlag] = 0) -> Rule:
def regex(regex: str, flags: int | re.RegexFlag = 0) -> Rule:
"""匹配符合正则表达式的消息字符串。
可以通过 {ref}`nonebot.params.RegexStr` 获取匹配成功的字符串,