diff --git a/nonebot/dependencies/__init__.py b/nonebot/dependencies/__init__.py index 05786d4b..54853dee 100644 --- a/nonebot/dependencies/__init__.py +++ b/nonebot/dependencies/__init__.py @@ -58,6 +58,15 @@ class Dependent(Generic[R]): self.parameterless = parameterless or [] self.allow_types = allow_types or [] + def __repr__(self) -> str: + return ( + f"" + ) + + def __str__(self) -> str: + return self.__repr__() + async def __call__(self, **kwargs: Any) -> R: values = await self.solve(**kwargs) diff --git a/nonebot/matcher.py b/nonebot/matcher.py index acdec706..a90ac63b 100644 --- a/nonebot/matcher.py +++ b/nonebot/matcher.py @@ -172,11 +172,6 @@ class Matcher(metaclass=MatcherMeta): :说明: 事件响应器默认状态 """ - _default_parser: Optional[Dependent[None]] = None - """ - :类型: ``Optional[Dependent]`` - :说明: 事件响应器默认参数解析函数 - """ _default_type_updater: Optional[Dependent[str]] = None """ :类型: ``Optional[Dependent]`` @@ -441,28 +436,27 @@ class Matcher(metaclass=MatcherMeta): * ``parameterless: Optional[List[Any]]``: 非参数类型依赖列表 """ + _id = id or "" + async def _receive(event: Event, matcher: "Matcher") -> Union[None, NoReturn]: - if matcher.get_receive(id): + if matcher.get_receive(_id): return - if matcher.get_target() == RECEIVE_KEY.format(id=id or ""): - matcher.set_receive(id, event) + if matcher.get_target() == RECEIVE_KEY.format(id=_id): + matcher.set_receive(_id, event) return - matcher.set_target(RECEIVE_KEY.format(id=id or "")) + matcher.set_target(RECEIVE_KEY.format(id=_id)) raise RejectedException - parameterless = [params.Depends(_receive), *(parameterless or [])] + _parameterless = [params.Depends(_receive), *(parameterless or [])] def _decorator(func: T_Handler) -> T_Handler: if cls.handlers and cls.handlers[-1].call is func: func_handler = cls.handlers[-1] - for depend in reversed(parameterless): + for depend in reversed(_parameterless): func_handler.prepend_parameterless(depend) else: - cls.append_handler( - func, - parameterless=parameterless if cls.handlers else parameterless, - ) + cls.append_handler(func, parameterless=_parameterless) return func @@ -558,15 +552,8 @@ class Matcher(metaclass=MatcherMeta): * ``message: Union[str, Message, MessageSegment]``: 消息内容 * ``**kwargs``: 其他传递给 ``bot.send`` 的参数,请参考对应 adapter 的 bot 对象 api """ - bot = current_bot.get() - event = current_event.get() - state = current_state.get() - if isinstance(message, MessageTemplate): - _message = message.format(**state) - else: - _message = message - if _message is not None: - await bot.send(event=event, message=_message, **kwargs) + if message is not None: + await cls.send(message, **kwargs) raise FinishedException @classmethod @@ -585,15 +572,8 @@ class Matcher(metaclass=MatcherMeta): * ``prompt: Union[str, Message, MessageSegment]``: 消息内容 * ``**kwargs``: 其他传递给 ``bot.send`` 的参数,请参考对应 adapter 的 bot 对象 api """ - bot = current_bot.get() - event = current_event.get() - state = current_state.get() - if isinstance(prompt, MessageTemplate): - _prompt = prompt.format(**state) - else: - _prompt = prompt - if _prompt is not None: - await bot.send(event=event, message=_prompt, **kwargs) + if prompt is not None: + await cls.send(prompt, **kwargs) raise PausedException @classmethod @@ -610,27 +590,20 @@ class Matcher(metaclass=MatcherMeta): * ``prompt: Union[str, Message, MessageSegment]``: 消息内容 * ``**kwargs``: 其他传递给 ``bot.send`` 的参数,请参考对应 adapter 的 bot 对象 api """ - bot = current_bot.get() - event = current_event.get() - state = current_state.get() - if isinstance(prompt, MessageTemplate): - _prompt = prompt.format(**state) - else: - _prompt = prompt - if _prompt is not None: - await bot.send(event=event, message=_prompt, **kwargs) + if prompt is not None: + await cls.send(prompt, **kwargs) raise RejectedException - def get_receive(self, id: Optional[str], default: T = None) -> Union[Event, T]: - if id is None: - return self.state.get(LAST_RECEIVE_KEY, default) + def get_receive(self, id: str, default: T = None) -> Union[Event, T]: return self.state.get(RECEIVE_KEY.format(id=id), default) - def set_receive(self, id: Optional[str], event: Event) -> None: - if id is not None: - self.state[RECEIVE_KEY.format(id=id)] = event + def set_receive(self, id: str, event: Event) -> None: + 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]: + return self.state.get(LAST_RECEIVE_KEY, default) + def get_arg(self, key: str, default: T = None) -> Union[Event, T]: return self.state.get(ARG_KEY.format(key=key), default) diff --git a/nonebot/params.py b/nonebot/params.py index bab4ed7f..c067fb13 100644 --- a/nonebot/params.py +++ b/nonebot/params.py @@ -318,16 +318,16 @@ class MatcherParam(Param): return matcher -def Received(id: str, default: Any = None) -> Any: +def Received(id: Optional[str] = None, default: Any = None) -> Any: def _received(matcher: "Matcher"): - return matcher.get_receive(id, default) + return matcher.get_receive(id or "", default) return Depends(_received, use_cache=False) def LastReceived(default: Any = None) -> Any: def _last_received(matcher: "Matcher") -> Any: - return matcher.get_receive(None, default) + return matcher.get_last_receive(default) return Depends(_last_received, use_cache=False) diff --git a/tests/.env.test b/tests/.env.test index 11b8445f..41ae0e10 100644 --- a/tests/.env.test +++ b/tests/.env.test @@ -1,2 +1,3 @@ +DEBUG=true NICKNAME=["test"] CONFIG_FROM_ENV= diff --git a/tests/plugins/matcher.py b/tests/plugins/matcher.py new file mode 100644 index 00000000..a15c423a --- /dev/null +++ b/tests/plugins/matcher.py @@ -0,0 +1,35 @@ +from nonebot import on_message +from nonebot.adapters import Event +from nonebot.params import ArgStr, Received, LastReceived + +test_handle = on_message() + + +@test_handle.handle() +async def handle(): + await test_handle.finish("send", at_sender=True) + + +test_got = on_message() + + +@test_got.got("key1", "prompt key1") +@test_got.got("key2", "prompt key2") +async def got(key1: str = ArgStr(), key2: str = ArgStr()): + assert key1 == "text" + assert key2 == "text" + await test_got.reject("reject", at_sender=True) + + +test_receive = on_message() + + +@test_receive.receive() +@test_receive.receive("receive") +async def receive( + x: Event = Received("receive"), y: Event = LastReceived(), z: Event = Received() +): + assert str(x.get_message()) == "text" + assert str(z.get_message()) == "text" + assert x is y + await test_receive.pause("pause", at_sender=True) diff --git a/tests/test_matcher.py b/tests/test_matcher.py new file mode 100644 index 00000000..df2488c0 --- /dev/null +++ b/tests/test_matcher.py @@ -0,0 +1,41 @@ +from typing import TYPE_CHECKING, Set + +import pytest +from nonebug import App + +from utils import load_plugin, make_fake_event, make_fake_message + + +@pytest.mark.asyncio +async def test_matcher(app: App, load_plugin): + from plugins.matcher import test_got, test_handle, test_receive + + message = make_fake_message()("text") + event = make_fake_event(_message=message)() + + assert len(test_handle.handlers) == 1 + async with app.test_matcher(test_handle) as ctx: + bot = ctx.create_bot() + ctx.receive_event(bot, event) + ctx.should_call_send(event, "send", "result", at_sender=True) + ctx.should_finished() + + assert len(test_got.handlers) == 1 + async with app.test_matcher(test_got) as ctx: + bot = ctx.create_bot() + ctx.receive_event(bot, event) + ctx.should_call_send(event, "prompt key1", "result1") + ctx.receive_event(bot, event) + ctx.should_call_send(event, "prompt key2", "result2") + ctx.receive_event(bot, event) + ctx.should_call_send(event, "reject", "result3", at_sender=True) + ctx.should_rejected() + + assert len(test_receive.handlers) == 1 + async with app.test_matcher(test_receive) as ctx: + bot = ctx.create_bot() + ctx.receive_event(bot, event) + ctx.receive_event(bot, event) + ctx.receive_event(bot, event) + ctx.should_call_send(event, "pause", "result", at_sender=True) + ctx.should_paused() diff --git a/tests/test_param.py b/tests/test_param.py index c338091e..606ea08a 100644 --- a/tests/test_param.py +++ b/tests/test_param.py @@ -196,7 +196,7 @@ async def test_matcher(app: App, load_plugin): event = make_fake_event()() fake_matcher.set_receive("test", event) event_next = make_fake_event()() - fake_matcher.set_receive(None, event_next) + fake_matcher.set_receive("", event_next) async with app.test_dependent( receive, allow_types=[MatcherParam, DependParam]