From 4974c596eccaf5587df018997c92401528202bc9 Mon Sep 17 00:00:00 2001 From: Ju4tCode <42488585+yanyongyu@users.noreply.github.com> Date: Sun, 14 Aug 2022 19:41:00 +0800 Subject: [PATCH] :boom: remove Python 3.7 support (#1148) --- .github/actions/setup-python/action.yml | 2 +- .github/workflows/codecov.yml | 2 +- README.md | 2 +- nonebot/__init__.py | 5 +- nonebot/consts.py | 2 +- nonebot/dependencies/__init__.py | 50 +++--- nonebot/dependencies/utils.py | 3 +- nonebot/drivers/_block_driver.py | 21 +-- nonebot/drivers/fastapi.py | 15 +- nonebot/internal/adapter/bot.py | 13 +- nonebot/internal/driver/driver.py | 16 +- nonebot/internal/matcher.py | 47 +++++- nonebot/internal/params.py | 3 +- nonebot/internal/permission.py | 4 +- nonebot/internal/rule.py | 4 +- nonebot/message.py | 121 ++++++-------- nonebot/rule.py | 6 +- nonebot/typing.py | 37 +++-- nonebot/utils.py | 22 ++- packages/nonebot-plugin-docs/README.md | 2 +- packages/nonebot-plugin-docs/pyproject.toml | 2 +- poetry.lock | 169 ++------------------ pyproject.toml | 2 +- tests/test_driver.py | 24 +++ website/docs/README.md | 2 +- website/docs/start/installation.mdx | 2 +- 26 files changed, 261 insertions(+), 317 deletions(-) diff --git a/.github/actions/setup-python/action.yml b/.github/actions/setup-python/action.yml index d164ca79..35d70382 100644 --- a/.github/actions/setup-python/action.yml +++ b/.github/actions/setup-python/action.yml @@ -5,7 +5,7 @@ inputs: python-version: description: Python version required: false - default: "3.9" + default: "3.10" runs: using: "composite" diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index 6303d5ab..3f0b2915 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -15,7 +15,7 @@ jobs: cancel-in-progress: true strategy: matrix: - python-version: ["3.7", "3.8", "3.9", "3.10"] + python-version: ["3.8", "3.9", "3.10"] os: [ubuntu-latest, windows-latest, macos-latest] fail-fast: false env: diff --git a/README.md b/README.md index 962f622c..e2c6f87d 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ _✨ 跨平台 Python 异步机器人框架 ✨_ pypi - python + python codecov diff --git a/nonebot/__init__.py b/nonebot/__init__.py index f12acba0..50592b26 100644 --- a/nonebot/__init__.py +++ b/nonebot/__init__.py @@ -171,8 +171,7 @@ def get_bots() -> Dict[str, Bot]: bots = nonebot.get_bots() ``` """ - driver = get_driver() - return driver.bots + return get_driver().bots def _resolve_dot_notation( @@ -240,7 +239,7 @@ def init(*, _env_file: Optional[str] = None, **kwargs: Any) -> None: f"Loaded Config: {escape_tag(str(config.dict()))}" ) - DriverClass: Type[Driver] = _resolve_combine_expr(config.driver) + DriverClass = _resolve_combine_expr(config.driver) _driver = DriverClass(env, config) diff --git a/nonebot/consts.py b/nonebot/consts.py index 3fe93486..31b781d6 100644 --- a/nonebot/consts.py +++ b/nonebot/consts.py @@ -4,7 +4,7 @@ FrontMatter: sidebar_position: 9 description: nonebot.consts 模块 """ -from typing_extensions import Literal +from typing import Literal # used by Matcher RECEIVE_KEY: Literal["_receive_{id}"] = "_receive_{id}" diff --git a/nonebot/dependencies/__init__.py b/nonebot/dependencies/__init__.py index 42565b9b..be17a054 100644 --- a/nonebot/dependencies/__init__.py +++ b/nonebot/dependencies/__init__.py @@ -7,7 +7,18 @@ FrontMatter: import abc import inspect -from typing import Any, Dict, List, Type, Generic, TypeVar, Callable, Optional +from typing import ( + Any, + Dict, + List, + Type, + Generic, + TypeVar, + Callable, + Optional, + Awaitable, + cast, +) from pydantic import BaseConfig from pydantic.schema import get_annotation_from_field_info @@ -15,6 +26,7 @@ from pydantic.fields import Required, FieldInfo, Undefined, ModelField from nonebot.log import logger from nonebot.exception import TypeMisMatch +from nonebot.typing import _DependentCallable from nonebot.utils import run_sync, is_coroutine_callable from .utils import check_field_type, get_typed_signature @@ -64,7 +76,7 @@ class Dependent(Generic[R]): def __init__( self, *, - call: Callable[..., Any], + call: _DependentCallable[R], pre_checkers: Optional[List[Param]] = None, params: Optional[List[ModelField]] = None, parameterless: Optional[List[Param]] = None, @@ -89,29 +101,25 @@ class Dependent(Generic[R]): values = await self.solve(**kwargs) if is_coroutine_callable(self.call): - return await self.call(**values) + return await cast(Callable[..., Awaitable[R]], self.call)(**values) else: - return await run_sync(self.call)(**values) + return await run_sync(cast(Callable[..., R], self.call))(**values) def parse_param(self, name: str, param: inspect.Parameter) -> Param: for allow_type in self.allow_types: - field_info = allow_type._check_param(self, name, param) - if field_info: + if field_info := allow_type._check_param(self, name, param): return field_info - else: - raise ValueError( - f"Unknown parameter {name} for function {self.call} with type {param.annotation}" - ) + raise ValueError( + f"Unknown parameter {name} for function {self.call} with type {param.annotation}" + ) def parse_parameterless(self, value: Any) -> Param: for allow_type in self.allow_types: - field_info = allow_type._check_parameterless(self, value) - if field_info: + if field_info := allow_type._check_parameterless(self, value): return field_info - else: - raise ValueError( - f"Unknown parameterless {value} for function {self.call} with type {type(value)}" - ) + raise ValueError( + f"Unknown parameterless {value} for function {self.call} with type {type(value)}" + ) def prepend_parameterless(self, value: Any) -> None: self.parameterless.insert(0, self.parse_parameterless(value)) @@ -121,12 +129,12 @@ class Dependent(Generic[R]): @classmethod def parse( - cls: Type[T], + cls, *, - call: Callable[..., Any], + call: _DependentCallable[R], parameterless: Optional[List[Any]] = None, allow_types: Optional[List[Type[Param]]] = None, - ) -> T: + ) -> "Dependent[R]": signature = get_typed_signature(call) params = signature.parameters dependent = cls( @@ -141,10 +149,10 @@ class Dependent(Generic[R]): if isinstance(default_value, Param): field_info = default_value - default_value = field_info.default else: field_info = dependent.parse_param(param_name, param) - default_value = field_info.default + + default_value = field_info.default annotation: Any = Any required = default_value == Required diff --git a/nonebot/dependencies/utils.py b/nonebot/dependencies/utils.py index c7f5470b..7a9b1d5b 100644 --- a/nonebot/dependencies/utils.py +++ b/nonebot/dependencies/utils.py @@ -28,8 +28,7 @@ def get_typed_signature(call: Callable[..., Any]) -> inspect.Signature: ) for param in signature.parameters.values() ] - typed_signature = inspect.Signature(typed_params) - return typed_signature + return inspect.Signature(typed_params) def get_typed_annotation(param: inspect.Parameter, globalns: Dict[str, Any]) -> Any: diff --git a/nonebot/drivers/_block_driver.py b/nonebot/drivers/_block_driver.py index 0c47caa3..ee020423 100644 --- a/nonebot/drivers/_block_driver.py +++ b/nonebot/drivers/_block_driver.py @@ -1,7 +1,7 @@ import signal import asyncio import threading -from typing import Set, Union, Callable, Awaitable +from typing import Set, Union, Callable, Awaitable, cast from nonebot.log import logger from nonebot.drivers import Driver @@ -9,8 +9,7 @@ from nonebot.typing import overrides from nonebot.config import Env, Config from nonebot.utils import run_sync, is_coroutine_callable -STARTUP_FUNC = Callable[[], Union[None, Awaitable[None]]] -SHUTDOWN_FUNC = Callable[[], Union[None, Awaitable[None]]] +HOOK_FUNC = Union[Callable[[], None], Callable[[], Awaitable[None]]] HANDLED_SIGNALS = ( signal.SIGINT, # Unix signal 2. Sent by Ctrl+C. signal.SIGTERM, # Unix signal 15. Sent by `kill `. @@ -20,8 +19,8 @@ HANDLED_SIGNALS = ( class BlockDriver(Driver): def __init__(self, env: Env, config: Config): super().__init__(env, config) - self.startup_funcs: Set[STARTUP_FUNC] = set() - self.shutdown_funcs: Set[SHUTDOWN_FUNC] = set() + self.startup_funcs: Set[HOOK_FUNC] = set() + self.shutdown_funcs: Set[HOOK_FUNC] = set() self.should_exit: asyncio.Event = asyncio.Event() self.force_exit: bool = False @@ -38,7 +37,7 @@ class BlockDriver(Driver): return logger @overrides(Driver) - def on_startup(self, func: STARTUP_FUNC) -> STARTUP_FUNC: + def on_startup(self, func: HOOK_FUNC) -> HOOK_FUNC: """ 注册一个启动时执行的函数 """ @@ -46,7 +45,7 @@ class BlockDriver(Driver): return func @overrides(Driver) - def on_shutdown(self, func: SHUTDOWN_FUNC) -> SHUTDOWN_FUNC: + def on_shutdown(self, func: HOOK_FUNC) -> HOOK_FUNC: """ 注册一个停止时执行的函数 """ @@ -71,7 +70,9 @@ class BlockDriver(Driver): async def startup(self): # run startup cors = [ - startup() if is_coroutine_callable(startup) else run_sync(startup)() + cast(Callable[..., Awaitable[None]], startup)() + if is_coroutine_callable(startup) + else run_sync(startup)() for startup in self.startup_funcs ] if cors: @@ -94,7 +95,9 @@ class BlockDriver(Driver): logger.info("Waiting for application shutdown.") # run shutdown cors = [ - shutdown() if is_coroutine_callable(shutdown) else run_sync(shutdown)() + cast(Callable[..., Awaitable[None]], shutdown)() + if is_coroutine_callable(shutdown) + else run_sync(shutdown)() for shutdown in self.shutdown_funcs ] if cors: diff --git a/nonebot/drivers/fastapi.py b/nonebot/drivers/fastapi.py index a0142ea1..258d3aa4 100644 --- a/nonebot/drivers/fastapi.py +++ b/nonebot/drivers/fastapi.py @@ -9,7 +9,9 @@ FrontMatter: description: nonebot.drivers.fastapi 模块 """ + import logging +import contextlib from functools import wraps from typing import Any, List, Tuple, Union, Callable, Optional @@ -186,14 +188,12 @@ class Driver(ReverseDriver): setup: HTTPServerSetup, ) -> Response: json: Any = None - try: + with contextlib.suppress(Exception): json = await request.json() - except Exception: - pass data: Optional[dict] = None files: Optional[List[Tuple[str, FileTypes]]] = None - try: + with contextlib.suppress(Exception): form = await request.form() data = {} files = [] @@ -204,8 +204,7 @@ class Driver(ReverseDriver): ) else: data[key] = value - except Exception: - pass + http_request = BaseRequest( request.method, str(request.url), @@ -219,7 +218,9 @@ class Driver(ReverseDriver): ) response = await setup.handle_func(http_request) - return Response(response.content, response.status_code, dict(response.headers)) + return Response( + response.content, response.status_code, dict(response.headers.items()) + ) async def _handle_ws(self, websocket: WebSocket, setup: WebSocketServerSetup): request = BaseRequest( diff --git a/nonebot/internal/adapter/bot.py b/nonebot/internal/adapter/bot.py index 6d9a0074..5bedecb9 100644 --- a/nonebot/internal/adapter/bot.py +++ b/nonebot/internal/adapter/bot.py @@ -1,8 +1,7 @@ import abc import asyncio from functools import partial -from typing_extensions import Protocol -from typing import TYPE_CHECKING, Any, Set, Union, Optional +from typing import TYPE_CHECKING, Any, Set, Union, Optional, Protocol from nonebot.log import logger from nonebot.config import Config @@ -72,8 +71,7 @@ class Bot(abc.ABC): skip_calling_api: bool = False exception: Optional[Exception] = None - coros = list(map(lambda x: x(self, api, data), self._calling_api_hook)) - if coros: + if coros := [hook(self, api, data) for hook in self._calling_api_hook]: try: logger.debug("Running CallingAPI hooks...") await asyncio.gather(*coros) @@ -95,10 +93,9 @@ class Bot(abc.ABC): except Exception as e: exception = e - coros = list( - map(lambda x: x(self, exception, api, data, result), self._called_api_hook) - ) - if coros: + if coros := [ + hook(self, exception, api, data, result) for hook in self._called_api_hook + ]: try: logger.debug("Running CalledAPI hooks...") await asyncio.gather(*coros) diff --git a/nonebot/internal/driver/driver.py b/nonebot/internal/driver/driver.py index 8ca672ca..d0846aed 100644 --- a/nonebot/internal/driver/driver.py +++ b/nonebot/internal/driver/driver.py @@ -233,13 +233,11 @@ def combine_driver(driver: Type[Driver], *mixins: Type[ForwardMixin]) -> Type[Dr if not mixins: return driver - class CombinedDriver(*mixins, driver, ForwardDriver): # type: ignore - @property - def type(self) -> str: - return ( - driver.type.__get__(self) - + "+" - + "+".join(map(lambda x: x.type.__get__(self), mixins)) - ) + def type_(self: ForwardDriver) -> str: + return ( + driver.type.__get__(self) + + "+" + + "+".join(map(lambda x: x.type.__get__(self), mixins)) + ) - return CombinedDriver + return type("CombinedDriver", (*mixins, driver, ForwardDriver), {"type": property(type_)}) # type: ignore diff --git a/nonebot/internal/matcher.py b/nonebot/internal/matcher.py index d95c55cf..4d05b786 100644 --- a/nonebot/internal/matcher.py +++ b/nonebot/internal/matcher.py @@ -14,6 +14,7 @@ from typing import ( Callable, NoReturn, Optional, + overload, ) from nonebot.log import logger @@ -551,7 +552,17 @@ class Matcher(metaclass=MatcherMeta): """ raise SkippedException - def get_receive(self, id: str, default: T = None) -> Union[Event, T]: + @overload + def get_receive(self, id: str) -> Union[Event, None]: + ... + + @overload + def get_receive(self, id: str, default: T) -> Union[Event, T]: + ... + + def get_receive( + self, id: str, default: Optional[T] = None + ) -> Optional[Union[Event, T]]: """获取一个 `receive` 事件 如果没有找到对应的事件,返回 `default` 值 @@ -563,14 +574,34 @@ class Matcher(metaclass=MatcherMeta): self.state[RECEIVE_KEY.format(id=id)] = event self.state[LAST_RECEIVE_KEY] = event - def get_last_receive(self, default: T = None) -> Union[Event, T]: + @overload + def get_last_receive(self) -> Union[Event, None]: + ... + + @overload + def get_last_receive(self, default: T) -> Union[Event, T]: + ... + + def get_last_receive( + self, default: Optional[T] = None + ) -> Optional[Union[Event, T]]: """获取最近一次 `receive` 事件 如果没有事件,返回 `default` 值 """ return self.state.get(LAST_RECEIVE_KEY, default) - def get_arg(self, key: str, default: T = None) -> Union[Message, T]: + @overload + def get_arg(self, key: str) -> Union[Message, None]: + ... + + @overload + def get_arg(self, key: str, default: T) -> Union[Message, T]: + ... + + def get_arg( + self, key: str, default: Optional[T] = None + ) -> Optional[Union[Message, T]]: """获取一个 `got` 消息 如果没有找到对应的消息,返回 `default` 值 @@ -587,7 +618,15 @@ class Matcher(metaclass=MatcherMeta): else: self.state[REJECT_TARGET] = target - def get_target(self, default: T = None) -> Union[str, T]: + @overload + def get_target(self) -> Union[str, None]: + ... + + @overload + def get_target(self, default: T) -> Union[str, T]: + ... + + def get_target(self, default: Optional[T] = None) -> Optional[Union[str, T]]: return self.state.get(REJECT_TARGET, default) def stop_propagation(self): diff --git a/nonebot/internal/params.py b/nonebot/internal/params.py index 23fd4176..adc42b33 100644 --- a/nonebot/internal/params.py +++ b/nonebot/internal/params.py @@ -1,8 +1,7 @@ import asyncio import inspect import warnings -from typing_extensions import Literal -from typing import TYPE_CHECKING, Any, Callable, Optional, cast +from typing import TYPE_CHECKING, Any, Literal, Callable, Optional, cast from contextlib import AsyncExitStack, contextmanager, asynccontextmanager from pydantic.fields import Required, Undefined, ModelField diff --git a/nonebot/internal/permission.py b/nonebot/internal/permission.py index ec96a97a..48c054a8 100644 --- a/nonebot/internal/permission.py +++ b/nonebot/internal/permission.py @@ -37,14 +37,14 @@ class Permission: ] def __init__(self, *checkers: Union[T_PermissionChecker, Dependent[bool]]) -> None: - self.checkers: Set[Dependent[bool]] = set( + self.checkers: Set[Dependent[bool]] = { checker if isinstance(checker, Dependent) else Dependent[bool].parse( call=checker, allow_types=self.HANDLER_PARAM_TYPES ) for checker in checkers - ) + } """存储 `PermissionChecker`""" async def __call__( diff --git a/nonebot/internal/rule.py b/nonebot/internal/rule.py index a15c8871..b5e2f097 100644 --- a/nonebot/internal/rule.py +++ b/nonebot/internal/rule.py @@ -37,14 +37,14 @@ class Rule: ] def __init__(self, *checkers: Union[T_RuleChecker, Dependent[bool]]) -> None: - self.checkers: Set[Dependent[bool]] = set( + self.checkers: Set[Dependent[bool]] = { checker if isinstance(checker, Dependent) else Dependent[bool].parse( call=checker, allow_types=self.HANDLER_PARAM_TYPES ) for checker in checkers - ) + } """存储 `RuleChecker`""" async def __call__( diff --git a/nonebot/message.py b/nonebot/message.py index b1f1b4b7..762c2e6a 100644 --- a/nonebot/message.py +++ b/nonebot/message.py @@ -8,6 +8,7 @@ FrontMatter: """ import asyncio +import contextlib from datetime import datetime from contextlib import AsyncExitStack from typing import TYPE_CHECKING, Any, Set, Dict, Type, Optional, Coroutine @@ -120,10 +121,8 @@ async def _check_matcher( dependency_cache: Optional[T_DependencyCache] = None, ) -> None: if Matcher.expire_time and datetime.now() > Matcher.expire_time: - try: + with contextlib.suppress(Exception): matchers[priority].remove(Matcher) - except Exception: - pass return try: @@ -138,11 +137,8 @@ async def _check_matcher( return if Matcher.temp: - try: + with contextlib.suppress(Exception): matchers[priority].remove(Matcher) - except Exception: - pass - await _run_matcher(Matcher, bot, event, state, stack, dependency_cache) @@ -157,24 +153,20 @@ async def _run_matcher( logger.info(f"Event will be handled by {Matcher}") matcher = Matcher() - - coros = list( - map( - lambda x: run_coro_with_catch( - x( - matcher=matcher, - bot=bot, - event=event, - state=state, - stack=stack, - dependency_cache=dependency_cache, - ), - (SkippedException,), + if coros := [ + run_coro_with_catch( + proc( + matcher=matcher, + bot=bot, + event=event, + state=state, + stack=stack, + dependency_cache=dependency_cache, ), - _run_preprocessors, + (SkippedException,), ) - ) - if coros: + for proc in _run_preprocessors + ]: try: await asyncio.gather(*coros) except IgnoredException: @@ -184,9 +176,9 @@ async def _run_matcher( return except Exception as e: logger.opt(colors=True, exception=e).error( - "Error when running RunPreProcessors. " - "Running cancelled!" + "Error when running RunPreProcessors. Running cancelled!" ) + return exception = None @@ -200,24 +192,21 @@ async def _run_matcher( ) exception = e - coros = list( - map( - lambda x: run_coro_with_catch( - x( - matcher=matcher, - exception=exception, - bot=bot, - event=event, - state=matcher.state, - stack=stack, - dependency_cache=dependency_cache, - ), - (SkippedException,), + if coros := [ + run_coro_with_catch( + proc( + matcher=matcher, + exception=exception, + bot=bot, + event=event, + state=matcher.state, + stack=stack, + dependency_cache=dependency_cache, ), - _run_postprocessors, + (SkippedException,), ) - ) - if coros: + for proc in _run_postprocessors + ]: try: await asyncio.gather(*coros) except Exception as e: @@ -256,22 +245,19 @@ async def handle_event(bot: "Bot", event: "Event") -> None: dependency_cache: T_DependencyCache = {} async with AsyncExitStack() as stack: - coros = list( - map( - lambda x: run_coro_with_catch( - x( - bot=bot, - event=event, - state=state, - stack=stack, - dependency_cache=dependency_cache, - ), - (SkippedException,), + if coros := [ + run_coro_with_catch( + proc( + bot=bot, + event=event, + state=state, + stack=stack, + dependency_cache=dependency_cache, ), - _event_preprocessors, + (SkippedException,), ) - ) - if coros: + for proc in _event_preprocessors + ]: try: if show_log: logger.debug("Running PreProcessors...") @@ -324,22 +310,19 @@ async def handle_event(bot: "Bot", event: "Event") -> None: "Error when checking Matcher." ) - coros = list( - map( - lambda x: run_coro_with_catch( - x( - bot=bot, - event=event, - state=state, - stack=stack, - dependency_cache=dependency_cache, - ), - (SkippedException,), + if coros := [ + run_coro_with_catch( + proc( + bot=bot, + event=event, + state=state, + stack=stack, + dependency_cache=dependency_cache, ), - _event_postprocessors, + (SkippedException,), ) - ) - if coros: + for proc in _event_postprocessors + ]: try: if show_log: logger.debug("Running PostProcessors...") diff --git a/nonebot/rule.py b/nonebot/rule.py index f10fdff8..2fedfa06 100644 --- a/nonebot/rule.py +++ b/nonebot/rule.py @@ -12,9 +12,8 @@ import re import shlex from itertools import product from argparse import Namespace -from typing_extensions import TypedDict from argparse import ArgumentParser as ArgParser -from typing import Any, List, Tuple, Union, Optional, Sequence, NamedTuple +from typing import Any, List, Tuple, Union, Optional, Sequence, TypedDict, NamedTuple from pygtrie import CharTrie @@ -83,8 +82,7 @@ class TrieRule: message_seg: MessageSegment = message[0] if message_seg.is_text(): segment_text = str(message_seg).lstrip() - pf = cls.prefix.longest_prefix(segment_text) - if pf: + if pf := cls.prefix.longest_prefix(segment_text): value: TRIE_VALUE = pf.value prefix[RAW_CMD_KEY] = pf.key prefix[CMD_START_KEY] = value.command_start diff --git a/nonebot/typing.py b/nonebot/typing.py index d6223fb9..a27513f6 100644 --- a/nonebot/typing.py +++ b/nonebot/typing.py @@ -11,6 +11,7 @@ FrontMatter: sidebar_position: 11 description: nonebot.typing 模块 """ + from typing import ( TYPE_CHECKING, Any, @@ -28,6 +29,8 @@ if TYPE_CHECKING: from nonebot.adapters import Bot from nonebot.permission import Permission +T = TypeVar("T") + T_Wrapped = TypeVar("T_Wrapped", bound=Callable) @@ -41,10 +44,14 @@ def overrides(InterfaceClass: object) -> Callable[[T_Wrapped], T_Wrapped]: return overrider +# state T_State = Dict[Any, Any] """事件处理状态 State 类型""" -T_BotConnectionHook = Callable[..., Awaitable[Any]] +_DependentCallable = Union[Callable[..., T], Callable[..., Awaitable[T]]] + +# driver hooks +T_BotConnectionHook = _DependentCallable[Any] """Bot 连接建立时钩子函数 依赖参数: @@ -53,7 +60,7 @@ T_BotConnectionHook = Callable[..., Awaitable[Any]] - BotParam: Bot 对象 - DefaultParam: 带有默认值的参数 """ -T_BotDisconnectionHook = Callable[..., Awaitable[Any]] +T_BotDisconnectionHook = _DependentCallable[Any] """Bot 连接断开时钩子函数 依赖参数: @@ -62,6 +69,8 @@ T_BotDisconnectionHook = Callable[..., Awaitable[Any]] - BotParam: Bot 对象 - DefaultParam: 带有默认值的参数 """ + +# api hooks T_CallingAPIHook = Callable[["Bot", str, Dict[str, Any]], Awaitable[Any]] """`bot.call_api` 钩子函数""" T_CalledAPIHook = Callable[ @@ -69,7 +78,8 @@ T_CalledAPIHook = Callable[ ] """`bot.call_api` 后执行的函数,参数分别为 bot, exception, api, data, result""" -T_EventPreProcessor = Callable[..., Union[Any, Awaitable[Any]]] +# event hooks +T_EventPreProcessor = _DependentCallable[Any] """事件预处理函数 EventPreProcessor 类型 依赖参数: @@ -80,7 +90,7 @@ T_EventPreProcessor = Callable[..., Union[Any, Awaitable[Any]]] - StateParam: State 对象 - DefaultParam: 带有默认值的参数 """ -T_EventPostProcessor = Callable[..., Union[Any, Awaitable[Any]]] +T_EventPostProcessor = _DependentCallable[Any] """事件预处理函数 EventPostProcessor 类型 依赖参数: @@ -91,7 +101,9 @@ T_EventPostProcessor = Callable[..., Union[Any, Awaitable[Any]]] - StateParam: State 对象 - DefaultParam: 带有默认值的参数 """ -T_RunPreProcessor = Callable[..., Union[Any, Awaitable[Any]]] + +# matcher run hooks +T_RunPreProcessor = _DependentCallable[Any] """事件响应器运行前预处理函数 RunPreProcessor 类型 依赖参数: @@ -103,7 +115,7 @@ T_RunPreProcessor = Callable[..., Union[Any, Awaitable[Any]]] - MatcherParam: Matcher 对象 - DefaultParam: 带有默认值的参数 """ -T_RunPostProcessor = Callable[..., Union[Any, Awaitable[Any]]] +T_RunPostProcessor = _DependentCallable[Any] """事件响应器运行后后处理函数 RunPostProcessor 类型 依赖参数: @@ -117,7 +129,8 @@ T_RunPostProcessor = Callable[..., Union[Any, Awaitable[Any]]] - DefaultParam: 带有默认值的参数 """ -T_RuleChecker = Callable[..., Union[bool, Awaitable[bool]]] +# rule, permission +T_RuleChecker = _DependentCallable[bool] """RuleChecker 即判断是否响应事件的处理函数。 依赖参数: @@ -128,7 +141,7 @@ T_RuleChecker = Callable[..., Union[bool, Awaitable[bool]]] - StateParam: State 对象 - DefaultParam: 带有默认值的参数 """ -T_PermissionChecker = Callable[..., Union[bool, Awaitable[bool]]] +T_PermissionChecker = _DependentCallable[bool] """PermissionChecker 即判断事件是否满足权限的处理函数。 依赖参数: @@ -139,9 +152,9 @@ T_PermissionChecker = Callable[..., Union[bool, Awaitable[bool]]] - DefaultParam: 带有默认值的参数 """ -T_Handler = Callable[..., Any] +T_Handler = _DependentCallable[Any] """Handler 处理函数。""" -T_TypeUpdater = Callable[..., Union[str, Awaitable[str]]] +T_TypeUpdater = _DependentCallable[str] """TypeUpdater 在 Matcher.pause, Matcher.reject 时被运行,用于更新响应的事件类型。默认会更新为 `message`。 依赖参数: @@ -153,7 +166,7 @@ T_TypeUpdater = Callable[..., Union[str, Awaitable[str]]] - MatcherParam: Matcher 对象 - DefaultParam: 带有默认值的参数 """ -T_PermissionUpdater = Callable[..., Union["Permission", Awaitable["Permission"]]] +T_PermissionUpdater = _DependentCallable["Permission"] """PermissionUpdater 在 Matcher.pause, Matcher.reject 时被运行,用于更新会话对象权限。默认会更新为当前事件的触发对象。 依赖参数: @@ -165,5 +178,5 @@ T_PermissionUpdater = Callable[..., Union["Permission", Awaitable["Permission"]] - MatcherParam: Matcher 对象 - DefaultParam: 带有默认值的参数 """ -T_DependencyCache = Dict[Callable[..., Any], "Task[Any]"] +T_DependencyCache = Dict[_DependentCallable[Any], "Task[Any]"] """依赖缓存, 用于存储依赖函数的返回值""" diff --git a/nonebot/utils.py b/nonebot/utils.py index 652a9924..b2aac548 100644 --- a/nonebot/utils.py +++ b/nonebot/utils.py @@ -24,6 +24,7 @@ from typing import ( Coroutine, AsyncGenerator, ContextManager, + overload, ) from pydantic.typing import is_union, is_none_type @@ -129,11 +130,28 @@ async def run_sync_ctx_manager( await run_sync(cm.__exit__)(None, None, None) +@overload async def run_coro_with_catch( coro: Coroutine[Any, Any, T], exc: Tuple[Type[Exception], ...], - return_on_err: R = None, +) -> Union[T, None]: + ... + + +@overload +async def run_coro_with_catch( + coro: Coroutine[Any, Any, T], + exc: Tuple[Type[Exception], ...], + return_on_err: R, ) -> Union[T, R]: + ... + + +async def run_coro_with_catch( + coro: Coroutine[Any, Any, T], + exc: Tuple[Type[Exception], ...], + return_on_err: Optional[R] = None, +) -> Optional[Union[T, R]]: try: return await coro except exc: @@ -173,7 +191,7 @@ def logger_wrapper(logger_name: str): def log(level: str, message: str, exception: Optional[Exception] = None): logger.opt(colors=True, exception=exception).log( - level, f"{escape_tag(logger_name)} | " + message + level, f"{escape_tag(logger_name)} | {message}" ) return log diff --git a/packages/nonebot-plugin-docs/README.md b/packages/nonebot-plugin-docs/README.md index df099b03..16b5ceb3 100644 --- a/packages/nonebot-plugin-docs/README.md +++ b/packages/nonebot-plugin-docs/README.md @@ -17,7 +17,7 @@ _✨ NoneBot 本地文档插件 ✨_ pypi - python + python

## 使用方式 diff --git a/packages/nonebot-plugin-docs/pyproject.toml b/packages/nonebot-plugin-docs/pyproject.toml index bcc1c2f9..9ba24d40 100644 --- a/packages/nonebot-plugin-docs/pyproject.toml +++ b/packages/nonebot-plugin-docs/pyproject.toml @@ -12,7 +12,7 @@ include = ["nonebot_plugin_docs/dist/**/*"] [tool.poetry.dependencies] -python = "^3.7.3" +python = "^3.8" nonebot2 = "^2.0.0-beta.1" [tool.poetry.dev-dependencies] diff --git a/poetry.lock b/poetry.lock index 9d117e33..1687a4e8 100644 --- a/poetry.lock +++ b/poetry.lock @@ -29,14 +29,12 @@ python-versions = ">=3.6" aiodns = {version = "*", optional = true, markers = "extra == \"speedups\""} aiosignal = ">=1.1.2" async-timeout = ">=4.0.0a3,<5.0" -asynctest = {version = "0.13.0", markers = "python_version < \"3.8\""} attrs = ">=17.3.0" Brotli = {version = "*", optional = true, markers = "extra == \"speedups\""} cchardet = {version = "*", optional = true, markers = "extra == \"speedups\""} charset-normalizer = ">=2.0,<3.0" frozenlist = ">=1.1.1" multidict = ">=4.5,<7.0" -typing-extensions = {version = ">=3.7.4", markers = "python_version < \"3.8\""} yarl = ">=1.0,<2.0" [package.extras] @@ -64,7 +62,6 @@ python-versions = ">=3.6.2" [package.dependencies] idna = ">=2.8" sniffio = ">=1.1" -typing-extensions = {version = "*", markers = "python_version < \"3.8\""} [package.extras] doc = ["packaging", "sphinx-rtd-theme", "sphinx-autodoc-typehints (>=1.2.0)"] @@ -79,9 +76,6 @@ category = "dev" optional = false python-versions = ">=3.7" -[package.dependencies] -typing-extensions = {version = "*", markers = "python_version < \"3.8\""} - [package.extras] tests = ["pytest", "pytest-asyncio", "mypy (>=0.800)"] @@ -105,17 +99,6 @@ category = "main" optional = true python-versions = ">=3.6" -[package.dependencies] -typing-extensions = {version = ">=3.6.5", markers = "python_version < \"3.8\""} - -[[package]] -name = "asynctest" -version = "0.13.0" -description = "Enhance the standard unittest package with features for testing asyncio libraries" -category = "main" -optional = true -python-versions = ">=3.5" - [[package]] name = "atomicwrites" version = "1.4.1" @@ -152,7 +135,6 @@ mypy-extensions = ">=0.4.3" pathspec = ">=0.9.0" platformdirs = ">=2" tomli = {version = ">=1.1.0", markers = "python_full_version < \"3.11.0a7\""} -typed-ast = {version = ">=1.4.2", markers = "python_version < \"3.8\" and implementation_name == \"cpython\""} typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""} [package.extras] @@ -233,7 +215,6 @@ python-versions = ">=3.7" [package.dependencies] colorama = {version = "*", markers = "platform_system == \"Windows\""} -importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} [[package]] name = "colorama" @@ -245,7 +226,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [[package]] name = "coverage" -version = "6.4.2" +version = "6.4.3" description = "Code coverage measurement for Python" category = "dev" optional = false @@ -296,15 +277,15 @@ test = ["pytest (>=6.2.4,<7.0.0)", "pytest-cov (>=2.12.0,<4.0.0)", "mypy (==0.91 [[package]] name = "filelock" -version = "3.7.1" +version = "3.8.0" description = "A platform independent file lock." category = "dev" optional = false python-versions = ">=3.7" [package.extras] -docs = ["furo (>=2021.8.17b43)", "sphinx (>=4.1)", "sphinx-autodoc-typehints (>=1.12)"] -testing = ["covdefaults (>=1.2.0)", "coverage (>=4)", "pytest (>=4)", "pytest-cov", "pytest-timeout (>=1.4.2)"] +docs = ["furo (>=2022.6.21)", "sphinx (>=5.1.1)", "sphinx-autodoc-typehints (>=1.19.1)"] +testing = ["covdefaults (>=2.2)", "coverage (>=6.4.2)", "pytest (>=7.1.2)", "pytest-cov (>=3)", "pytest-timeout (>=2.1)"] [[package]] name = "frozenlist" @@ -405,7 +386,6 @@ h11 = "*" h2 = ">=3.1.0" priority = "*" toml = "*" -typing_extensions = {version = ">=3.7.4", markers = "python_version < \"3.8\""} wsproto = ">=0.14.0" [package.extras] @@ -440,23 +420,6 @@ category = "main" optional = false python-versions = ">=3.5" -[[package]] -name = "importlib-metadata" -version = "4.12.0" -description = "Read metadata from Python packages" -category = "main" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""} -zipp = ">=0.5" - -[package.extras] -docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)"] -perf = ["ipython"] -testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.3)", "packaging", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)", "importlib-resources (>=1.3)"] - [[package]] name = "iniconfig" version = "1.1.1" @@ -651,9 +614,6 @@ category = "dev" optional = false python-versions = ">=3.6" -[package.dependencies] -importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} - [package.extras] dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] @@ -669,7 +629,6 @@ python-versions = ">=3.7" [package.dependencies] cfgv = ">=2.0.0" identify = ">=1.0.0" -importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} nodeenv = ">=0.11.1" pyyaml = ">=5.1" toml = "*" @@ -704,7 +663,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [[package]] name = "pycares" -version = "4.2.1" +version = "4.2.2" description = "Python interface for c-ares" category = "main" optional = true @@ -771,7 +730,6 @@ python-versions = ">=3.7" atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} attrs = ">=19.2.0" colorama = {version = "*", markers = "sys_platform == \"win32\""} -importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} iniconfig = "*" packaging = "*" pluggy = ">=0.12,<2.0" @@ -791,7 +749,6 @@ python-versions = ">=3.7" [package.dependencies] pytest = ">=6.1.0" -typing-extensions = {version = ">=3.7.2", markers = "python_version < \"3.8\""} [package.extras] testing = ["coverage (>=6.2)", "hypothesis (>=5.7.1)", "flaky (>=3.5.0)", "mypy (>=0.931)", "pytest-trio (>=0.7.0)"] @@ -873,12 +830,10 @@ aiofiles = "*" blinker = "*" click = "*" hypercorn = ">=0.11.2" -importlib_metadata = {version = "*", markers = "python_version < \"3.8\""} itsdangerous = "*" jinja2 = "*" markupsafe = "*" toml = "*" -typing_extensions = {version = "*", markers = "python_version < \"3.8\""} werkzeug = ">=2.0.0" [package.extras] @@ -965,20 +920,12 @@ python-versions = ">=3.7" [[package]] name = "tomlkit" -version = "0.11.1" +version = "0.11.3" description = "Style preserving TOML library" category = "main" optional = false python-versions = ">=3.6,<4.0" -[[package]] -name = "typed-ast" -version = "1.5.4" -description = "a fork of Python 2 and 3 ast modules with type comment support" -category = "dev" -optional = false -python-versions = ">=3.6" - [[package]] name = "typing-extensions" version = "4.3.0" @@ -1015,7 +962,6 @@ h11 = ">=0.8" httptools = {version = ">=0.4.0", optional = true, markers = "extra == \"standard\""} python-dotenv = {version = ">=0.13", optional = true, markers = "extra == \"standard\""} PyYAML = {version = ">=5.1", optional = true, markers = "extra == \"standard\""} -typing-extensions = {version = "*", markers = "python_version < \"3.8\""} uvloop = {version = ">=0.14.0,<0.15.0 || >0.15.0,<0.15.1 || >0.15.1", optional = true, markers = "sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"PyPy\" and extra == \"standard\""} watchfiles = {version = ">=0.13", optional = true, markers = "extra == \"standard\""} websockets = {version = ">=10.0", optional = true, markers = "extra == \"standard\""} @@ -1038,21 +984,20 @@ test = ["aiohttp", "flake8 (>=3.9.2,<3.10.0)", "psutil", "pycodestyle (>=2.7.0,< [[package]] name = "virtualenv" -version = "20.16.2" +version = "20.16.3" description = "Virtual Python Environment builder" category = "dev" optional = false python-versions = ">=3.6" [package.dependencies] -distlib = ">=0.3.1,<1" -filelock = ">=3.2,<4" -importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} -platformdirs = ">=2,<3" +distlib = ">=0.3.5,<1" +filelock = ">=3.4.1,<4" +platformdirs = ">=2.4,<3" [package.extras] -docs = ["proselint (>=0.10.2)", "sphinx (>=3)", "sphinx-argparse (>=0.2.5)", "sphinx-rtd-theme (>=0.4.3)", "towncrier (>=21.3)"] -testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)", "packaging (>=20.0)", "pytest (>=4)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.1)", "pytest-mock (>=2)", "pytest-randomly (>=1)", "pytest-timeout (>=1)"] +docs = ["proselint (>=0.13)", "sphinx (>=5.1.1)", "sphinx-argparse (>=0.3.1)", "sphinx-rtd-theme (>=1)", "towncrier (>=21.9)"] +testing = ["coverage (>=6.2)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=21.3)", "pytest (>=7.0.1)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.2)", "pytest-mock (>=3.6.1)", "pytest-randomly (>=3.10.3)", "pytest-timeout (>=2.1)"] [[package]] name = "watchfiles" @@ -1083,7 +1028,7 @@ python-versions = ">=3.7" [[package]] name = "werkzeug" -version = "2.2.1" +version = "2.2.2" description = "The comprehensive WSGI web application library." category = "main" optional = true @@ -1128,19 +1073,6 @@ python-versions = ">=3.7" [package.dependencies] idna = ">=2.0" multidict = ">=4.0" -typing-extensions = {version = ">=3.7.4", markers = "python_version < \"3.8\""} - -[[package]] -name = "zipp" -version = "3.8.1" -description = "Backport of pathlib-compatible object wrapper for zip files" -category = "main" -optional = false -python-versions = ">=3.7" - -[package.extras] -docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)", "jaraco.tidelift (>=1.4)"] -testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.3)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)"] [extras] aiohttp = ["aiohttp"] @@ -1151,8 +1083,8 @@ websockets = ["websockets"] [metadata] lock-version = "1.1" -python-versions = "^3.7.3" -content-hash = "8775c8091ff054a3fb807281e0cfebde4a0409d18970a1001a7a06fad595addf" +python-versions = "^3.8" +content-hash = "3b21339de9113224b61700da359ea53ef866677d19c0bdbad7126e33ceceb856" [metadata.files] aiodns = [ @@ -1256,10 +1188,6 @@ async-timeout = [ {file = "async-timeout-4.0.2.tar.gz", hash = "sha256:2163e1640ddb52b7a8c80d0a67a08587e5d245cc9c553a74a847056bc2976b15"}, {file = "async_timeout-4.0.2-py3-none-any.whl", hash = "sha256:8ca1e4fcf50d07413d66d1a5e416e42cfdf5851c981d679a09851a6853383b3c"}, ] -asynctest = [ - {file = "asynctest-0.13.0-py3-none-any.whl", hash = "sha256:5da6118a7e6d6b54d83a8f7197769d046922a44d2a99c21382f0a6e4fadae676"}, - {file = "asynctest-0.13.0.tar.gz", hash = "sha256:c27862842d15d83e6a34eb0b2866c323880eb3a75e4485b079ea11748fd77fac"}, -] atomicwrites = [] attrs = [ {file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"}, @@ -1455,10 +1383,7 @@ execnet = [ {file = "execnet-1.9.0.tar.gz", hash = "sha256:8f694f3ba9cc92cab508b152dcfe322153975c29bda272e2fd7f3f00f36e47c5"}, ] fastapi = [] -filelock = [ - {file = "filelock-3.7.1-py3-none-any.whl", hash = "sha256:37def7b658813cda163b56fc564cdc75e86d338246458c4c28ae84cabefa2404"}, - {file = "filelock-3.7.1.tar.gz", hash = "sha256:3a0fd85166ad9dbab54c9aec96737b744106dc5f15c0b09a6744a445299fcf04"}, -] +filelock = [] frozenlist = [] h11 = [ {file = "h11-0.12.0-py3-none-any.whl", hash = "sha256:36a3cb8c0a032f56e2da7084577878a035d3b61d104230d4bd49c0c6b555a9c6"}, @@ -1529,7 +1454,6 @@ idna = [ {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, ] -importlib-metadata = [] iniconfig = [ {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, @@ -1694,39 +1618,7 @@ py = [ {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, ] -pycares = [ - {file = "pycares-4.2.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d83f193563b42360528167705b1c7bb91e2a09f990b98e3d6378835b72cd5c96"}, - {file = "pycares-4.2.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b03f69df69f0ab3bfb8dbe54444afddff6ff9389561a08aade96b4f91207a655"}, - {file = "pycares-4.2.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:3b78bdee2f2f1351d5fccc2d1b667aea2d15a55d74d52cb9fd5bea8b5e74c4dc"}, - {file = "pycares-4.2.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f05223de13467bb26f9a1594a1799ce2d08ad8ea241489fecd9d8ed3bbbfc672"}, - {file = "pycares-4.2.1-cp310-cp310-win32.whl", hash = "sha256:1f37f762414680063b4dfec5be809a84f74cd8e203d939aaf3ba9c807a9e7013"}, - {file = "pycares-4.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:1a9506d496efeb809a1b63647cb2f3f33c67fcf62bf80a2359af692fef2c1755"}, - {file = "pycares-4.2.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:2fd53eb5b441c4f6f9c78d7900e05883e9998b34a14b804be4fc4c6f9fea89f3"}, - {file = "pycares-4.2.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:061dd4c80fec73feb150455b159704cd51a122f20d36790033bd6375d4198579"}, - {file = "pycares-4.2.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a521d7f54f3e52ded4d34c306ba05cfe9eb5aaa2e5aaf83c96564b9369495588"}, - {file = "pycares-4.2.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:99e00e397d07a79c9f43e4303e67f4f97bcabd013bda0d8f2d430509b7aef8a0"}, - {file = "pycares-4.2.1-cp36-cp36m-win32.whl", hash = "sha256:d9cd826d8e0c270059450709bff994bfeb072f79d82fd3f11c701690ff65d0e7"}, - {file = "pycares-4.2.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f8e6942965465ca98e212376c4afb9aec501d8129054929744b2f4a487c8c14b"}, - {file = "pycares-4.2.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e75cbd4d3b3d9b02bba6e170846e39893a825e7a5fb1b96728fc6d7b964f8945"}, - {file = "pycares-4.2.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d2e8ec4c8e07c986b70a3cc8f5b297c53b08ac755e5b9797512002a466e2de86"}, - {file = "pycares-4.2.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5333b51ef4ff3e8973b4a1b57cad5ada13e15552445ee3cd74bd77407dec9d44"}, - {file = "pycares-4.2.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2113529004df4894783eaa61e9abc3a680756b6f033d942f2800301ae8c71c29"}, - {file = "pycares-4.2.1-cp37-cp37m-win32.whl", hash = "sha256:e7a95763cdc20cf9ec357066e656ea30b8de6b03de6175cbb50890e22aa01868"}, - {file = "pycares-4.2.1-cp37-cp37m-win_amd64.whl", hash = "sha256:7a901776163a04de5d67c42bd63a287cff9cb05fc041668ad1681fe3daa36445"}, - {file = "pycares-4.2.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:66b5390a4885a578e687d3f2683689c35e1d4573f4d0ecf217431f7bb55c49a0"}, - {file = "pycares-4.2.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:15dd5cf21bc73ad539e8aabf7afe370d1df8af7bc6944cd7298f3bfef0c1a27c"}, - {file = "pycares-4.2.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:4ee625d7571039038bca51ae049b047cbfcfc024b302aae6cc53d5d9aa8648a8"}, - {file = "pycares-4.2.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:396ee487178e9de06ca4122a35a157474db3ce0a0db6038a31c831ebb9863315"}, - {file = "pycares-4.2.1-cp38-cp38-win32.whl", hash = "sha256:e4dc37f732f7110ca6368e0128cbbd0a54f5211515a061b2add64da2ddb8e5ca"}, - {file = "pycares-4.2.1-cp38-cp38-win_amd64.whl", hash = "sha256:3636fccf643c5192c34ee0183c514a2d09419e3a76ca2717cef626638027cb21"}, - {file = "pycares-4.2.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6724573e830ea2345f4bcf0f968af64cc6d491dc2133e9c617f603445dcdfa58"}, - {file = "pycares-4.2.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9dbfcacbde6c21380c412c13d53ea44b257dea3f7b9d80be2c873bb20e21fee"}, - {file = "pycares-4.2.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c8a46839da642b281ac5f56d3c6336528e128b3c41eab9c5330d250f22325e9d"}, - {file = "pycares-4.2.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9b05c2cec644a6c66b55bcf6c24d4dfdaf2f7205b16e5c4ceee31db104fac958"}, - {file = "pycares-4.2.1-cp39-cp39-win32.whl", hash = "sha256:8bd6ed3ad3a5358a635c1acf5d0f46be9afb095772b84427ff22283d2f31db1b"}, - {file = "pycares-4.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:fbd53728d798d07811898e11991e22209229c090eab265a53d12270b95d70d1a"}, - {file = "pycares-4.2.1.tar.gz", hash = "sha256:735b4f75fd0f595c4e9184da18cd87737f46bc81a64ea41f4edce2b6b68d46d2"}, -] +pycares = [] pycparser = [ {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, @@ -1862,32 +1754,6 @@ tomli = [ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] tomlkit = [] -typed-ast = [ - {file = "typed_ast-1.5.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:669dd0c4167f6f2cd9f57041e03c3c2ebf9063d0757dc89f79ba1daa2bfca9d4"}, - {file = "typed_ast-1.5.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:211260621ab1cd7324e0798d6be953d00b74e0428382991adfddb352252f1d62"}, - {file = "typed_ast-1.5.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:267e3f78697a6c00c689c03db4876dd1efdfea2f251a5ad6555e82a26847b4ac"}, - {file = "typed_ast-1.5.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c542eeda69212fa10a7ada75e668876fdec5f856cd3d06829e6aa64ad17c8dfe"}, - {file = "typed_ast-1.5.4-cp310-cp310-win_amd64.whl", hash = "sha256:a9916d2bb8865f973824fb47436fa45e1ebf2efd920f2b9f99342cb7fab93f72"}, - {file = "typed_ast-1.5.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:79b1e0869db7c830ba6a981d58711c88b6677506e648496b1f64ac7d15633aec"}, - {file = "typed_ast-1.5.4-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a94d55d142c9265f4ea46fab70977a1944ecae359ae867397757d836ea5a3f47"}, - {file = "typed_ast-1.5.4-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:183afdf0ec5b1b211724dfef3d2cad2d767cbefac291f24d69b00546c1837fb6"}, - {file = "typed_ast-1.5.4-cp36-cp36m-win_amd64.whl", hash = "sha256:639c5f0b21776605dd6c9dbe592d5228f021404dafd377e2b7ac046b0349b1a1"}, - {file = "typed_ast-1.5.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:cf4afcfac006ece570e32d6fa90ab74a17245b83dfd6655a6f68568098345ff6"}, - {file = "typed_ast-1.5.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed855bbe3eb3715fca349c80174cfcfd699c2f9de574d40527b8429acae23a66"}, - {file = "typed_ast-1.5.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6778e1b2f81dfc7bc58e4b259363b83d2e509a65198e85d5700dfae4c6c8ff1c"}, - {file = "typed_ast-1.5.4-cp37-cp37m-win_amd64.whl", hash = "sha256:0261195c2062caf107831e92a76764c81227dae162c4f75192c0d489faf751a2"}, - {file = "typed_ast-1.5.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2efae9db7a8c05ad5547d522e7dbe62c83d838d3906a3716d1478b6c1d61388d"}, - {file = "typed_ast-1.5.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7d5d014b7daa8b0bf2eaef684295acae12b036d79f54178b92a2b6a56f92278f"}, - {file = "typed_ast-1.5.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:370788a63915e82fd6f212865a596a0fefcbb7d408bbbb13dea723d971ed8bdc"}, - {file = "typed_ast-1.5.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4e964b4ff86550a7a7d56345c7864b18f403f5bd7380edf44a3c1fb4ee7ac6c6"}, - {file = "typed_ast-1.5.4-cp38-cp38-win_amd64.whl", hash = "sha256:683407d92dc953c8a7347119596f0b0e6c55eb98ebebd9b23437501b28dcbb8e"}, - {file = "typed_ast-1.5.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4879da6c9b73443f97e731b617184a596ac1235fe91f98d279a7af36c796da35"}, - {file = "typed_ast-1.5.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3e123d878ba170397916557d31c8f589951e353cc95fb7f24f6bb69adc1a8a97"}, - {file = "typed_ast-1.5.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebd9d7f80ccf7a82ac5f88c521115cc55d84e35bf8b446fcd7836eb6b98929a3"}, - {file = "typed_ast-1.5.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98f80dee3c03455e92796b58b98ff6ca0b2a6f652120c263efdba4d6c5e58f72"}, - {file = "typed_ast-1.5.4-cp39-cp39-win_amd64.whl", hash = "sha256:0fdbcf2fef0ca421a3f5912555804296f0b0960f0418c440f5d6d3abb549f3e1"}, - {file = "typed_ast-1.5.4.tar.gz", hash = "sha256:39e21ceb7388e4bb37f4c679d72707ed46c2fbf2a5609b8b8ebc4b067d977df2"}, -] typing-extensions = [ {file = "typing_extensions-4.3.0-py3-none-any.whl", hash = "sha256:25642c956049920a5aa49edcdd6ab1e06d7e5d467fc00e0506c44ac86fbfca02"}, {file = "typing_extensions-4.3.0.tar.gz", hash = "sha256:e6d2677a32f47fc7eb2795db1dd15c1f34eff616bcaf2cfb5e997f854fa1c4a6"}, @@ -1978,4 +1844,3 @@ wsproto = [ {file = "wsproto-1.1.0.tar.gz", hash = "sha256:a2e56bfd5c7cd83c1369d83b5feccd6d37798b74872866e62616e0ecf111bda8"}, ] yarl = [] -zipp = [] diff --git a/pyproject.toml b/pyproject.toml index bf4d404f..50ecda5b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,7 +22,7 @@ packages = [ include = ["nonebot/py.typed"] [tool.poetry.dependencies] -python = "^3.7.3" +python = "^3.8" yarl = "^1.7.2" loguru = "^0.6.0" pygtrie = "^2.4.1" diff --git a/tests/test_driver.py b/tests/test_driver.py index c74a448a..75507bad 100644 --- a/tests/test_driver.py +++ b/tests/test_driver.py @@ -78,3 +78,27 @@ async def test_reverse_driver(app: App): assert await ws.receive_bytes() == b"pong" await ws.close() + + +@pytest.mark.asyncio +@pytest.mark.parametrize( + "nonebug_init, driver_type", + [ + pytest.param( + {"driver": "nonebot.drivers.fastapi:Driver+nonebot.drivers.aiohttp:Mixin"}, + "fastapi+aiohttp", + id="fastapi+aiohttp", + ), + pytest.param( + {"driver": "~httpx:Driver+~websockets"}, + "block_driver+httpx+websockets", + id="httpx+websockets", + ), + ], + indirect=["nonebug_init"], +) +async def test_combine_driver(app: App, driver_type: str): + import nonebot + + driver = nonebot.get_driver() + assert driver.type == driver_type diff --git a/website/docs/README.md b/website/docs/README.md index 9e864dff..4e0fffc6 100644 --- a/website/docs/README.md +++ b/website/docs/README.md @@ -8,7 +8,7 @@ slug: / NoneBot2 是一个现代、跨平台、可扩展的 Python 聊天机器人框架,它基于 Python 的类型注解和异步特性,能够为你的需求实现提供便捷灵活的支持。 -需要注意的是,NoneBot2 仅支持 **Python 3.7.3 以上版本** +需要注意的是,NoneBot2 仅支持 **Python 3.8 以上版本** ## 特色 diff --git a/website/docs/start/installation.mdx b/website/docs/start/installation.mdx index 87730ed2..6869b8c0 100644 --- a/website/docs/start/installation.mdx +++ b/website/docs/start/installation.mdx @@ -13,7 +13,7 @@ import Asciinema from "@site/src/components/Asciinema"; # 安装 NoneBot2 :::warning 注意 -请确保你的 Python 版本 >= 3.7.3。 +请确保你的 Python 版本 >= 3.8。 ::: :::warning 注意