mirror of
https://github.com/nonebot/nonebot2.git
synced 2024-11-24 00:55:07 +08:00
🚧 process handler call
This commit is contained in:
parent
f7eadb48b5
commit
9d708a6723
@ -12,7 +12,7 @@ from typing import TYPE_CHECKING, Set, Type, Optional
|
||||
from nonebot.log import logger
|
||||
from nonebot.rule import TrieRule
|
||||
from nonebot.utils import escape_tag
|
||||
from nonebot.matcher import Matcher, matchers
|
||||
from nonebot.processor import Matcher, matchers
|
||||
from nonebot.exception import NoLogException, StopPropagation, IgnoredException
|
||||
from nonebot.typing import (T_State, T_RunPreProcessor, T_RunPostProcessor,
|
||||
T_EventPreProcessor, T_EventPostProcessor)
|
||||
|
@ -5,10 +5,9 @@ from types import ModuleType
|
||||
from typing import (TYPE_CHECKING, Any, Set, Dict, List, Type, Tuple, Union,
|
||||
Optional)
|
||||
|
||||
from nonebot.handler import Handler
|
||||
from nonebot.matcher import Matcher
|
||||
from .manager import _current_plugin
|
||||
from nonebot.permission import Permission
|
||||
from nonebot.processor import Handler, Matcher
|
||||
from nonebot.typing import T_State, T_Handler, T_RuleChecker, T_StateFactory
|
||||
from nonebot.rule import (Rule, ArgumentParser, regex, command, keyword,
|
||||
endswith, startswith, shell_command)
|
||||
|
@ -1,10 +1,9 @@
|
||||
import re
|
||||
from typing import Set, List, Type, Tuple, Union, Optional
|
||||
|
||||
from nonebot.handler import Handler
|
||||
from nonebot.matcher import Matcher
|
||||
from nonebot.permission import Permission
|
||||
from nonebot.rule import Rule, ArgumentParser
|
||||
from nonebot.processor import Handler, Matcher
|
||||
from nonebot.typing import T_State, T_Handler, T_RuleChecker, T_StateFactory
|
||||
|
||||
|
||||
|
@ -3,7 +3,7 @@ from dataclasses import field, dataclass
|
||||
from typing import Set, Dict, Type, Optional
|
||||
|
||||
from .export import Export
|
||||
from nonebot.matcher import Matcher
|
||||
from nonebot.processor import Matcher
|
||||
|
||||
plugins: Dict[str, "Plugin"] = {}
|
||||
"""
|
||||
|
@ -1,7 +1,7 @@
|
||||
from typing import Dict, Optional
|
||||
|
||||
from nonebot.typing import T_State
|
||||
from nonebot.matcher import Matcher
|
||||
from nonebot.processor import Matcher
|
||||
from nonebot.adapters import Bot, Event
|
||||
from nonebot.message import (IgnoredException, run_preprocessor,
|
||||
run_postprocessor)
|
||||
|
@ -1,14 +1,18 @@
|
||||
import inspect
|
||||
from typing import Any, Callable, Optional
|
||||
from itertools import chain
|
||||
from typing import Any, Dict, List, Tuple, Callable, Optional, cast
|
||||
|
||||
from .models import Dependent
|
||||
from .models import Depends as Depends
|
||||
from nonebot.typing import T_State
|
||||
from nonebot.adapters import Bot, Event
|
||||
from .utils import get_typed_signature, generic_check_issubclass
|
||||
from .models import Depends as DependsClass
|
||||
from nonebot.utils import run_sync, is_coroutine_callable
|
||||
from .utils import (generic_get_types, get_typed_signature,
|
||||
generic_check_issubclass)
|
||||
|
||||
|
||||
def get_param_sub_dependent(*, param: inspect.Parameter) -> Dependent:
|
||||
depends: Depends = param.default
|
||||
depends: DependsClass = param.default
|
||||
if depends.dependency:
|
||||
dependency = depends.dependency
|
||||
else:
|
||||
@ -20,7 +24,7 @@ def get_param_sub_dependent(*, param: inspect.Parameter) -> Dependent:
|
||||
)
|
||||
|
||||
|
||||
def get_parameterless_sub_dependant(*, depends: Depends) -> Dependent:
|
||||
def get_parameterless_sub_dependant(*, depends: DependsClass) -> Dependent:
|
||||
assert callable(
|
||||
depends.dependency
|
||||
), "A parameter-less dependency must have a callable dependency"
|
||||
@ -29,7 +33,7 @@ def get_parameterless_sub_dependant(*, depends: Depends) -> Dependent:
|
||||
|
||||
def get_sub_dependant(
|
||||
*,
|
||||
depends: Depends,
|
||||
depends: DependsClass,
|
||||
dependency: Callable[..., Any],
|
||||
name: Optional[str] = None,
|
||||
) -> Dependent:
|
||||
@ -49,29 +53,124 @@ def get_dependent(*,
|
||||
params = signature.parameters
|
||||
dependent = Dependent(func=func, name=name, use_cache=use_cache)
|
||||
for param_name, param in params.items():
|
||||
if isinstance(param.default, Depends):
|
||||
if isinstance(param.default, DependsClass):
|
||||
sub_dependent = get_param_sub_dependent(param=param)
|
||||
dependent.dependencies.append(sub_dependent)
|
||||
continue
|
||||
|
||||
if generic_check_issubclass(param.annotation, Bot):
|
||||
if dependent.bot_param_name is not None:
|
||||
raise ValueError(f"{func} has more than one Bot parameter: "
|
||||
f"{dependent.bot_param_name} / {param_name}")
|
||||
dependent.bot_param_name = param_name
|
||||
continue
|
||||
dependent.bot_param_type = generic_get_types(param.annotation)
|
||||
elif generic_check_issubclass(param.annotation, Event):
|
||||
if dependent.event_param_name is not None:
|
||||
raise ValueError(f"{func} has more than one Event parameter: "
|
||||
f"{dependent.event_param_name} / {param_name}")
|
||||
dependent.event_param_name = param_name
|
||||
continue
|
||||
dependent.event_param_type = generic_get_types(param.annotation)
|
||||
elif generic_check_issubclass(param.annotation, dict):
|
||||
if dependent.state_param_name is not None:
|
||||
raise ValueError(f"{func} has more than one State parameter: "
|
||||
f"{dependent.state_param_name} / {param_name}")
|
||||
dependent.state_param_name = param_name
|
||||
continue
|
||||
elif generic_check_issubclass(param.annotation, Matcher):
|
||||
if dependent.matcher_param_name is not None:
|
||||
raise ValueError(
|
||||
f"{func} has more than one Matcher parameter: "
|
||||
f"{dependent.matcher_param_name} / {param_name}")
|
||||
dependent.matcher_param_name = param_name
|
||||
continue
|
||||
|
||||
raise ValueError(
|
||||
f"Unknown parameter {param_name} with type {param.annotation}")
|
||||
else:
|
||||
raise ValueError(
|
||||
f"Unknown parameter {param_name} with type {param.annotation}")
|
||||
|
||||
return dependent
|
||||
|
||||
|
||||
async def solve_dependencies(
|
||||
*,
|
||||
dependent: Dependent,
|
||||
bot: Bot,
|
||||
event: Event,
|
||||
state: T_State,
|
||||
matcher: "Matcher",
|
||||
sub_dependents: Optional[List[Dependent]] = None,
|
||||
dependency_overrides_provider: Optional[Any] = None,
|
||||
dependency_cache: Optional[Dict[Tuple[Callable[..., Any]], Any]] = None,
|
||||
) -> Tuple[Dict[str, Any], Dict[Tuple[Callable[..., Any]], Any]]:
|
||||
values: Dict[str, Any] = {}
|
||||
dependency_cache = dependency_cache or {}
|
||||
|
||||
# solve sub dependencies
|
||||
sub_dependant: Dependent
|
||||
for sub_dependant in chain(sub_dependents or tuple(),
|
||||
dependent.dependencies):
|
||||
sub_dependant.func = cast(Callable[..., Any], sub_dependant.func)
|
||||
sub_dependant.cache_key = cast(Tuple[Callable[..., Any]],
|
||||
sub_dependant.cache_key)
|
||||
func = sub_dependant.func
|
||||
|
||||
# dependency overrides
|
||||
use_sub_dependant = sub_dependant
|
||||
if (dependency_overrides_provider and
|
||||
hasattr(dependency_overrides_provider, "dependency_overrides")):
|
||||
original_call = sub_dependant.func
|
||||
func = getattr(dependency_overrides_provider,
|
||||
"dependency_overrides",
|
||||
{}).get(original_call, original_call)
|
||||
use_sub_dependant = get_dependent(
|
||||
func=func,
|
||||
name=sub_dependant.name,
|
||||
)
|
||||
|
||||
# solve sub dependency with current cache
|
||||
solved_result = await solve_dependencies(
|
||||
dependent=use_sub_dependant,
|
||||
bot=bot,
|
||||
event=event,
|
||||
state=state,
|
||||
matcher=matcher,
|
||||
dependency_overrides_provider=dependency_overrides_provider,
|
||||
dependency_cache=dependency_cache,
|
||||
)
|
||||
sub_values, sub_dependency_cache = solved_result
|
||||
# update cache?
|
||||
dependency_cache.update(sub_dependency_cache)
|
||||
|
||||
# run dependency function
|
||||
if sub_dependant.use_cache and sub_dependant.cache_key in dependency_cache:
|
||||
solved = dependency_cache[sub_dependant.cache_key]
|
||||
elif is_coroutine_callable(func):
|
||||
solved = await func(**sub_values)
|
||||
else:
|
||||
solved = await run_sync(func)(**sub_values)
|
||||
|
||||
# parameter dependency
|
||||
if sub_dependant.name is not None:
|
||||
values[sub_dependant.name] = solved
|
||||
# save current dependency to cache
|
||||
if sub_dependant.cache_key not in dependency_cache:
|
||||
dependency_cache[sub_dependant.cache_key] = solved
|
||||
|
||||
# usual dependency
|
||||
if dependent.bot_param_name is not None:
|
||||
values[dependent.bot_param_name] = bot
|
||||
if dependent.event_param_name is not None:
|
||||
values[dependent.event_param_name] = event
|
||||
if dependent.state_param_name is not None:
|
||||
values[dependent.state_param_name] = state
|
||||
if dependent.matcher_param_name is not None:
|
||||
values[dependent.matcher_param_name] = matcher
|
||||
return values, dependency_cache
|
||||
|
||||
|
||||
def Depends(dependency: Optional[Callable[..., Any]] = None,
|
||||
*,
|
||||
use_cache: bool = True) -> Any:
|
||||
return DependsClass(dependency=dependency, use_cache=use_cache)
|
||||
|
||||
|
||||
from .handler import Handler as Handler
|
||||
from .matcher import Matcher as Matcher
|
||||
from .matcher import matchers as matchers
|
||||
|
@ -4,12 +4,14 @@
|
||||
|
||||
该模块实现事件处理函数的封装,以实现动态参数等功能。
|
||||
"""
|
||||
from typing import TYPE_CHECKING, List, Optional
|
||||
|
||||
from .models import Depends
|
||||
from nonebot.utils import get_name
|
||||
import asyncio
|
||||
from typing import TYPE_CHECKING, Any, Dict, List, Tuple, Callable, Optional
|
||||
|
||||
from .models import Depends, Dependent
|
||||
from nonebot.utils import get_name, run_sync
|
||||
from nonebot.typing import T_State, T_Handler
|
||||
from . import get_dependent, get_parameterless_sub_dependant
|
||||
from . import get_dependent, solve_dependencies, get_parameterless_sub_dependant
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .matcher import Matcher
|
||||
@ -23,7 +25,8 @@ class Handler:
|
||||
func: T_Handler,
|
||||
*,
|
||||
name: Optional[str] = None,
|
||||
dependencies: Optional[List[Depends]] = None):
|
||||
dependencies: Optional[List[Depends]] = None,
|
||||
dependency_overrides_provider: Optional[Any] = None):
|
||||
"""装饰事件处理函数以便根据动态参数运行"""
|
||||
self.func: T_Handler = func
|
||||
"""
|
||||
@ -33,11 +36,57 @@ class Handler:
|
||||
self.name = get_name(func) if name is None else name
|
||||
|
||||
self.dependencies = dependencies or []
|
||||
self.sub_dependents: Dict[Tuple[Callable[..., Any]], Dependent] = {}
|
||||
if dependencies:
|
||||
for depends in dependencies:
|
||||
if not depends.dependency:
|
||||
raise ValueError(f"{depends} has no dependency")
|
||||
if (depends.dependency,) in self.sub_dependents:
|
||||
raise ValueError(f"{depends} is already in dependencies")
|
||||
sub_dependant = get_parameterless_sub_dependant(depends=depends)
|
||||
self.sub_dependents[(depends.dependency,)] = sub_dependant
|
||||
self.dependency_overrides_provider = dependency_overrides_provider
|
||||
self.dependent = get_dependent(func=func)
|
||||
for depends in self.dependencies[::-1]:
|
||||
self.dependent.dependencies.insert(
|
||||
0, get_parameterless_sub_dependant(depends=depends))
|
||||
|
||||
def __call__(self, bot: Bot, event: Event, state: T_State,
|
||||
matcher: "Matcher"):
|
||||
...
|
||||
async def __call__(self, matcher: "Matcher", bot: Bot, event: Event,
|
||||
state: T_State):
|
||||
values, _ = await solve_dependencies(
|
||||
dependent=self.dependent,
|
||||
bot=bot,
|
||||
event=event,
|
||||
state=state,
|
||||
matcher=matcher,
|
||||
sub_dependents=[
|
||||
self.sub_dependents[(dependency.dependency,)] # type: ignore
|
||||
for dependency in self.dependencies
|
||||
],
|
||||
dependency_overrides_provider=self.dependency_overrides_provider)
|
||||
|
||||
if asyncio.iscoroutinefunction(self.func):
|
||||
await self.func(**values)
|
||||
else:
|
||||
await run_sync(self.func)(**values)
|
||||
|
||||
def cache_dependent(self, dependency: Depends):
|
||||
if not dependency.dependency:
|
||||
raise ValueError(f"{dependency} has no dependency")
|
||||
if (dependency.dependency,) in self.sub_dependents:
|
||||
raise ValueError(f"{dependency} is already in dependencies")
|
||||
sub_dependant = get_parameterless_sub_dependant(depends=dependency)
|
||||
self.sub_dependents[(dependency.dependency,)] = sub_dependant
|
||||
|
||||
def prepend_dependency(self, dependency: Depends):
|
||||
self.cache_dependent(dependency)
|
||||
self.dependencies.insert(0, dependency)
|
||||
|
||||
def append_dependency(self, dependency: Depends):
|
||||
self.cache_dependent(dependency)
|
||||
self.dependencies.append(dependency)
|
||||
|
||||
def remove_dependency(self, dependency: Depends):
|
||||
if not dependency.dependency:
|
||||
raise ValueError(f"{dependency} has no dependency")
|
||||
if (dependency.dependency,) in self.sub_dependents:
|
||||
del self.sub_dependents[(dependency.dependency,)]
|
||||
if dependency in self.dependencies:
|
||||
self.dependencies.remove(dependency)
|
||||
|
@ -5,7 +5,6 @@
|
||||
该模块实现事件响应器的创建与运行,并提供一些快捷方法来帮助用户更好的与机器人进行对话 。
|
||||
"""
|
||||
|
||||
from functools import wraps
|
||||
from types import ModuleType
|
||||
from datetime import datetime
|
||||
from contextvars import ContextVar
|
||||
@ -13,8 +12,10 @@ from collections import defaultdict
|
||||
from typing import (TYPE_CHECKING, Any, Dict, List, Type, Union, Callable,
|
||||
NoReturn, Optional)
|
||||
|
||||
from .models import Depends
|
||||
from .handler import Handler
|
||||
from nonebot.rule import Rule
|
||||
from nonebot import get_driver
|
||||
from nonebot.log import logger
|
||||
from nonebot.adapters import MessageTemplate
|
||||
from nonebot.permission import USER, Permission
|
||||
@ -228,8 +229,8 @@ class Matcher(metaclass=MatcherMeta):
|
||||
"permission":
|
||||
permission or Permission(),
|
||||
"handlers": [
|
||||
handler
|
||||
if isinstance(handler, Handler) else Handler(handler)
|
||||
handler if isinstance(handler, Handler) else Handler(
|
||||
handler, dependency_overrides_provider=get_driver())
|
||||
for handler in handlers
|
||||
] if handlers else [],
|
||||
"temp":
|
||||
@ -343,8 +344,12 @@ class Matcher(metaclass=MatcherMeta):
|
||||
return func
|
||||
|
||||
@classmethod
|
||||
def append_handler(cls, handler: T_Handler) -> Handler:
|
||||
handler_ = Handler(handler)
|
||||
def append_handler(cls,
|
||||
handler: T_Handler,
|
||||
dependencies: Optional[List[Depends]] = None) -> Handler:
|
||||
handler_ = Handler(handler,
|
||||
dependencies=dependencies,
|
||||
dependency_overrides_provider=get_driver())
|
||||
cls.handlers.append(handler_)
|
||||
return handler_
|
||||
|
||||
@ -378,22 +383,19 @@ class Matcher(metaclass=MatcherMeta):
|
||||
* 无
|
||||
"""
|
||||
|
||||
async def _receive(bot: "Bot", event: "Event") -> NoReturn:
|
||||
raise PausedException
|
||||
|
||||
if cls.handlers:
|
||||
# 已有前置handlers则接受一条新的消息,否则视为接收初始消息
|
||||
receive_handler = cls.append_handler(_receive)
|
||||
else:
|
||||
receive_handler = None
|
||||
|
||||
def _decorator(func: T_Handler) -> T_Handler:
|
||||
if not cls.handlers or cls.handlers[-1] is not func:
|
||||
func_handler = cls.append_handler(func)
|
||||
if receive_handler:
|
||||
receive_handler.update_signature(
|
||||
bot=func_handler.bot_type,
|
||||
event=func_handler.event_type)
|
||||
|
||||
async def _receive() -> NoReturn:
|
||||
func_handler.remove_dependency(depend)
|
||||
raise PausedException
|
||||
|
||||
depend = Depends(_receive)
|
||||
if cls.handlers and cls.handlers[-1].func is func:
|
||||
func_handler = cls.handlers[-1]
|
||||
func_handler.prepend_dependency(depend)
|
||||
else:
|
||||
func_handler = cls.append_handler(
|
||||
func, dependencies=[depend] if cls.handlers else [])
|
||||
|
||||
return func
|
||||
|
||||
@ -419,54 +421,42 @@ class Matcher(metaclass=MatcherMeta):
|
||||
* ``args_parser: Optional[T_ArgsParser]``: 可选参数解析函数,空则使用默认解析函数
|
||||
"""
|
||||
|
||||
async def _key_getter(bot: "Bot", event: "Event", state: T_State):
|
||||
state["_current_key"] = key
|
||||
if key not in state:
|
||||
if prompt is not None:
|
||||
if isinstance(prompt, MessageTemplate):
|
||||
_prompt = prompt.format(**state)
|
||||
else:
|
||||
_prompt = prompt
|
||||
await bot.send(event=event, message=_prompt)
|
||||
raise PausedException
|
||||
else:
|
||||
state["_skip_key"] = True
|
||||
|
||||
async def _key_parser(bot: "Bot", event: "Event", state: T_State):
|
||||
if key in state and state.get("_skip_key"):
|
||||
del state["_skip_key"]
|
||||
return
|
||||
parser = args_parser or cls._default_parser
|
||||
if parser:
|
||||
# parser = cast(T_ArgsParser["Bot", "Event"], parser)
|
||||
await parser(bot, event, state)
|
||||
else:
|
||||
state[state["_current_key"]] = str(event.get_message())
|
||||
|
||||
getter_handler = cls.append_handler(_key_getter)
|
||||
parser_handler = cls.append_handler(_key_parser)
|
||||
|
||||
def _decorator(func: T_Handler) -> T_Handler:
|
||||
if not hasattr(cls.handlers[-1].func, "__wrapped__"):
|
||||
parser = cls.handlers.pop()
|
||||
func_handler = Handler(func)
|
||||
|
||||
@wraps(func)
|
||||
async def wrapper(bot: "Bot", event: "Event", state: T_State,
|
||||
matcher: Matcher):
|
||||
await parser(matcher, bot, event, state)
|
||||
await func_handler(matcher, bot, event, state)
|
||||
if "_current_key" in state:
|
||||
del state["_current_key"]
|
||||
async def _key_getter(bot: "Bot", event: "Event", state: T_State):
|
||||
func_handler.remove_dependency(get_depend)
|
||||
state["_current_key"] = key
|
||||
if key not in state:
|
||||
if prompt is not None:
|
||||
if isinstance(prompt, MessageTemplate):
|
||||
_prompt = prompt.format(**state)
|
||||
else:
|
||||
_prompt = prompt
|
||||
await bot.send(event=event, message=_prompt)
|
||||
raise PausedException
|
||||
else:
|
||||
state["_skip_key"] = True
|
||||
|
||||
wrapper_handler = cls.append_handler(wrapper)
|
||||
async def _key_parser(bot: "Bot", event: "Event", state: T_State):
|
||||
if key in state and state.get("_skip_key"):
|
||||
del state["_skip_key"]
|
||||
return
|
||||
parser = args_parser or cls._default_parser
|
||||
if parser:
|
||||
await parser(bot, event, state)
|
||||
else:
|
||||
state[state["_current_key"]] = str(event.get_message())
|
||||
|
||||
getter_handler.update_signature(
|
||||
bot=wrapper_handler.bot_type,
|
||||
event=wrapper_handler.event_type)
|
||||
parser_handler.update_signature(
|
||||
bot=wrapper_handler.bot_type,
|
||||
event=wrapper_handler.event_type)
|
||||
get_depend = Depends(_key_getter)
|
||||
parser_depend = Depends(_key_parser)
|
||||
|
||||
if cls.handlers and cls.handlers[-1].func is func:
|
||||
func_handler = cls.handlers[-1]
|
||||
func_handler.prepend_dependency(parser_depend)
|
||||
func_handler.prepend_dependency(get_depend)
|
||||
else:
|
||||
func_handler = cls.append_handler(
|
||||
func, dependencies=[get_depend, parser_depend])
|
||||
|
||||
return func
|
||||
|
||||
|
@ -1,7 +1,10 @@
|
||||
from typing import Any, List, Callable, Optional
|
||||
from typing import TYPE_CHECKING, Any, List, Tuple, Callable, Optional
|
||||
|
||||
from nonebot.utils import get_name
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from nonebot.adapters import Bot, Event
|
||||
|
||||
|
||||
class Depends:
|
||||
|
||||
@ -25,7 +28,9 @@ class Dependent:
|
||||
func: Optional[Callable[..., Any]] = None,
|
||||
name: Optional[str] = None,
|
||||
bot_param_name: Optional[str] = None,
|
||||
bot_param_type: Optional[Tuple["Bot", ...]] = None,
|
||||
event_param_name: Optional[str] = None,
|
||||
event_param_type: Optional[Tuple["Event", ...]] = None,
|
||||
state_param_name: Optional[str] = None,
|
||||
matcher_param_name: Optional[str] = None,
|
||||
dependencies: Optional[List["Dependent"]] = None,
|
||||
@ -33,7 +38,9 @@ class Dependent:
|
||||
self.func = func
|
||||
self.name = name
|
||||
self.bot_param_name = bot_param_name
|
||||
self.bot_param_type = bot_param_type
|
||||
self.event_param_name = event_param_name
|
||||
self.event_param_type = event_param_type
|
||||
self.state_param_name = state_param_name
|
||||
self.matcher_param_name = matcher_param_name
|
||||
self.dependencies = dependencies or []
|
||||
|
@ -1,7 +1,7 @@
|
||||
import inspect
|
||||
from typing import Any, Dict, Type, Tuple, Union, Callable
|
||||
|
||||
from pydantic.typing import (ForwardRef, GenericAlias, get_args, get_origin,
|
||||
from pydantic.typing import (ForwardRef, get_args, get_origin,
|
||||
evaluate_forwardref)
|
||||
|
||||
|
||||
@ -41,3 +41,9 @@ def generic_check_issubclass(
|
||||
return False
|
||||
return True
|
||||
raise
|
||||
|
||||
|
||||
def generic_get_types(cls: Any) -> Tuple[Type[Any], ...]:
|
||||
if get_origin(cls) is Union:
|
||||
return get_args(cls)
|
||||
return (cls,)
|
||||
|
@ -22,7 +22,7 @@ from typing import (TYPE_CHECKING, Any, Dict, Union, TypeVar, Callable,
|
||||
NoReturn, Optional, Awaitable)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from nonebot.matcher import Matcher
|
||||
from nonebot.processor import Matcher
|
||||
from nonebot.adapters import Bot, Event
|
||||
from nonebot.permission import Permission
|
||||
|
||||
|
@ -4,11 +4,15 @@ import asyncio
|
||||
import inspect
|
||||
import dataclasses
|
||||
from functools import wraps, partial
|
||||
from typing import Any, Callable, Optional, Awaitable
|
||||
from typing_extensions import ParamSpec
|
||||
from typing import Any, TypeVar, Callable, Optional, Awaitable
|
||||
|
||||
from nonebot.log import logger
|
||||
from nonebot.typing import overrides
|
||||
|
||||
P = ParamSpec("P")
|
||||
R = TypeVar("R")
|
||||
|
||||
|
||||
def escape_tag(s: str) -> str:
|
||||
"""
|
||||
@ -27,7 +31,16 @@ def escape_tag(s: str) -> str:
|
||||
return re.sub(r"</?((?:[fb]g\s)?[^<>\s]*)>", r"\\\g<0>", s)
|
||||
|
||||
|
||||
def run_sync(func: Callable[..., Any]) -> Callable[..., Awaitable[Any]]:
|
||||
def is_coroutine_callable(func: Callable[..., Any]) -> bool:
|
||||
if inspect.isroutine(func):
|
||||
return inspect.iscoroutinefunction(func)
|
||||
if inspect.isclass(func):
|
||||
return False
|
||||
func_ = getattr(func, "__call__", None)
|
||||
return inspect.iscoroutinefunction(func_)
|
||||
|
||||
|
||||
def run_sync(func: Callable[P, R]) -> Callable[P, Awaitable[R]]:
|
||||
"""
|
||||
:说明:
|
||||
|
||||
@ -35,15 +48,15 @@ def run_sync(func: Callable[..., Any]) -> Callable[..., Awaitable[Any]]:
|
||||
|
||||
:参数:
|
||||
|
||||
* ``func: Callable[..., Any]``: 被装饰的同步函数
|
||||
* ``func: Callable[P, R]``: 被装饰的同步函数
|
||||
|
||||
:返回:
|
||||
|
||||
- ``Callable[..., Awaitable[Any]]``
|
||||
- ``Callable[P, Awaitable[R]]``
|
||||
"""
|
||||
|
||||
@wraps(func)
|
||||
async def _wrapper(*args: Any, **kwargs: Any) -> Any:
|
||||
async def _wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
|
||||
loop = asyncio.get_running_loop()
|
||||
pfunc = partial(func, *args, **kwargs)
|
||||
result = await loop.run_in_executor(None, pfunc)
|
||||
|
2
poetry.lock
generated
2
poetry.lock
generated
@ -1099,7 +1099,7 @@ quart = ["Quart"]
|
||||
[metadata]
|
||||
lock-version = "1.1"
|
||||
python-versions = "^3.7.3"
|
||||
content-hash = "51f4f0ce5ced234a65cae790c4f57486e42d7120972657a3f51e733cb4e7c639"
|
||||
content-hash = "81edd95f4289e55d7cfe632664c930846bde723cb8fa0359fa1e18474853f454"
|
||||
|
||||
[metadata.files]
|
||||
aiocache = [
|
||||
|
@ -28,6 +28,7 @@ pygtrie = "^2.4.1"
|
||||
tomlkit = "^0.7.0"
|
||||
fastapi = "^0.70.0"
|
||||
websockets = ">=9.1"
|
||||
typing-extensions = "^3.10.0"
|
||||
Quart = { version = "^0.15.0", optional = true }
|
||||
httpx = { version = ">=0.20.0, <1.0.0", extras = ["http2"] }
|
||||
pydantic = { version = "~1.8.0", extras = ["dotenv"] }
|
||||
|
@ -1,7 +1,7 @@
|
||||
from nonebot.typing import T_State
|
||||
from nonebot.matcher import Matcher
|
||||
from nonebot.processor import Matcher
|
||||
from nonebot.adapters import Bot, Event
|
||||
from nonebot.message import event_preprocessor, run_preprocessor
|
||||
from nonebot.message import run_preprocessor, event_preprocessor
|
||||
|
||||
|
||||
@event_preprocessor
|
||||
|
Loading…
Reference in New Issue
Block a user