mirror of
https://github.com/nonebot/nonebot2.git
synced 2026-02-26 20:54:44 +00:00
💥 Remove: 移除 Python 3.9 支持 (#3860)
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
from collections.abc import Generator
|
||||
from collections.abc import Callable, Generator
|
||||
from functools import wraps
|
||||
import os
|
||||
from pathlib import Path
|
||||
import sys
|
||||
import threading
|
||||
from typing import TYPE_CHECKING, Callable, TypeVar
|
||||
from types import EllipsisType
|
||||
from typing import TYPE_CHECKING, TypeVar
|
||||
from typing_extensions import ParamSpec
|
||||
|
||||
from nonebug import NONEBOT_INIT_KWARGS
|
||||
@@ -50,12 +51,12 @@ def anyio_backend(request: pytest.FixtureRequest):
|
||||
|
||||
|
||||
def run_once(func: Callable[P, R]) -> Callable[P, R]:
|
||||
result = ...
|
||||
result: R | EllipsisType = ...
|
||||
|
||||
@wraps(func)
|
||||
def _wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
|
||||
nonlocal result
|
||||
if result is not Ellipsis:
|
||||
if result is not ...:
|
||||
return result
|
||||
|
||||
result = func(*args, **kwargs)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import base64
|
||||
import json
|
||||
import socket
|
||||
from typing import TypeVar, Union
|
||||
from typing import TypeVar
|
||||
|
||||
from werkzeug import Request, Response
|
||||
from werkzeug.datastructures import MultiDict
|
||||
@@ -36,7 +36,7 @@ def json_safe(string, content_type="application/octet-stream") -> str:
|
||||
).decode("utf-8")
|
||||
|
||||
|
||||
def flattern(d: "MultiDict[K, V]") -> dict[K, Union[V, list[V]]]:
|
||||
def flattern(d: "MultiDict[K, V]") -> dict[K, V | list[V]]:
|
||||
return {k: v[0] if len(v) == 1 else v for k, v in d.to_dict(flat=False).items()}
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from typing import TypeVar, Union
|
||||
from typing import TypeVar
|
||||
|
||||
from nonebot.adapters import Bot
|
||||
|
||||
@@ -28,7 +28,7 @@ async def sub_bot(b: FooBot) -> FooBot:
|
||||
class BarBot(Bot): ...
|
||||
|
||||
|
||||
async def union_bot(b: Union[FooBot, BarBot]) -> Union[FooBot, BarBot]:
|
||||
async def union_bot(b: FooBot | BarBot) -> FooBot | BarBot:
|
||||
return b
|
||||
|
||||
|
||||
@@ -46,4 +46,4 @@ async def generic_bot_none(b: CB) -> CB:
|
||||
return b
|
||||
|
||||
|
||||
async def not_bot(b: Union[int, Bot]): ...
|
||||
async def not_bot(b: int | Bot): ...
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from typing import TypeVar, Union
|
||||
from typing import TypeVar
|
||||
|
||||
from nonebot.adapters import Event, Message
|
||||
from nonebot.params import EventMessage, EventPlainText, EventToMe, EventType
|
||||
@@ -29,7 +29,7 @@ async def sub_event(e: FooEvent) -> FooEvent:
|
||||
class BarEvent(Event): ...
|
||||
|
||||
|
||||
async def union_event(e: Union[FooEvent, BarEvent]) -> Union[FooEvent, BarEvent]:
|
||||
async def union_event(e: FooEvent | BarEvent) -> FooEvent | BarEvent:
|
||||
return e
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ async def generic_event_none(e: CE) -> CE:
|
||||
return e
|
||||
|
||||
|
||||
async def not_event(e: Union[int, Event]): ...
|
||||
async def not_event(e: int | Event): ...
|
||||
|
||||
|
||||
async def event_type(t: str = EventType()) -> str:
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
from typing import Union
|
||||
|
||||
|
||||
async def exc(e: Exception, x: Union[ValueError, TypeError]) -> Exception:
|
||||
async def exc(e: Exception, x: ValueError | TypeError) -> Exception:
|
||||
assert e == x
|
||||
return e
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from typing import Any, TypeVar, Union
|
||||
from typing import Any, TypeVar
|
||||
|
||||
from nonebot.adapters import Event
|
||||
from nonebot.matcher import Matcher
|
||||
@@ -36,8 +36,8 @@ class BarMatcher(Matcher): ...
|
||||
|
||||
|
||||
async def union_matcher(
|
||||
m: Union[FooMatcher, BarMatcher],
|
||||
) -> Union[FooMatcher, BarMatcher]:
|
||||
m: FooMatcher | BarMatcher,
|
||||
) -> FooMatcher | BarMatcher:
|
||||
return m
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ async def generic_matcher_none(m: CM) -> CM:
|
||||
return m
|
||||
|
||||
|
||||
async def not_matcher(m: Union[int, Matcher]): ...
|
||||
async def not_matcher(m: int | Matcher): ...
|
||||
|
||||
|
||||
async def receive(e: Event = Received("test")) -> Event:
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
from typing import Optional
|
||||
|
||||
from nonebot.adapters import Bot, Event, Message
|
||||
from nonebot.matcher import Matcher
|
||||
from nonebot.params import Arg, Depends
|
||||
@@ -12,11 +10,11 @@ def dependency():
|
||||
|
||||
async def complex_priority(
|
||||
sub: int = Depends(dependency),
|
||||
bot: Optional[Bot] = None,
|
||||
event: Optional[Event] = None,
|
||||
bot: Bot | None = None,
|
||||
event: Event | None = None,
|
||||
state: T_State = {},
|
||||
matcher: Optional[Matcher] = None,
|
||||
matcher: Matcher | None = None,
|
||||
arg: Message = Arg(),
|
||||
exception: Optional[Exception] = None,
|
||||
exception: Exception | None = None,
|
||||
default: int = 1,
|
||||
): ...
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
from contextlib import asynccontextmanager
|
||||
from typing import Optional
|
||||
|
||||
from nonebug import App
|
||||
import pytest
|
||||
@@ -19,8 +18,8 @@ from utils import FakeAdapter
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_adapter_connect(app: App, driver: Driver):
|
||||
last_connect_bot: Optional[Bot] = None
|
||||
last_disconnect_bot: Optional[Bot] = None
|
||||
last_connect_bot: Bot | None = None
|
||||
last_disconnect_bot: Bot | None = None
|
||||
|
||||
def _fake_bot_connect(bot: Bot):
|
||||
nonlocal last_connect_bot
|
||||
@@ -75,8 +74,8 @@ async def test_adapter_connect(app: App, driver: Driver):
|
||||
indirect=True,
|
||||
)
|
||||
def test_adapter_server(driver: Driver):
|
||||
last_http_setup: Optional[HTTPServerSetup] = None
|
||||
last_ws_setup: Optional[WebSocketServerSetup] = None
|
||||
last_http_setup: HTTPServerSetup | None = None
|
||||
last_ws_setup: WebSocketServerSetup | None = None
|
||||
|
||||
def _fake_setup_http_server(setup: HTTPServerSetup):
|
||||
nonlocal last_http_setup
|
||||
@@ -142,7 +141,7 @@ def test_adapter_server(driver: Driver):
|
||||
indirect=True,
|
||||
)
|
||||
async def test_adapter_http_client(driver: Driver):
|
||||
last_request: Optional[Request] = None
|
||||
last_request: Request | None = None
|
||||
|
||||
async def _fake_request(request: Request):
|
||||
nonlocal last_request
|
||||
@@ -190,7 +189,7 @@ async def test_adapter_http_client(driver: Driver):
|
||||
)
|
||||
async def test_adapter_websocket_client(driver: Driver):
|
||||
_fake_ws = object()
|
||||
_last_request: Optional[Request] = None
|
||||
_last_request: Request | None = None
|
||||
|
||||
@asynccontextmanager
|
||||
async def _fake_websocket(setup: Request):
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from typing import Any, Optional
|
||||
from typing import Any
|
||||
|
||||
import anyio
|
||||
from nonebug import App
|
||||
@@ -123,7 +123,7 @@ async def test_bot_called_api_hook_simple(app: App):
|
||||
|
||||
async def called_api_hook(
|
||||
bot: Bot,
|
||||
exception: Optional[Exception],
|
||||
exception: Exception | None,
|
||||
api: str,
|
||||
data: dict[str, Any],
|
||||
result: Any,
|
||||
@@ -155,7 +155,7 @@ async def test_bot_called_api_hook_mock(app: App):
|
||||
|
||||
async def called_api_hook(
|
||||
bot: Bot,
|
||||
exception: Optional[Exception],
|
||||
exception: Exception | None,
|
||||
api: str,
|
||||
data: dict[str, Any],
|
||||
result: Any,
|
||||
@@ -201,7 +201,7 @@ async def test_bot_called_api_hook_multi_mock(app: App):
|
||||
|
||||
async def called_api_hook1(
|
||||
bot: Bot,
|
||||
exception: Optional[Exception],
|
||||
exception: Exception | None,
|
||||
api: str,
|
||||
data: dict[str, Any],
|
||||
result: Any,
|
||||
@@ -214,7 +214,7 @@ async def test_bot_called_api_hook_multi_mock(app: App):
|
||||
|
||||
async def called_api_hook2(
|
||||
bot: Bot,
|
||||
exception: Optional[Exception],
|
||||
exception: Exception | None,
|
||||
api: str,
|
||||
data: dict[str, Any],
|
||||
result: Any,
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import sys
|
||||
from typing import Optional
|
||||
|
||||
from nonebug import App
|
||||
import pytest
|
||||
@@ -326,7 +325,7 @@ async def test_run_postprocessor(app: App, monkeypatch: pytest.MonkeyPatch):
|
||||
event: Event,
|
||||
state: T_State,
|
||||
matcher: Matcher,
|
||||
exception: Optional[Exception],
|
||||
exception: Exception | None,
|
||||
sub: int = Depends(_dependency),
|
||||
default: int = 1,
|
||||
):
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from dataclasses import dataclass
|
||||
from typing import Annotated, Any, Optional
|
||||
from typing import Annotated, Any
|
||||
|
||||
from pydantic import BaseModel, ValidationError
|
||||
import pytest
|
||||
@@ -144,7 +144,7 @@ def test_validate_json():
|
||||
test3: bool
|
||||
test4: dict
|
||||
test5: list
|
||||
test6: Optional[int]
|
||||
test6: int | None
|
||||
|
||||
assert type_validate_json(
|
||||
TestModel,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from typing import TYPE_CHECKING, Optional, Union
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
import pytest
|
||||
@@ -16,8 +16,8 @@ class Simple(BaseModel):
|
||||
|
||||
class Example(BaseSettings):
|
||||
if TYPE_CHECKING:
|
||||
_env_file: Optional[DOTENV_TYPE] = ".env", ".env.example"
|
||||
_env_nested_delimiter: Optional[str] = "__"
|
||||
_env_file: DOTENV_TYPE | None = ".env", ".env.example"
|
||||
_env_nested_delimiter: str | None = "__"
|
||||
|
||||
if PYDANTIC_V2:
|
||||
model_config = SettingsConfig(
|
||||
@@ -32,10 +32,10 @@ class Example(BaseSettings):
|
||||
env_nested_delimiter = "__"
|
||||
|
||||
simple: str = ""
|
||||
int_str: Union[int, str] = LegacyUnionField(default="")
|
||||
int_str: int | str = LegacyUnionField(default="")
|
||||
complex: list[int] = Field(default=[1])
|
||||
complex_none: Optional[list[int]] = None
|
||||
complex_union: Union[int, list[int]] = 1
|
||||
complex_none: list[int] | None = None
|
||||
complex_union: int | list[int] = 1
|
||||
nested: Simple = Simple()
|
||||
nested_inner: Simple = Simple()
|
||||
aliased_simple: str = Field(default="", alias="alias_simple")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from http.cookies import SimpleCookie
|
||||
import json
|
||||
from typing import Any, Optional
|
||||
from typing import Any
|
||||
|
||||
from aiohttp import ClientSession, ClientWebSocketResponse, WSMessage, WSMsgType
|
||||
import anyio
|
||||
@@ -173,7 +173,7 @@ async def test_websocket_server(app: App, driver: Driver):
|
||||
async def test_cross_context(app: App, driver: Driver):
|
||||
assert isinstance(driver, ASGIMixin)
|
||||
|
||||
ws: Optional[WebSocket] = None
|
||||
ws: WebSocket | None = None
|
||||
ws_ready = anyio.Event()
|
||||
ws_should_close = anyio.Event()
|
||||
|
||||
@@ -651,7 +651,7 @@ async def test_aiohttp_websocket_close_frame(msg_type: str) -> None:
|
||||
def closed(self) -> bool:
|
||||
return True
|
||||
|
||||
async def receive(self, timeout: Optional[float] = None) -> WSMessage: # noqa: ASYNC109
|
||||
async def receive(self, timeout: float | None = None) -> WSMessage: # noqa: ASYNC109
|
||||
return WSMessage(type=WSMsgType[msg_type], data=None, extra=None)
|
||||
|
||||
async with ClientSession() as session:
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
from typing import Optional
|
||||
|
||||
from nonebug import App
|
||||
import pytest
|
||||
|
||||
@@ -138,7 +136,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
|
||||
app: App, session_ids: tuple[str, ...], session_id: str | None, expected: bool
|
||||
):
|
||||
dependent = next(iter(USER(*session_ids).checkers))
|
||||
checker = dependent.call
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
from collections.abc import Callable
|
||||
from dataclasses import asdict
|
||||
from functools import wraps
|
||||
from pathlib import Path
|
||||
import sys
|
||||
from typing import Callable, TypeVar
|
||||
from typing import TypeVar
|
||||
from typing_extensions import ParamSpec
|
||||
|
||||
import pytest
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from typing import Callable, Optional
|
||||
from collections.abc import Callable
|
||||
|
||||
import pytest
|
||||
|
||||
@@ -103,7 +103,7 @@ from nonebot.typing import T_RuleChecker
|
||||
)
|
||||
def test_on(
|
||||
matcher_name: str,
|
||||
pre_rule_factory: Optional[Callable[[type[Event]], T_RuleChecker]],
|
||||
pre_rule_factory: Callable[[type[Event]], T_RuleChecker] | None,
|
||||
has_permission: bool,
|
||||
):
|
||||
import plugins.plugin.matchers as module
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import re
|
||||
from re import Match
|
||||
from typing import Optional, Union
|
||||
|
||||
from nonebug import App
|
||||
import pytest
|
||||
@@ -163,10 +162,10 @@ async def test_trie(app: App):
|
||||
],
|
||||
)
|
||||
async def test_startswith(
|
||||
msg: Union[str, tuple[str, ...]],
|
||||
msg: str | tuple[str, ...],
|
||||
ignorecase: bool,
|
||||
type: str,
|
||||
text: Optional[str],
|
||||
text: str | None,
|
||||
expected: bool,
|
||||
):
|
||||
test_startswith = startswith(msg, ignorecase)
|
||||
@@ -203,10 +202,10 @@ async def test_startswith(
|
||||
],
|
||||
)
|
||||
async def test_endswith(
|
||||
msg: Union[str, tuple[str, ...]],
|
||||
msg: str | tuple[str, ...],
|
||||
ignorecase: bool,
|
||||
type: str,
|
||||
text: Optional[str],
|
||||
text: str | None,
|
||||
expected: bool,
|
||||
):
|
||||
test_endswith = endswith(msg, ignorecase)
|
||||
@@ -243,10 +242,10 @@ async def test_endswith(
|
||||
],
|
||||
)
|
||||
async def test_fullmatch(
|
||||
msg: Union[str, tuple[str, ...]],
|
||||
msg: str | tuple[str, ...],
|
||||
ignorecase: bool,
|
||||
type: str,
|
||||
text: Optional[str],
|
||||
text: str | None,
|
||||
expected: bool,
|
||||
):
|
||||
test_fullmatch = fullmatch(msg, ignorecase)
|
||||
@@ -281,7 +280,7 @@ async def test_fullmatch(
|
||||
async def test_keyword(
|
||||
kws: tuple[str, ...],
|
||||
type: str,
|
||||
text: Optional[str],
|
||||
text: str | None,
|
||||
expected: bool,
|
||||
):
|
||||
test_keyword = keyword(*kws)
|
||||
@@ -324,10 +323,10 @@ async def test_keyword(
|
||||
)
|
||||
async def test_command(
|
||||
cmds: tuple[tuple[str, ...]],
|
||||
force_whitespace: Optional[Union[str, bool]],
|
||||
force_whitespace: str | bool | None,
|
||||
cmd: tuple[str, ...],
|
||||
whitespace: Optional[str],
|
||||
arg_text: Optional[str],
|
||||
whitespace: str | None,
|
||||
arg_text: str | None,
|
||||
expected: bool,
|
||||
):
|
||||
test_command = command(*cmds, force_whitespace=force_whitespace)
|
||||
@@ -492,9 +491,9 @@ async def test_shell_command():
|
||||
async def test_regex(
|
||||
pattern: str,
|
||||
type: str,
|
||||
text: Optional[str],
|
||||
text: str | None,
|
||||
expected: bool,
|
||||
matched: Optional[Match[str]],
|
||||
matched: Match[str] | None,
|
||||
):
|
||||
test_regex = regex(pattern)
|
||||
dependent = next(iter(test_regex.checkers))
|
||||
@@ -507,7 +506,7 @@ async def test_regex(
|
||||
event = make_fake_event(_type=type, _message=message)()
|
||||
state = {}
|
||||
assert await dependent(event=event, state=state) == expected
|
||||
result: Optional[Match[str]] = state.get(REGEX_MATCHED)
|
||||
result: Match[str] | None = state.get(REGEX_MATCHED)
|
||||
if matched is None:
|
||||
assert result is None
|
||||
else:
|
||||
|
||||
@@ -23,7 +23,8 @@ def test_loguru_escape_tag():
|
||||
def test_generic_check_issubclass():
|
||||
assert generic_check_issubclass(int, (int, float))
|
||||
assert not generic_check_issubclass(str, (int, float))
|
||||
assert generic_check_issubclass(Union[int, float, None], (int, float))
|
||||
assert generic_check_issubclass(Union[int, float, None], (int, float)) # noqa: UP007
|
||||
assert generic_check_issubclass(int | float | None, (int, float))
|
||||
assert generic_check_issubclass(Literal[1, 2, 3], int)
|
||||
assert not generic_check_issubclass(Literal[1, 2, "3"], int)
|
||||
assert generic_check_issubclass(List[int], list) # noqa: UP006
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
from collections.abc import Iterable, Mapping
|
||||
from typing import Optional, Union
|
||||
from typing_extensions import override
|
||||
|
||||
from pydantic import create_model
|
||||
@@ -60,7 +59,7 @@ class FakeMessage(Message[FakeMessageSegment]):
|
||||
|
||||
@staticmethod
|
||||
@override
|
||||
def _construct(msg: Union[str, Iterable[Mapping]]):
|
||||
def _construct(msg: str | Iterable[Mapping]):
|
||||
if isinstance(msg, str):
|
||||
yield FakeMessageSegment.text(msg)
|
||||
else:
|
||||
@@ -69,21 +68,19 @@ class FakeMessage(Message[FakeMessageSegment]):
|
||||
return
|
||||
|
||||
@override
|
||||
def __add__(
|
||||
self, other: Union[str, FakeMessageSegment, Iterable[FakeMessageSegment]]
|
||||
):
|
||||
def __add__(self, other: str | FakeMessageSegment | Iterable[FakeMessageSegment]):
|
||||
other = escape_text(other) if isinstance(other, str) else other
|
||||
return super().__add__(other)
|
||||
|
||||
|
||||
def make_fake_event(
|
||||
_base: Optional[type[Event]] = None,
|
||||
_base: type[Event] | None = None,
|
||||
_type: str = "message",
|
||||
_name: str = "test",
|
||||
_description: str = "test",
|
||||
_user_id: Optional[str] = "test",
|
||||
_session_id: Optional[str] = "test",
|
||||
_message: Optional[Message] = None,
|
||||
_user_id: str | None = "test",
|
||||
_session_id: str | None = "test",
|
||||
_message: Message | None = None,
|
||||
_to_me: bool = True,
|
||||
**fields,
|
||||
) -> type[Event]:
|
||||
|
||||
Reference in New Issue
Block a user