mirror of
https://github.com/nonebot/nonebot2.git
synced 2024-11-24 00:55:07 +08:00
✨ Feature: 优化事件分发方法 (#2067)
This commit is contained in:
parent
3199fc454a
commit
f52abc8314
@ -80,7 +80,10 @@ RUN_POSTPCS_PARAMS = (
|
|||||||
|
|
||||||
|
|
||||||
def event_preprocessor(func: T_EventPreProcessor) -> T_EventPreProcessor:
|
def event_preprocessor(func: T_EventPreProcessor) -> T_EventPreProcessor:
|
||||||
"""事件预处理。装饰一个函数,使它在每次接收到事件并分发给各响应器之前执行。"""
|
"""事件预处理。
|
||||||
|
|
||||||
|
装饰一个函数,使它在每次接收到事件并分发给各响应器之前执行。
|
||||||
|
"""
|
||||||
_event_preprocessors.add(
|
_event_preprocessors.add(
|
||||||
Dependent[Any].parse(call=func, allow_types=EVENT_PCS_PARAMS)
|
Dependent[Any].parse(call=func, allow_types=EVENT_PCS_PARAMS)
|
||||||
)
|
)
|
||||||
@ -88,7 +91,10 @@ def event_preprocessor(func: T_EventPreProcessor) -> T_EventPreProcessor:
|
|||||||
|
|
||||||
|
|
||||||
def event_postprocessor(func: T_EventPostProcessor) -> T_EventPostProcessor:
|
def event_postprocessor(func: T_EventPostProcessor) -> T_EventPostProcessor:
|
||||||
"""事件后处理。装饰一个函数,使它在每次接收到事件并分发给各响应器之后执行。"""
|
"""事件后处理。
|
||||||
|
|
||||||
|
装饰一个函数,使它在每次接收到事件并分发给各响应器之后执行。
|
||||||
|
"""
|
||||||
_event_postprocessors.add(
|
_event_postprocessors.add(
|
||||||
Dependent[Any].parse(call=func, allow_types=EVENT_PCS_PARAMS)
|
Dependent[Any].parse(call=func, allow_types=EVENT_PCS_PARAMS)
|
||||||
)
|
)
|
||||||
@ -96,7 +102,10 @@ def event_postprocessor(func: T_EventPostProcessor) -> T_EventPostProcessor:
|
|||||||
|
|
||||||
|
|
||||||
def run_preprocessor(func: T_RunPreProcessor) -> T_RunPreProcessor:
|
def run_preprocessor(func: T_RunPreProcessor) -> T_RunPreProcessor:
|
||||||
"""运行预处理。装饰一个函数,使它在每次事件响应器运行前执行。"""
|
"""运行预处理。
|
||||||
|
|
||||||
|
装饰一个函数,使它在每次事件响应器运行前执行。
|
||||||
|
"""
|
||||||
_run_preprocessors.add(
|
_run_preprocessors.add(
|
||||||
Dependent[Any].parse(call=func, allow_types=RUN_PREPCS_PARAMS)
|
Dependent[Any].parse(call=func, allow_types=RUN_PREPCS_PARAMS)
|
||||||
)
|
)
|
||||||
@ -104,13 +113,222 @@ def run_preprocessor(func: T_RunPreProcessor) -> T_RunPreProcessor:
|
|||||||
|
|
||||||
|
|
||||||
def run_postprocessor(func: T_RunPostProcessor) -> T_RunPostProcessor:
|
def run_postprocessor(func: T_RunPostProcessor) -> T_RunPostProcessor:
|
||||||
"""运行后处理。装饰一个函数,使它在每次事件响应器运行后执行。"""
|
"""运行后处理。
|
||||||
|
|
||||||
|
装饰一个函数,使它在每次事件响应器运行后执行。
|
||||||
|
"""
|
||||||
_run_postprocessors.add(
|
_run_postprocessors.add(
|
||||||
Dependent[Any].parse(call=func, allow_types=RUN_POSTPCS_PARAMS)
|
Dependent[Any].parse(call=func, allow_types=RUN_POSTPCS_PARAMS)
|
||||||
)
|
)
|
||||||
return func
|
return func
|
||||||
|
|
||||||
|
|
||||||
|
async def _apply_event_preprocessors(
|
||||||
|
bot: "Bot",
|
||||||
|
event: "Event",
|
||||||
|
state: T_State,
|
||||||
|
stack: Optional[AsyncExitStack] = None,
|
||||||
|
dependency_cache: Optional[T_DependencyCache] = None,
|
||||||
|
show_log: bool = True,
|
||||||
|
) -> bool:
|
||||||
|
"""运行事件预处理。
|
||||||
|
|
||||||
|
参数:
|
||||||
|
bot: Bot 对象
|
||||||
|
event: Event 对象
|
||||||
|
state: 会话状态
|
||||||
|
stack: 异步上下文栈
|
||||||
|
dependency_cache: 依赖缓存
|
||||||
|
show_log: 是否显示日志
|
||||||
|
|
||||||
|
返回:
|
||||||
|
是否继续处理事件
|
||||||
|
"""
|
||||||
|
if not _event_preprocessors:
|
||||||
|
return True
|
||||||
|
|
||||||
|
if show_log:
|
||||||
|
logger.debug("Running PreProcessors...")
|
||||||
|
|
||||||
|
try:
|
||||||
|
await asyncio.gather(
|
||||||
|
*(
|
||||||
|
run_coro_with_catch(
|
||||||
|
proc(
|
||||||
|
bot=bot,
|
||||||
|
event=event,
|
||||||
|
state=state,
|
||||||
|
stack=stack,
|
||||||
|
dependency_cache=dependency_cache,
|
||||||
|
),
|
||||||
|
(SkippedException,),
|
||||||
|
)
|
||||||
|
for proc in _event_preprocessors
|
||||||
|
)
|
||||||
|
)
|
||||||
|
except IgnoredException as e:
|
||||||
|
logger.opt(colors=True).info(
|
||||||
|
f"Event {escape_tag(event.get_event_name())} is <b>ignored</b>"
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
except Exception as e:
|
||||||
|
logger.opt(colors=True, exception=e).error(
|
||||||
|
"<r><bg #f8bbd0>Error when running EventPreProcessors. "
|
||||||
|
"Event ignored!</bg #f8bbd0></r>"
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
async def _apply_event_postprocessors(
|
||||||
|
bot: "Bot",
|
||||||
|
event: "Event",
|
||||||
|
state: T_State,
|
||||||
|
stack: Optional[AsyncExitStack] = None,
|
||||||
|
dependency_cache: Optional[T_DependencyCache] = None,
|
||||||
|
show_log: bool = True,
|
||||||
|
) -> None:
|
||||||
|
"""运行事件后处理。
|
||||||
|
|
||||||
|
参数:
|
||||||
|
bot: Bot 对象
|
||||||
|
event: Event 对象
|
||||||
|
state: 会话状态
|
||||||
|
stack: 异步上下文栈
|
||||||
|
dependency_cache: 依赖缓存
|
||||||
|
show_log: 是否显示日志
|
||||||
|
"""
|
||||||
|
if not _event_postprocessors:
|
||||||
|
return
|
||||||
|
|
||||||
|
if show_log:
|
||||||
|
logger.debug("Running PostProcessors...")
|
||||||
|
|
||||||
|
try:
|
||||||
|
await asyncio.gather(
|
||||||
|
*(
|
||||||
|
run_coro_with_catch(
|
||||||
|
proc(
|
||||||
|
bot=bot,
|
||||||
|
event=event,
|
||||||
|
state=state,
|
||||||
|
stack=stack,
|
||||||
|
dependency_cache=dependency_cache,
|
||||||
|
),
|
||||||
|
(SkippedException,),
|
||||||
|
)
|
||||||
|
for proc in _event_postprocessors
|
||||||
|
)
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
logger.opt(colors=True, exception=e).error(
|
||||||
|
"<r><bg #f8bbd0>Error when running EventPostProcessors</bg #f8bbd0></r>"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def _apply_run_preprocessors(
|
||||||
|
bot: "Bot",
|
||||||
|
event: "Event",
|
||||||
|
state: T_State,
|
||||||
|
matcher: Matcher,
|
||||||
|
stack: Optional[AsyncExitStack] = None,
|
||||||
|
dependency_cache: Optional[T_DependencyCache] = None,
|
||||||
|
) -> bool:
|
||||||
|
"""运行事件响应器运行前处理。
|
||||||
|
|
||||||
|
参数:
|
||||||
|
bot: Bot 对象
|
||||||
|
event: Event 对象
|
||||||
|
state: 会话状态
|
||||||
|
matcher: 事件响应器
|
||||||
|
stack: 异步上下文栈
|
||||||
|
dependency_cache: 依赖缓存
|
||||||
|
|
||||||
|
返回:
|
||||||
|
是否继续处理事件
|
||||||
|
"""
|
||||||
|
if not _run_preprocessors:
|
||||||
|
return True
|
||||||
|
|
||||||
|
# ensure matcher function can be correctly called
|
||||||
|
with matcher.ensure_context(bot, event):
|
||||||
|
try:
|
||||||
|
await asyncio.gather(
|
||||||
|
*(
|
||||||
|
run_coro_with_catch(
|
||||||
|
proc(
|
||||||
|
matcher=matcher,
|
||||||
|
bot=bot,
|
||||||
|
event=event,
|
||||||
|
state=state,
|
||||||
|
stack=stack,
|
||||||
|
dependency_cache=dependency_cache,
|
||||||
|
),
|
||||||
|
(SkippedException,),
|
||||||
|
)
|
||||||
|
for proc in _run_preprocessors
|
||||||
|
)
|
||||||
|
)
|
||||||
|
except IgnoredException:
|
||||||
|
logger.opt(colors=True).info(f"{matcher} running is <b>cancelled</b>")
|
||||||
|
return False
|
||||||
|
except Exception as e:
|
||||||
|
logger.opt(colors=True, exception=e).error(
|
||||||
|
"<r><bg #f8bbd0>Error when running RunPreProcessors. "
|
||||||
|
"Running cancelled!</bg #f8bbd0></r>"
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
async def _apply_run_postprocessors(
|
||||||
|
bot: "Bot",
|
||||||
|
event: "Event",
|
||||||
|
matcher: Matcher,
|
||||||
|
exception: Optional[Exception] = None,
|
||||||
|
stack: Optional[AsyncExitStack] = None,
|
||||||
|
dependency_cache: Optional[T_DependencyCache] = None,
|
||||||
|
) -> None:
|
||||||
|
"""运行事件响应器运行后处理。
|
||||||
|
|
||||||
|
Args:
|
||||||
|
bot: Bot 对象
|
||||||
|
event: Event 对象
|
||||||
|
matcher: 事件响应器
|
||||||
|
exception: 事件响应器运行异常
|
||||||
|
stack: 异步上下文栈
|
||||||
|
dependency_cache: 依赖缓存
|
||||||
|
"""
|
||||||
|
if not _run_postprocessors:
|
||||||
|
return
|
||||||
|
|
||||||
|
with matcher.ensure_context(bot, event):
|
||||||
|
try:
|
||||||
|
await asyncio.gather(
|
||||||
|
*(
|
||||||
|
run_coro_with_catch(
|
||||||
|
proc(
|
||||||
|
matcher=matcher,
|
||||||
|
exception=exception,
|
||||||
|
bot=bot,
|
||||||
|
event=event,
|
||||||
|
state=matcher.state,
|
||||||
|
stack=stack,
|
||||||
|
dependency_cache=dependency_cache,
|
||||||
|
),
|
||||||
|
(SkippedException,),
|
||||||
|
)
|
||||||
|
for proc in _run_postprocessors
|
||||||
|
)
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
logger.opt(colors=True, exception=e).error(
|
||||||
|
"<r><bg #f8bbd0>Error when running RunPostProcessors</bg #f8bbd0></r>"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def _check_matcher(
|
async def _check_matcher(
|
||||||
Matcher: Type[Matcher],
|
Matcher: Type[Matcher],
|
||||||
bot: "Bot",
|
bot: "Bot",
|
||||||
@ -118,27 +336,39 @@ async def _check_matcher(
|
|||||||
state: T_State,
|
state: T_State,
|
||||||
stack: Optional[AsyncExitStack] = None,
|
stack: Optional[AsyncExitStack] = None,
|
||||||
dependency_cache: Optional[T_DependencyCache] = None,
|
dependency_cache: Optional[T_DependencyCache] = None,
|
||||||
) -> None:
|
) -> bool:
|
||||||
|
"""检查事件响应器是否符合运行条件。
|
||||||
|
|
||||||
|
请注意,过时的事件响应器将被**销毁**。对于未过时的事件响应器,将会一次检查其响应类型、权限和规则。
|
||||||
|
|
||||||
|
参数:
|
||||||
|
Matcher: 要检查的事件响应器
|
||||||
|
bot: Bot 对象
|
||||||
|
event: Event 对象
|
||||||
|
state: 会话状态
|
||||||
|
stack: 异步上下文栈
|
||||||
|
dependency_cache: 依赖缓存
|
||||||
|
|
||||||
|
返回:
|
||||||
|
bool: 是否符合运行条件
|
||||||
|
"""
|
||||||
if Matcher.expire_time and datetime.now() > Matcher.expire_time:
|
if Matcher.expire_time and datetime.now() > Matcher.expire_time:
|
||||||
with contextlib.suppress(Exception):
|
with contextlib.suppress(Exception):
|
||||||
Matcher.destroy()
|
Matcher.destroy()
|
||||||
return
|
return False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if not await Matcher.check_perm(
|
if not await Matcher.check_perm(
|
||||||
bot, event, stack, dependency_cache
|
bot, event, stack, dependency_cache
|
||||||
) or not await Matcher.check_rule(bot, event, state, stack, dependency_cache):
|
) or not await Matcher.check_rule(bot, event, state, stack, dependency_cache):
|
||||||
return
|
return False
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.opt(colors=True, exception=e).error(
|
logger.opt(colors=True, exception=e).error(
|
||||||
f"<r><bg #f8bbd0>Rule check failed for {Matcher}.</bg #f8bbd0></r>"
|
f"<r><bg #f8bbd0>Rule check failed for {Matcher}.</bg #f8bbd0></r>"
|
||||||
)
|
)
|
||||||
return
|
return False
|
||||||
|
|
||||||
if Matcher.temp:
|
return True
|
||||||
with contextlib.suppress(Exception):
|
|
||||||
Matcher.destroy()
|
|
||||||
await _run_matcher(Matcher, bot, event, state, stack, dependency_cache)
|
|
||||||
|
|
||||||
|
|
||||||
async def _run_matcher(
|
async def _run_matcher(
|
||||||
@ -149,36 +379,38 @@ async def _run_matcher(
|
|||||||
stack: Optional[AsyncExitStack] = None,
|
stack: Optional[AsyncExitStack] = None,
|
||||||
dependency_cache: Optional[T_DependencyCache] = None,
|
dependency_cache: Optional[T_DependencyCache] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
"""运行事件响应器。
|
||||||
|
|
||||||
|
临时事件响应器将在运行前被**销毁**。
|
||||||
|
|
||||||
|
参数:
|
||||||
|
Matcher: 事件响应器
|
||||||
|
bot: Bot 对象
|
||||||
|
event: Event 对象
|
||||||
|
state: 会话状态
|
||||||
|
stack: 异步上下文栈
|
||||||
|
dependency_cache: 依赖缓存
|
||||||
|
|
||||||
|
异常:
|
||||||
|
StopPropagation: 阻止事件继续传播
|
||||||
|
"""
|
||||||
logger.info(f"Event will be handled by {Matcher}")
|
logger.info(f"Event will be handled by {Matcher}")
|
||||||
|
|
||||||
matcher = Matcher()
|
if Matcher.temp:
|
||||||
if coros := [
|
with contextlib.suppress(Exception):
|
||||||
run_coro_with_catch(
|
Matcher.destroy()
|
||||||
proc(
|
|
||||||
matcher=matcher,
|
|
||||||
bot=bot,
|
|
||||||
event=event,
|
|
||||||
state=state,
|
|
||||||
stack=stack,
|
|
||||||
dependency_cache=dependency_cache,
|
|
||||||
),
|
|
||||||
(SkippedException,),
|
|
||||||
)
|
|
||||||
for proc in _run_preprocessors
|
|
||||||
]:
|
|
||||||
# ensure matcher function can be correctly called
|
|
||||||
with matcher.ensure_context(bot, event):
|
|
||||||
try:
|
|
||||||
await asyncio.gather(*coros)
|
|
||||||
except IgnoredException:
|
|
||||||
logger.opt(colors=True).info(f"{matcher} running is <b>cancelled</b>")
|
|
||||||
return
|
|
||||||
except Exception as e:
|
|
||||||
logger.opt(colors=True, exception=e).error(
|
|
||||||
"<r><bg #f8bbd0>Error when running RunPreProcessors. Running cancelled!</bg #f8bbd0></r>"
|
|
||||||
)
|
|
||||||
|
|
||||||
return
|
matcher = Matcher()
|
||||||
|
|
||||||
|
if not await _apply_run_preprocessors(
|
||||||
|
bot=bot,
|
||||||
|
event=event,
|
||||||
|
state=state,
|
||||||
|
matcher=matcher,
|
||||||
|
stack=stack,
|
||||||
|
dependency_cache=dependency_cache,
|
||||||
|
):
|
||||||
|
return
|
||||||
|
|
||||||
exception = None
|
exception = None
|
||||||
|
|
||||||
@ -191,33 +423,55 @@ async def _run_matcher(
|
|||||||
)
|
)
|
||||||
exception = e
|
exception = e
|
||||||
|
|
||||||
if coros := [
|
await _apply_run_postprocessors(
|
||||||
run_coro_with_catch(
|
bot=bot,
|
||||||
proc(
|
event=event,
|
||||||
matcher=matcher,
|
matcher=matcher,
|
||||||
exception=exception,
|
exception=exception,
|
||||||
bot=bot,
|
stack=stack,
|
||||||
event=event,
|
dependency_cache=dependency_cache,
|
||||||
state=matcher.state,
|
)
|
||||||
stack=stack,
|
|
||||||
dependency_cache=dependency_cache,
|
|
||||||
),
|
|
||||||
(SkippedException,),
|
|
||||||
)
|
|
||||||
for proc in _run_postprocessors
|
|
||||||
]:
|
|
||||||
# ensure matcher function can be correctly called
|
|
||||||
with matcher.ensure_context(bot, event):
|
|
||||||
try:
|
|
||||||
await asyncio.gather(*coros)
|
|
||||||
except Exception as e:
|
|
||||||
logger.opt(colors=True, exception=e).error(
|
|
||||||
"<r><bg #f8bbd0>Error when running RunPostProcessors</bg #f8bbd0></r>"
|
|
||||||
)
|
|
||||||
|
|
||||||
if matcher.block:
|
if matcher.block:
|
||||||
raise StopPropagation
|
raise StopPropagation
|
||||||
return
|
|
||||||
|
|
||||||
|
async def check_and_run_matcher(
|
||||||
|
Matcher: Type[Matcher],
|
||||||
|
bot: "Bot",
|
||||||
|
event: "Event",
|
||||||
|
state: T_State,
|
||||||
|
stack: Optional[AsyncExitStack] = None,
|
||||||
|
dependency_cache: Optional[T_DependencyCache] = None,
|
||||||
|
) -> None:
|
||||||
|
"""检查并运行事件响应器。
|
||||||
|
|
||||||
|
参数:
|
||||||
|
Matcher: 事件响应器
|
||||||
|
bot: Bot 对象
|
||||||
|
event: Event 对象
|
||||||
|
state: 会话状态
|
||||||
|
stack: 异步上下文栈
|
||||||
|
dependency_cache: 依赖缓存
|
||||||
|
"""
|
||||||
|
if not await _check_matcher(
|
||||||
|
Matcher=Matcher,
|
||||||
|
bot=bot,
|
||||||
|
event=event,
|
||||||
|
state=state,
|
||||||
|
stack=stack,
|
||||||
|
dependency_cache=dependency_cache,
|
||||||
|
):
|
||||||
|
return
|
||||||
|
|
||||||
|
await _run_matcher(
|
||||||
|
Matcher=Matcher,
|
||||||
|
bot=bot,
|
||||||
|
event=event,
|
||||||
|
state=state,
|
||||||
|
stack=stack,
|
||||||
|
dependency_cache=dependency_cache,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def handle_event(bot: "Bot", event: "Event") -> None:
|
async def handle_event(bot: "Bot", event: "Event") -> None:
|
||||||
@ -245,35 +499,16 @@ async def handle_event(bot: "Bot", event: "Event") -> None:
|
|||||||
state: Dict[Any, Any] = {}
|
state: Dict[Any, Any] = {}
|
||||||
dependency_cache: T_DependencyCache = {}
|
dependency_cache: T_DependencyCache = {}
|
||||||
|
|
||||||
|
# create event scope context
|
||||||
async with AsyncExitStack() as stack:
|
async with AsyncExitStack() as stack:
|
||||||
if coros := [
|
if not await _apply_event_preprocessors(
|
||||||
run_coro_with_catch(
|
bot=bot,
|
||||||
proc(
|
event=event,
|
||||||
bot=bot,
|
state=state,
|
||||||
event=event,
|
stack=stack,
|
||||||
state=state,
|
dependency_cache=dependency_cache,
|
||||||
stack=stack,
|
):
|
||||||
dependency_cache=dependency_cache,
|
return
|
||||||
),
|
|
||||||
(SkippedException,),
|
|
||||||
)
|
|
||||||
for proc in _event_preprocessors
|
|
||||||
]:
|
|
||||||
try:
|
|
||||||
if show_log:
|
|
||||||
logger.debug("Running PreProcessors...")
|
|
||||||
await asyncio.gather(*coros)
|
|
||||||
except IgnoredException as e:
|
|
||||||
logger.opt(colors=True).info(
|
|
||||||
f"Event {escape_tag(event.get_event_name())} is <b>ignored</b>"
|
|
||||||
)
|
|
||||||
return
|
|
||||||
except Exception as e:
|
|
||||||
logger.opt(colors=True, exception=e).error(
|
|
||||||
"<r><bg #f8bbd0>Error when running EventPreProcessors. "
|
|
||||||
"Event ignored!</bg #f8bbd0></r>"
|
|
||||||
)
|
|
||||||
return
|
|
||||||
|
|
||||||
# Trie Match
|
# Trie Match
|
||||||
try:
|
try:
|
||||||
@ -284,6 +519,7 @@ async def handle_event(bot: "Bot", event: "Event") -> None:
|
|||||||
)
|
)
|
||||||
|
|
||||||
break_flag = False
|
break_flag = False
|
||||||
|
# iterate through all priority until stop propagation
|
||||||
for priority in sorted(matchers.keys()):
|
for priority in sorted(matchers.keys()):
|
||||||
if break_flag:
|
if break_flag:
|
||||||
break
|
break
|
||||||
@ -292,14 +528,12 @@ async def handle_event(bot: "Bot", event: "Event") -> None:
|
|||||||
logger.debug(f"Checking for matchers in priority {priority}...")
|
logger.debug(f"Checking for matchers in priority {priority}...")
|
||||||
|
|
||||||
pending_tasks = [
|
pending_tasks = [
|
||||||
_check_matcher(
|
check_and_run_matcher(
|
||||||
matcher, bot, event, state.copy(), stack, dependency_cache
|
matcher, bot, event, state.copy(), stack, dependency_cache
|
||||||
)
|
)
|
||||||
for matcher in matchers[priority]
|
for matcher in matchers[priority]
|
||||||
]
|
]
|
||||||
|
|
||||||
results = await asyncio.gather(*pending_tasks, return_exceptions=True)
|
results = await asyncio.gather(*pending_tasks, return_exceptions=True)
|
||||||
|
|
||||||
for result in results:
|
for result in results:
|
||||||
if not isinstance(result, Exception):
|
if not isinstance(result, Exception):
|
||||||
continue
|
continue
|
||||||
@ -314,24 +548,4 @@ async def handle_event(bot: "Bot", event: "Event") -> None:
|
|||||||
if show_log:
|
if show_log:
|
||||||
logger.debug("Checking for matchers completed")
|
logger.debug("Checking for matchers completed")
|
||||||
|
|
||||||
if coros := [
|
await _apply_event_postprocessors(bot, event, state, stack, dependency_cache)
|
||||||
run_coro_with_catch(
|
|
||||||
proc(
|
|
||||||
bot=bot,
|
|
||||||
event=event,
|
|
||||||
state=state,
|
|
||||||
stack=stack,
|
|
||||||
dependency_cache=dependency_cache,
|
|
||||||
),
|
|
||||||
(SkippedException,),
|
|
||||||
)
|
|
||||||
for proc in _event_postprocessors
|
|
||||||
]:
|
|
||||||
try:
|
|
||||||
if show_log:
|
|
||||||
logger.debug("Running PostProcessors...")
|
|
||||||
await asyncio.gather(*coros)
|
|
||||||
except Exception as e:
|
|
||||||
logger.opt(colors=True, exception=e).error(
|
|
||||||
"<r><bg #f8bbd0>Error when running EventPostProcessors</bg #f8bbd0></r>"
|
|
||||||
)
|
|
||||||
|
@ -113,8 +113,7 @@ def run_sync(call: Callable[P, R]) -> Callable[P, Coroutine[None, None, R]]:
|
|||||||
loop = asyncio.get_running_loop()
|
loop = asyncio.get_running_loop()
|
||||||
pfunc = partial(call, *args, **kwargs)
|
pfunc = partial(call, *args, **kwargs)
|
||||||
context = copy_context()
|
context = copy_context()
|
||||||
context_run = context.run
|
result = await loop.run_in_executor(None, partial(context.run, pfunc))
|
||||||
result = await loop.run_in_executor(None, context_run, pfunc)
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
return _wrapper
|
return _wrapper
|
||||||
@ -139,6 +138,7 @@ async def run_sync_ctx_manager(
|
|||||||
async def run_coro_with_catch(
|
async def run_coro_with_catch(
|
||||||
coro: Coroutine[Any, Any, T],
|
coro: Coroutine[Any, Any, T],
|
||||||
exc: Tuple[Type[Exception], ...],
|
exc: Tuple[Type[Exception], ...],
|
||||||
|
return_on_err: None = None,
|
||||||
) -> Union[T, None]:
|
) -> Union[T, None]:
|
||||||
...
|
...
|
||||||
|
|
||||||
|
@ -25,6 +25,6 @@ def load_plugin(nonebug_init: None) -> Set["Plugin"]:
|
|||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="session", autouse=True)
|
@pytest.fixture(scope="session", autouse=True)
|
||||||
def load_example(nonebug_init: None) -> Set["Plugin"]:
|
def load_builtin_plugin(nonebug_init: None) -> Set["Plugin"]:
|
||||||
# preload example plugins
|
# preload builtin plugins
|
||||||
return nonebot.load_plugins(str(Path(__file__).parent / "examples"))
|
return nonebot.load_builtin_plugins("echo", "single_session")
|
||||||
|
@ -1,29 +0,0 @@
|
|||||||
from nonebot import on_command
|
|
||||||
from nonebot.rule import to_me
|
|
||||||
from nonebot.matcher import Matcher
|
|
||||||
from nonebot.adapters import Message
|
|
||||||
from nonebot.params import Arg, CommandArg, ArgPlainText
|
|
||||||
|
|
||||||
weather = on_command("weather", rule=to_me(), aliases={"天气", "天气预报"}, priority=5)
|
|
||||||
|
|
||||||
|
|
||||||
@weather.handle()
|
|
||||||
async def handle_first_receive(matcher: Matcher, args: Message = CommandArg()):
|
|
||||||
plain_text = args.extract_plain_text() # 首次发送命令时跟随的参数,例:/天气 上海,则args为上海
|
|
||||||
if plain_text:
|
|
||||||
matcher.set_arg("city", args) # 如果用户发送了参数则直接赋值
|
|
||||||
|
|
||||||
|
|
||||||
@weather.got("city", prompt="你想查询哪个城市的天气呢?")
|
|
||||||
async def handle_city(city: Message = Arg(), city_name: str = ArgPlainText("city")):
|
|
||||||
if city_name not in ["北京", "上海"]: # 如果参数不符合要求,则提示用户重新输入
|
|
||||||
# 可以使用平台的 Message 类直接构造模板消息
|
|
||||||
await weather.reject(city.template("你想查询的城市 {city} 暂不支持,请重新输入!"))
|
|
||||||
|
|
||||||
city_weather = await get_weather(city_name)
|
|
||||||
await weather.finish(city_weather)
|
|
||||||
|
|
||||||
|
|
||||||
# 在这里编写获取天气信息的函数
|
|
||||||
async def get_weather(city: str) -> str:
|
|
||||||
return f"{city}的天气是..."
|
|
388
tests/test_broadcast.py
Normal file
388
tests/test_broadcast.py
Normal file
@ -0,0 +1,388 @@
|
|||||||
|
import sys
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from nonebug import App
|
||||||
|
|
||||||
|
from nonebot import on_message
|
||||||
|
import nonebot.message as message
|
||||||
|
from utils import make_fake_event
|
||||||
|
from nonebot.params import Depends
|
||||||
|
from nonebot.typing import T_State
|
||||||
|
from nonebot.matcher import Matcher
|
||||||
|
from nonebot.adapters import Bot, Event
|
||||||
|
from nonebot.exception import IgnoredException
|
||||||
|
from nonebot.log import logger, default_filter, default_format
|
||||||
|
from nonebot.message import (
|
||||||
|
run_preprocessor,
|
||||||
|
run_postprocessor,
|
||||||
|
event_preprocessor,
|
||||||
|
event_postprocessor,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def _dependency() -> int:
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_event_preprocessor(app: App, monkeypatch: pytest.MonkeyPatch):
|
||||||
|
with monkeypatch.context() as m:
|
||||||
|
m.setattr(message, "_event_preprocessors", set())
|
||||||
|
|
||||||
|
runned = False
|
||||||
|
|
||||||
|
@event_preprocessor
|
||||||
|
async def test_preprocessor(
|
||||||
|
bot: Bot,
|
||||||
|
event: Event,
|
||||||
|
state: T_State,
|
||||||
|
sub: int = Depends(_dependency),
|
||||||
|
default: int = 1,
|
||||||
|
):
|
||||||
|
nonlocal runned
|
||||||
|
runned = True
|
||||||
|
|
||||||
|
assert test_preprocessor in {
|
||||||
|
dependent.call for dependent in message._event_preprocessors
|
||||||
|
}
|
||||||
|
|
||||||
|
with app.provider.context({}):
|
||||||
|
matcher = on_message()
|
||||||
|
|
||||||
|
async with app.test_matcher(matcher) as ctx:
|
||||||
|
bot = ctx.create_bot()
|
||||||
|
event = make_fake_event()()
|
||||||
|
ctx.receive_event(bot, event)
|
||||||
|
|
||||||
|
assert runned, "event_preprocessor should runned"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_event_preprocessor_ignore(app: App, monkeypatch: pytest.MonkeyPatch):
|
||||||
|
with monkeypatch.context() as m:
|
||||||
|
m.setattr(message, "_event_preprocessors", set())
|
||||||
|
|
||||||
|
@event_preprocessor
|
||||||
|
async def test_preprocessor():
|
||||||
|
raise IgnoredException("pass")
|
||||||
|
|
||||||
|
assert test_preprocessor in {
|
||||||
|
dependent.call for dependent in message._event_preprocessors
|
||||||
|
}
|
||||||
|
|
||||||
|
runned = False
|
||||||
|
|
||||||
|
async def handler():
|
||||||
|
nonlocal runned
|
||||||
|
runned = True
|
||||||
|
|
||||||
|
with app.provider.context({}):
|
||||||
|
matcher = on_message(handlers=[handler])
|
||||||
|
|
||||||
|
async with app.test_matcher(matcher) as ctx:
|
||||||
|
bot = ctx.create_bot()
|
||||||
|
event = make_fake_event()()
|
||||||
|
ctx.receive_event(bot, event)
|
||||||
|
|
||||||
|
assert not runned, "matcher should not runned"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_event_preprocessor_exception(
|
||||||
|
app: App, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
|
||||||
|
):
|
||||||
|
with monkeypatch.context() as m:
|
||||||
|
m.setattr(message, "_event_preprocessors", set())
|
||||||
|
|
||||||
|
@event_preprocessor
|
||||||
|
async def test_preprocessor():
|
||||||
|
raise RuntimeError("test")
|
||||||
|
|
||||||
|
assert test_preprocessor in {
|
||||||
|
dependent.call for dependent in message._event_preprocessors
|
||||||
|
}
|
||||||
|
|
||||||
|
runned = False
|
||||||
|
|
||||||
|
async def handler():
|
||||||
|
nonlocal runned
|
||||||
|
runned = True
|
||||||
|
|
||||||
|
handler_id = logger.add(
|
||||||
|
sys.stdout,
|
||||||
|
level=0,
|
||||||
|
diagnose=False,
|
||||||
|
filter=default_filter,
|
||||||
|
format=default_format,
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
with app.provider.context({}):
|
||||||
|
matcher = on_message(handlers=[handler])
|
||||||
|
|
||||||
|
async with app.test_matcher(matcher) as ctx:
|
||||||
|
bot = ctx.create_bot()
|
||||||
|
event = make_fake_event()()
|
||||||
|
ctx.receive_event(bot, event)
|
||||||
|
finally:
|
||||||
|
logger.remove(handler_id)
|
||||||
|
|
||||||
|
assert not runned, "matcher should not runned"
|
||||||
|
assert "RuntimeError: test" in capsys.readouterr().out
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_event_postprocessor(app: App, monkeypatch: pytest.MonkeyPatch):
|
||||||
|
with monkeypatch.context() as m:
|
||||||
|
m.setattr(message, "_event_postprocessors", set())
|
||||||
|
|
||||||
|
runned = False
|
||||||
|
|
||||||
|
@event_postprocessor
|
||||||
|
async def test_postprocessor(
|
||||||
|
bot: Bot,
|
||||||
|
event: Event,
|
||||||
|
state: T_State,
|
||||||
|
sub: int = Depends(_dependency),
|
||||||
|
default: int = 1,
|
||||||
|
):
|
||||||
|
nonlocal runned
|
||||||
|
runned = True
|
||||||
|
|
||||||
|
assert test_postprocessor in {
|
||||||
|
dependent.call for dependent in message._event_postprocessors
|
||||||
|
}
|
||||||
|
|
||||||
|
with app.provider.context({}):
|
||||||
|
matcher = on_message()
|
||||||
|
|
||||||
|
async with app.test_matcher(matcher) as ctx:
|
||||||
|
bot = ctx.create_bot()
|
||||||
|
event = make_fake_event()()
|
||||||
|
ctx.receive_event(bot, event)
|
||||||
|
|
||||||
|
assert runned, "event_postprocessor should runned"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_event_postprocessor_exception(
|
||||||
|
app: App, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
|
||||||
|
):
|
||||||
|
with monkeypatch.context() as m:
|
||||||
|
m.setattr(message, "_event_postprocessors", set())
|
||||||
|
|
||||||
|
@event_postprocessor
|
||||||
|
async def test_postprocessor():
|
||||||
|
raise RuntimeError("test")
|
||||||
|
|
||||||
|
assert test_postprocessor in {
|
||||||
|
dependent.call for dependent in message._event_postprocessors
|
||||||
|
}
|
||||||
|
|
||||||
|
handler_id = logger.add(
|
||||||
|
sys.stdout,
|
||||||
|
level=0,
|
||||||
|
diagnose=False,
|
||||||
|
filter=default_filter,
|
||||||
|
format=default_format,
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
with app.provider.context({}):
|
||||||
|
matcher = on_message()
|
||||||
|
|
||||||
|
async with app.test_matcher(matcher) as ctx:
|
||||||
|
bot = ctx.create_bot()
|
||||||
|
event = make_fake_event()()
|
||||||
|
ctx.receive_event(bot, event)
|
||||||
|
finally:
|
||||||
|
logger.remove(handler_id)
|
||||||
|
|
||||||
|
assert "RuntimeError: test" in capsys.readouterr().out
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_run_preprocessor(app: App, monkeypatch: pytest.MonkeyPatch):
|
||||||
|
with monkeypatch.context() as m:
|
||||||
|
m.setattr(message, "_run_preprocessors", set())
|
||||||
|
|
||||||
|
runned = False
|
||||||
|
|
||||||
|
@run_preprocessor
|
||||||
|
async def test_preprocessor(
|
||||||
|
bot: Bot,
|
||||||
|
event: Event,
|
||||||
|
state: T_State,
|
||||||
|
matcher: Matcher,
|
||||||
|
sub: int = Depends(_dependency),
|
||||||
|
default: int = 1,
|
||||||
|
):
|
||||||
|
nonlocal runned
|
||||||
|
runned = True
|
||||||
|
|
||||||
|
await matcher.send("test")
|
||||||
|
|
||||||
|
assert test_preprocessor in {
|
||||||
|
dependent.call for dependent in message._run_preprocessors
|
||||||
|
}
|
||||||
|
|
||||||
|
with app.provider.context({}):
|
||||||
|
matcher = on_message()
|
||||||
|
|
||||||
|
async with app.test_matcher(matcher) as ctx:
|
||||||
|
bot = ctx.create_bot()
|
||||||
|
event = make_fake_event()()
|
||||||
|
ctx.receive_event(bot, event)
|
||||||
|
ctx.should_call_send(event, "test", True, bot)
|
||||||
|
|
||||||
|
assert runned, "run_preprocessor should runned"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_run_preprocessor_ignore(app: App, monkeypatch: pytest.MonkeyPatch):
|
||||||
|
with monkeypatch.context() as m:
|
||||||
|
m.setattr(message, "_run_preprocessors", set())
|
||||||
|
|
||||||
|
@run_preprocessor
|
||||||
|
async def test_preprocessor():
|
||||||
|
raise IgnoredException("pass")
|
||||||
|
|
||||||
|
assert test_preprocessor in {
|
||||||
|
dependent.call for dependent in message._run_preprocessors
|
||||||
|
}
|
||||||
|
|
||||||
|
runned = False
|
||||||
|
|
||||||
|
async def handler():
|
||||||
|
nonlocal runned
|
||||||
|
runned = True
|
||||||
|
|
||||||
|
with app.provider.context({}):
|
||||||
|
matcher = on_message(handlers=[handler])
|
||||||
|
|
||||||
|
async with app.test_matcher(matcher) as ctx:
|
||||||
|
bot = ctx.create_bot()
|
||||||
|
event = make_fake_event()()
|
||||||
|
ctx.receive_event(bot, event)
|
||||||
|
|
||||||
|
assert not runned, "matcher should not runned"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_run_preprocessor_exception(
|
||||||
|
app: App, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
|
||||||
|
):
|
||||||
|
with monkeypatch.context() as m:
|
||||||
|
m.setattr(message, "_run_preprocessors", set())
|
||||||
|
|
||||||
|
@run_preprocessor
|
||||||
|
async def test_preprocessor():
|
||||||
|
raise RuntimeError("test")
|
||||||
|
|
||||||
|
assert test_preprocessor in {
|
||||||
|
dependent.call for dependent in message._run_preprocessors
|
||||||
|
}
|
||||||
|
|
||||||
|
runned = False
|
||||||
|
|
||||||
|
async def handler():
|
||||||
|
nonlocal runned
|
||||||
|
runned = True
|
||||||
|
|
||||||
|
handler_id = logger.add(
|
||||||
|
sys.stdout,
|
||||||
|
level=0,
|
||||||
|
diagnose=False,
|
||||||
|
filter=default_filter,
|
||||||
|
format=default_format,
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
with app.provider.context({}):
|
||||||
|
matcher = on_message(handlers=[handler])
|
||||||
|
|
||||||
|
async with app.test_matcher(matcher) as ctx:
|
||||||
|
bot = ctx.create_bot()
|
||||||
|
event = make_fake_event()()
|
||||||
|
ctx.receive_event(bot, event)
|
||||||
|
finally:
|
||||||
|
logger.remove(handler_id)
|
||||||
|
|
||||||
|
assert not runned, "matcher should not runned"
|
||||||
|
assert "RuntimeError: test" in capsys.readouterr().out
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_run_postprocessor(app: App, monkeypatch: pytest.MonkeyPatch):
|
||||||
|
with monkeypatch.context() as m:
|
||||||
|
m.setattr(message, "_run_postprocessors", set())
|
||||||
|
|
||||||
|
runned = False
|
||||||
|
|
||||||
|
@run_postprocessor
|
||||||
|
async def test_postprocessor(
|
||||||
|
bot: Bot,
|
||||||
|
event: Event,
|
||||||
|
state: T_State,
|
||||||
|
matcher: Matcher,
|
||||||
|
exception: Optional[Exception],
|
||||||
|
sub: int = Depends(_dependency),
|
||||||
|
default: int = 1,
|
||||||
|
):
|
||||||
|
nonlocal runned
|
||||||
|
runned = True
|
||||||
|
|
||||||
|
await matcher.send("test")
|
||||||
|
|
||||||
|
assert test_postprocessor in {
|
||||||
|
dependent.call for dependent in message._run_postprocessors
|
||||||
|
}
|
||||||
|
|
||||||
|
with app.provider.context({}):
|
||||||
|
matcher = on_message()
|
||||||
|
|
||||||
|
async with app.test_matcher(matcher) as ctx:
|
||||||
|
bot = ctx.create_bot()
|
||||||
|
event = make_fake_event()()
|
||||||
|
ctx.receive_event(bot, event)
|
||||||
|
ctx.should_call_send(event, "test", True, bot)
|
||||||
|
|
||||||
|
assert runned, "run_postprocessor should runned"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_run_postprocessor_exception(
|
||||||
|
app: App, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
|
||||||
|
):
|
||||||
|
with monkeypatch.context() as m:
|
||||||
|
m.setattr(message, "_run_postprocessors", set())
|
||||||
|
|
||||||
|
@run_postprocessor
|
||||||
|
async def test_postprocessor():
|
||||||
|
raise RuntimeError("test")
|
||||||
|
|
||||||
|
assert test_postprocessor in {
|
||||||
|
dependent.call for dependent in message._run_postprocessors
|
||||||
|
}
|
||||||
|
|
||||||
|
handler_id = logger.add(
|
||||||
|
sys.stdout,
|
||||||
|
level=0,
|
||||||
|
diagnose=False,
|
||||||
|
filter=default_filter,
|
||||||
|
format=default_format,
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
with app.provider.context({}):
|
||||||
|
matcher = on_message()
|
||||||
|
|
||||||
|
async with app.test_matcher(matcher) as ctx:
|
||||||
|
bot = ctx.create_bot()
|
||||||
|
event = make_fake_event()()
|
||||||
|
ctx.receive_event(bot, event)
|
||||||
|
finally:
|
||||||
|
logger.remove(handler_id)
|
||||||
|
|
||||||
|
assert "RuntimeError: test" in capsys.readouterr().out
|
@ -1,76 +0,0 @@
|
|||||||
import pytest
|
|
||||||
from nonebug import App
|
|
||||||
|
|
||||||
from utils import make_fake_event, make_fake_message
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
|
||||||
async def test_weather(app: App):
|
|
||||||
from examples.weather import weather
|
|
||||||
|
|
||||||
# 将此处的 make_fake_message() 替换为你要发送的平台消息 Message 类型
|
|
||||||
# from nonebot.adapters.console import Message
|
|
||||||
Message = make_fake_message()
|
|
||||||
|
|
||||||
async with app.test_matcher(weather) as ctx:
|
|
||||||
bot = ctx.create_bot()
|
|
||||||
|
|
||||||
msg = Message("/天气 上海")
|
|
||||||
# 将此处的 make_fake_event() 替换为你要发送的平台事件 Event 类型
|
|
||||||
# from nonebot.adapters.console import MessageEvent
|
|
||||||
# event = MessageEvent(message=msg, to_me=True, ...)
|
|
||||||
event = make_fake_event(_message=msg, _to_me=True)()
|
|
||||||
|
|
||||||
ctx.receive_event(bot, event)
|
|
||||||
ctx.should_call_send(event, "上海的天气是...", True)
|
|
||||||
ctx.should_finished()
|
|
||||||
|
|
||||||
async with app.test_matcher(weather) as ctx:
|
|
||||||
bot = ctx.create_bot()
|
|
||||||
|
|
||||||
msg = Message("/天气 南京")
|
|
||||||
# 将此处的 make_fake_event() 替换为你要发送的平台事件 Event 类型
|
|
||||||
event = make_fake_event(_message=msg, _to_me=True)()
|
|
||||||
|
|
||||||
ctx.receive_event(bot, event)
|
|
||||||
ctx.should_call_send(
|
|
||||||
event,
|
|
||||||
Message.template("你想查询的城市 {} 暂不支持,请重新输入!").format("南京"),
|
|
||||||
True,
|
|
||||||
)
|
|
||||||
ctx.should_rejected()
|
|
||||||
|
|
||||||
msg = Message("北京")
|
|
||||||
event = make_fake_event(_message=msg)()
|
|
||||||
|
|
||||||
ctx.receive_event(bot, event)
|
|
||||||
ctx.should_call_send(event, "北京的天气是...", True)
|
|
||||||
ctx.should_finished()
|
|
||||||
|
|
||||||
async with app.test_matcher(weather) as ctx:
|
|
||||||
bot = ctx.create_bot()
|
|
||||||
|
|
||||||
msg = Message("/天气")
|
|
||||||
# 将此处的 make_fake_event() 替换为你要发送的平台事件 Event 类型
|
|
||||||
event = make_fake_event(_message=msg, _to_me=True)()
|
|
||||||
|
|
||||||
ctx.receive_event(bot, event)
|
|
||||||
ctx.should_call_send(event, "你想查询哪个城市的天气呢?", True)
|
|
||||||
|
|
||||||
msg = Message("杭州")
|
|
||||||
event = make_fake_event(_message=msg)()
|
|
||||||
|
|
||||||
ctx.receive_event(bot, event)
|
|
||||||
ctx.should_call_send(
|
|
||||||
event,
|
|
||||||
Message.template("你想查询的城市 {} 暂不支持,请重新输入!").format("杭州"),
|
|
||||||
True,
|
|
||||||
)
|
|
||||||
ctx.should_rejected()
|
|
||||||
|
|
||||||
msg = Message("北京")
|
|
||||||
event = make_fake_event(_message=msg)()
|
|
||||||
|
|
||||||
ctx.receive_event(bot, event)
|
|
||||||
ctx.should_call_send(event, "北京的天气是...", True)
|
|
||||||
ctx.should_finished()
|
|
@ -2,8 +2,8 @@ import pytest
|
|||||||
from nonebug import App
|
from nonebug import App
|
||||||
|
|
||||||
from nonebot.permission import User
|
from nonebot.permission import User
|
||||||
from nonebot.message import _check_matcher
|
|
||||||
from nonebot.matcher import Matcher, matchers
|
from nonebot.matcher import Matcher, matchers
|
||||||
|
from nonebot.message import check_and_run_matcher
|
||||||
from utils import make_fake_event, make_fake_message
|
from utils import make_fake_event, make_fake_message
|
||||||
|
|
||||||
|
|
||||||
@ -200,19 +200,19 @@ async def test_expire(app: App):
|
|||||||
async with app.test_api() as ctx:
|
async with app.test_api() as ctx:
|
||||||
bot = ctx.create_bot()
|
bot = ctx.create_bot()
|
||||||
assert test_temp_matcher in matchers[test_temp_matcher.priority]
|
assert test_temp_matcher in matchers[test_temp_matcher.priority]
|
||||||
await _check_matcher(test_temp_matcher, bot, event, {})
|
await check_and_run_matcher(test_temp_matcher, bot, event, {})
|
||||||
assert test_temp_matcher not in matchers[test_temp_matcher.priority]
|
assert test_temp_matcher not in matchers[test_temp_matcher.priority]
|
||||||
|
|
||||||
event = make_fake_event()()
|
event = make_fake_event()()
|
||||||
async with app.test_api() as ctx:
|
async with app.test_api() as ctx:
|
||||||
bot = ctx.create_bot()
|
bot = ctx.create_bot()
|
||||||
assert test_datetime_matcher in matchers[test_datetime_matcher.priority]
|
assert test_datetime_matcher in matchers[test_datetime_matcher.priority]
|
||||||
await _check_matcher(test_datetime_matcher, bot, event, {})
|
await check_and_run_matcher(test_datetime_matcher, bot, event, {})
|
||||||
assert test_datetime_matcher not in matchers[test_datetime_matcher.priority]
|
assert test_datetime_matcher not in matchers[test_datetime_matcher.priority]
|
||||||
|
|
||||||
event = make_fake_event()()
|
event = make_fake_event()()
|
||||||
async with app.test_api() as ctx:
|
async with app.test_api() as ctx:
|
||||||
bot = ctx.create_bot()
|
bot = ctx.create_bot()
|
||||||
assert test_timedelta_matcher in matchers[test_timedelta_matcher.priority]
|
assert test_timedelta_matcher in matchers[test_timedelta_matcher.priority]
|
||||||
await _check_matcher(test_timedelta_matcher, bot, event, {})
|
await check_and_run_matcher(test_timedelta_matcher, bot, event, {})
|
||||||
assert test_timedelta_matcher not in matchers[test_timedelta_matcher.priority]
|
assert test_timedelta_matcher not in matchers[test_timedelta_matcher.priority]
|
||||||
|
@ -22,11 +22,11 @@ async def test_load_plugin():
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_load_plugins(load_plugin: Set[Plugin], load_example: Set[Plugin]):
|
async def test_load_plugins(load_plugin: Set[Plugin], load_builtin_plugin: Set[Plugin]):
|
||||||
loaded_plugins = {
|
loaded_plugins = {
|
||||||
plugin for plugin in nonebot.get_loaded_plugins() if not plugin.parent_plugin
|
plugin for plugin in nonebot.get_loaded_plugins() if not plugin.parent_plugin
|
||||||
}
|
}
|
||||||
assert loaded_plugins >= load_plugin | load_example
|
assert loaded_plugins >= load_plugin | load_builtin_plugin
|
||||||
|
|
||||||
# check simple plugin
|
# check simple plugin
|
||||||
assert "plugins.export" in sys.modules
|
assert "plugins.export" in sys.modules
|
||||||
|
Loading…
Reference in New Issue
Block a user