mirror of
https://github.com/nonebot/nonebot2.git
synced 2025-09-06 20:16:47 +00:00
💥 remove Python 3.7 support (#1148)
This commit is contained in:
@ -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 <y><b>Config</b></y>: {escape_tag(str(config.dict()))}"
|
||||
)
|
||||
|
||||
DriverClass: Type[Driver] = _resolve_combine_expr(config.driver)
|
||||
DriverClass = _resolve_combine_expr(config.driver)
|
||||
_driver = DriverClass(env, config)
|
||||
|
||||
|
||||
|
@ -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}"
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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 <pid>`.
|
||||
@ -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:
|
||||
|
@ -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(
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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):
|
||||
|
@ -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
|
||||
|
@ -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__(
|
||||
|
@ -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__(
|
||||
|
@ -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(
|
||||
"<r><bg #f8bbd0>Error when running RunPreProcessors. "
|
||||
"Running cancelled!</bg #f8bbd0></r>"
|
||||
"<r><bg #f8bbd0>Error when running RunPreProcessors. Running cancelled!</bg #f8bbd0></r>"
|
||||
)
|
||||
|
||||
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:
|
||||
"<r><bg #f8bbd0>Error when checking Matcher.</bg #f8bbd0></r>"
|
||||
)
|
||||
|
||||
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...")
|
||||
|
@ -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
|
||||
|
@ -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]"]
|
||||
"""依赖缓存, 用于存储依赖函数的返回值"""
|
||||
|
@ -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"<m>{escape_tag(logger_name)}</m> | " + message
|
||||
level, f"<m>{escape_tag(logger_name)}</m> | {message}"
|
||||
)
|
||||
|
||||
return log
|
||||
|
Reference in New Issue
Block a user