From 91a4bf0f82c53f749d9836d8dc9d9c27286eef09 Mon Sep 17 00:00:00 2001 From: aicorein Date: Fri, 22 Nov 2024 21:09:17 +0800 Subject: [PATCH] [melobot] Rename to unify context apis naming style --- docs/source/intro/action-echo.md | 2 +- docs/source/ob_api/v11.adapter.rst | 2 +- src/melobot/_meta.py | 2 +- src/melobot/adapter/base.py | 6 ++--- src/melobot/adapter/model.py | 6 ++--- src/melobot/bot/base.py | 8 +++---- src/melobot/ctx.py | 24 +++++++++++++++++-- src/melobot/handle/process.py | 4 ++-- src/melobot/plugin/load.py | 4 ++-- .../protocols/onebot/v11/adapter/base.py | 2 +- src/melobot/protocols/onebot/v11/handle.py | 7 ++++-- src/melobot/session/base.py | 2 +- src/melobot/typ.py | 2 +- tests/onebot/v11/test_io_duplex_http.py | 2 +- tests/onebot/v11/test_io_forward.py | 2 +- tests/onebot/v11/test_io_reverse.py | 2 +- tests/onebot/v11/test_utils_parse.py | 2 +- 17 files changed, 51 insertions(+), 28 deletions(-) diff --git a/docs/source/intro/action-echo.md b/docs/source/intro/action-echo.md index fb602f2e..841e23bd 100644 --- a/docs/source/intro/action-echo.md +++ b/docs/source/intro/action-echo.md @@ -58,7 +58,7 @@ from melobot.protocols.onebot.v11 import Adapter, on_message, EchoRequireCtx @on_message(...) async def _(adapter: Adapter): - with EchoRequireCtx().in_ctx(True): + with EchoRequireCtx().unfold(True): # 全部都会等待 await adapter.send("我一定先被看到") await adapter.send("我一定是第二条消息") diff --git a/docs/source/ob_api/v11.adapter.rst b/docs/source/ob_api/v11.adapter.rst index ba8dd41b..a8450137 100644 --- a/docs/source/ob_api/v11.adapter.rst +++ b/docs/source/ob_api/v11.adapter.rst @@ -258,7 +258,7 @@ v11 回应 handles1 = await block_send("Hello Melobot!") handles2 = await block_send("Hello OneBot!") # 当然,或者这样: - with EchoRequireCtx().in_ctx(True): + with EchoRequireCtx().unfold(True): handles1 = await adapter.send("Hello Melobot!") handles2 = await adapter.send_image( "test.jpg", diff --git a/src/melobot/_meta.py b/src/melobot/_meta.py index a2ec3632..49480542 100644 --- a/src/melobot/_meta.py +++ b/src/melobot/_meta.py @@ -4,7 +4,7 @@ from .typ import T -__version__ = "3.0.0rc18" +__version__ = "3.0.0rc19" def _version_str_to_info(s: str) -> VersionInfo: diff --git a/src/melobot/adapter/base.py b/src/melobot/adapter/base.py index 8f861353..fab0097b 100644 --- a/src/melobot/adapter/base.py +++ b/src/melobot/adapter/base.py @@ -183,7 +183,7 @@ async def __adapter_input_loop__(self, src: InSourceT) -> NoReturn: try: packet = await src.input() event = await self._event_factory.create(packet) - with _EVENT_BUILD_INFO_CTX.in_ctx(EventBuildInfo(self, src)): + with _EVENT_BUILD_INFO_CTX.unfold(EventBuildInfo(self, src)): await self._life_bus.emit( AdapterLifeSpan.BEFORE_EVENT, wait=True, args=(event,) ) @@ -228,12 +228,12 @@ async def __adapter_launch__(self) -> AsyncGenerator[Self, None]: @final def filter_out( self, filter: Callable[[OutSourceT], bool] - ) -> _GeneratorContextManager[None]: + ) -> _GeneratorContextManager[Callable[[OutSourceT], bool]]: """上下文管理器,提供由 `filter` 控制输出的输出上下文 :param filter: 过滤函数,为 `True` 时允许该输出源输出 """ - return _OUT_SRC_FILTER_CTX.in_ctx(filter) + return _OUT_SRC_FILTER_CTX.unfold(filter) async def call_output(self, action: ActionT) -> tuple[ActionHandle, ...]: """输出行为,并返回各个输出源返回的 :class:`.ActionHandle` 组成的元组 diff --git a/src/melobot/adapter/model.py b/src/melobot/adapter/model.py index 1841569f..5024d391 100644 --- a/src/melobot/adapter/model.py +++ b/src/melobot/adapter/model.py @@ -211,7 +211,7 @@ def _add_step(self, step: _ChainStep) -> None: self._chain[-1].next = step self._chain.append(step) - def in_ctx(self, ctx: Context[T], val: T) -> Self: + def unfold(self, ctx: Context[T], val: T) -> Self: """指定链后续的步骤中在 `ctx` 类别的上下文中执行,上下文值为 `val` :param ctx: 上下文类别 @@ -257,7 +257,7 @@ def sleep(self, interval: float) -> Self: async def _start(self, step: _ChainStep) -> None: if isinstance(step, _ChainCtxStep): - with step.ctx_var.in_ctx(step.ctx_val): + with step.ctx_var.unfold(step.ctx_val): if step.next: await self._start(step.next) return @@ -278,5 +278,5 @@ def open_chain() -> Generator[ActionChain, None, None]: :yield: 行为链对象 """ - with ActionManualSignalCtx().in_ctx(True): + with ActionManualSignalCtx().unfold(True): yield ActionChain() diff --git a/src/melobot/bot/base.py b/src/melobot/bot/base.py index 06274133..90d68d1a 100644 --- a/src/melobot/bot/base.py +++ b/src/melobot/bot/base.py @@ -131,15 +131,15 @@ def loop(self) -> asyncio.AbstractEventLoop: @contextmanager def _sync_common_ctx(self) -> Generator[ExitStack, None, None]: with ExitStack() as stack: - stack.enter_context(_BOT_CTX.in_ctx(self)) - stack.enter_context(_LOGGER_CTX.in_ctx(self.logger)) + stack.enter_context(_BOT_CTX.unfold(self)) + stack.enter_context(_LOGGER_CTX.unfold(self.logger)) yield stack @asynccontextmanager async def _async_common_ctx(self) -> AsyncGenerator[AsyncExitStack, None]: async with AsyncExitStack() as stack: - stack.enter_context(_BOT_CTX.in_ctx(self)) - stack.enter_context(_LOGGER_CTX.in_ctx(self.logger)) + stack.enter_context(_BOT_CTX.unfold(self)) + stack.enter_context(_LOGGER_CTX.unfold(self.logger)) yield stack def add_input(self, src: AbstractInSource) -> Bot: diff --git a/src/melobot/ctx.py b/src/melobot/ctx.py index 77ef1d10..6a215bbc 100644 --- a/src/melobot/ctx.py +++ b/src/melobot/ctx.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Callable, Generator, Generic, Union, cast from .exceptions import AdapterError, BotError, FlowError, LogError, SessionError -from .typ import T +from .typ import T, deprecated if TYPE_CHECKING: from .adapter import model @@ -89,12 +89,32 @@ def remove(self, token: Token[T]) -> None: """ self.__storage__.reset(token) + @contextmanager + def unfold(self, obj: T) -> Generator[T, None, None]: + """展开一个上下文值为 `obj` 的上下文环境,返回上下文管理器 + + 上下文管理器可 `yield` 上下文值,退出上下文管理器作用域后自动清理 + + :param obj: 上下文值 + """ + token = self.add(obj) + try: + yield obj + finally: + self.remove(token) + + @deprecated("将于 melobot v3.0.0 移除,使用 Context.unfold 方法代替") @contextmanager def in_ctx(self, obj: T) -> Generator[None, None, None]: - """上下文管理器,展开一个上下文值为 `obj` 的上下文环境 + """展开一个上下文值为 `obj` 的上下文环境,返回上下文管理器 退出上下文管理器作用域后自动清理 + .. admonition:: 重要提示 + :class: caution + + 已弃用。将于 `v3.0.0` 移除,使用 :meth:`unfold` 代替 + :param obj: 上下文值 """ token = self.add(obj) diff --git a/src/melobot/handle/process.py b/src/melobot/handle/process.py index 7413f960..afc68545 100644 --- a/src/melobot/handle/process.py +++ b/src/melobot/handle/process.py @@ -52,7 +52,7 @@ async def process(self, event: Event, flow: Flow) -> None: except _FLOW_CTX.lookup_exc_cls: records, store = FlowRecords(), FlowStore() - with _FLOW_CTX.in_ctx(FlowStatus(event, flow, self, True, records, store)): + with _FLOW_CTX.unfold(FlowStatus(event, flow, self, True, records, store)): try: records.append( FlowRecord(RecordStage.NODE_START, flow.name, self.name, event) @@ -264,7 +264,7 @@ async def run(self, event: Event) -> None: except _FLOW_CTX.lookup_exc_cls: records, store = FlowRecords(), FlowStore() - with _FLOW_CTX.in_ctx( + with _FLOW_CTX.unfold( FlowStatus(event, self, self.starts[0], True, records, store) ): try: diff --git a/src/melobot/plugin/load.py b/src/melobot/plugin/load.py index 5eb58d40..9b05821f 100644 --- a/src/melobot/plugin/load.py +++ b/src/melobot/plugin/load.py @@ -147,8 +147,8 @@ def run_init(*plugin_dirs: str | PathLike[str], load_depth: int = 1) -> None: remove(pinit_typ_path) with ExitStack() as ctx_stack: - ctx_stack.enter_context(BotCtx().in_ctx(tmp_bot)) - ctx_stack.enter_context(LoggerCtx().in_ctx(tmp_bot.logger)) + ctx_stack.enter_context(BotCtx().unfold(tmp_bot)) + ctx_stack.enter_context(LoggerCtx().unfold(tmp_bot.logger)) prefix = ".".join(p_dir.parts[-load_depth:]) p_load_mod_name = f"{prefix}.__plugin__" diff --git a/src/melobot/protocols/onebot/v11/adapter/base.py b/src/melobot/protocols/onebot/v11/adapter/base.py index b0d68a56..74892f30 100644 --- a/src/melobot/protocols/onebot/v11/adapter/base.py +++ b/src/melobot/protocols/onebot/v11/adapter/base.py @@ -75,7 +75,7 @@ def with_echo( async def wrapped_api( *args: P.args, **kwargs: P.kwargs ) -> tuple[ActionHandle[EchoT], ...]: - with EchoRequireCtx().in_ctx(True): + with EchoRequireCtx().unfold(True): handles = await func(*args, **kwargs) return cast(tuple[ActionHandle[EchoT], ...], handles) diff --git a/src/melobot/protocols/onebot/v11/handle.py b/src/melobot/protocols/onebot/v11/handle.py index 2ee01c0f..a19f985a 100644 --- a/src/melobot/protocols/onebot/v11/handle.py +++ b/src/melobot/protocols/onebot/v11/handle.py @@ -34,7 +34,10 @@ def GetParseArgs() -> ParseArgs: # pylint: disable=invalid-name def Args() -> ParseArgs: # pylint: disable=invalid-name """获取解析参数,与 :func:`~.v11.handle.GetParseArgs` 等价 - 已弃用。将于 `v3.0.0` 移除,使用 :func:`~.v11.handle.GetParseArgs` 代替 + .. admonition:: 重要提示 + :class: caution + + 已弃用。将于 `v3.0.0` 移除,使用 :func:`~.v11.handle.GetParseArgs` 代替 :return: 解析参数 """ @@ -82,7 +85,7 @@ async def wrapped() -> bool | None: p_args = parse_args event.spread = not block - with ParseArgsCtx().in_ctx(p_args): + with ParseArgsCtx().unfold(p_args): return await func() n = no_deps_node(wrapped) diff --git a/src/melobot/session/base.py b/src/melobot/session/base.py index 8f4377a1..70f1405b 100644 --- a/src/melobot/session/base.py +++ b/src/melobot/session/base.py @@ -227,7 +227,7 @@ async def enter_ctx( if session is None: await stop() - with _SESSION_CTX.in_ctx(session): + with _SESSION_CTX.unfold(session): try: yield session except asyncio.CancelledError: diff --git a/src/melobot/typ.py b/src/melobot/typ.py index 0bcbf47a..a7b27280 100644 --- a/src/melobot/typ.py +++ b/src/melobot/typ.py @@ -318,7 +318,7 @@ def decorator(func: Callable[P, T]) -> Callable[P, T]: @wraps(func) def deprecate_wrapped(*args: P.args, **kwargs: P.kwargs) -> T: warnings.warn( - f"调用了弃用函数 {func.__qualname__}: {msg}", + f"使用了弃用函数/方法 {func.__qualname__}: {msg}", category=DeprecationWarning, stacklevel=2, ) diff --git a/tests/onebot/v11/test_io_duplex_http.py b/tests/onebot/v11/test_io_duplex_http.py index 5efa6059..8bbacff5 100644 --- a/tests/onebot/v11/test_io_duplex_http.py +++ b/tests/onebot/v11/test_io_duplex_http.py @@ -70,7 +70,7 @@ async def close(self): async def test_http(monkeypatch) -> None: - with LoggerCtx().in_ctx(Logger()): + with LoggerCtx().unfold(Logger()): aiohttp._ClientSession = aiohttp.ClientSession monkeypatch.setattr(aiohttp, "ClientSession", lambda: MockClientSession()) io = HttpIO("localhost", 8080, "localhost", 9090) diff --git a/tests/onebot/v11/test_io_forward.py b/tests/onebot/v11/test_io_forward.py index c8c50c38..9ebb7023 100644 --- a/tests/onebot/v11/test_io_forward.py +++ b/tests/onebot/v11/test_io_forward.py @@ -71,7 +71,7 @@ async def wait_closed(self) -> None: async def test_forward_ws(monkeypatch) -> None: - with LoggerCtx().in_ctx(Logger()): + with LoggerCtx().unfold(Logger()): monkeypatch.setattr(websockets, "connect", MockWebsocket.get) io = ForwardWebSocketIO("ws://example.com", max_retry=3, retry_delay=1) async with io: diff --git a/tests/onebot/v11/test_io_reverse.py b/tests/onebot/v11/test_io_reverse.py index 84b4c786..99bf7801 100644 --- a/tests/onebot/v11/test_io_reverse.py +++ b/tests/onebot/v11/test_io_reverse.py @@ -76,7 +76,7 @@ async def wait_closed(self) -> None: async def test_reverse_ws(monkeypatch) -> None: - with LoggerCtx().in_ctx(Logger()): + with LoggerCtx().unfold(Logger()): monkeypatch.setattr(websockets, "serve", MockWebsocket.get) io = ReverseWebSocketIO("localhost", 8080) async with io: diff --git a/tests/onebot/v11/test_utils_parse.py b/tests/onebot/v11/test_utils_parse.py index 246016b1..06c8ebf6 100644 --- a/tests/onebot/v11/test_utils_parse.py +++ b/tests/onebot/v11/test_utils_parse.py @@ -24,7 +24,7 @@ async def test_parser(): assert (await p2.parse(".test#asdjf;a#")).vals == ["asdjf;a"] assert (await p2.parse(".echo#")).vals == [] - with LoggerCtx().in_ctx(Logger()): + with LoggerCtx().unfold(Logger()): p3 = pf1.get( ["test", "echo"], [