melobot.plugin.base 源代码

from __future__ import annotations

from dataclasses import dataclass
from enum import Enum
from pathlib import Path

from typing_extensions import Callable, final, overload

from ..exceptions import PluginLoadError
from ..handle.base import Flow
from ..mixin import HookMixin
from ..typ.base import P, T
from .ipc import AsyncShare, SyncShare


[文档] class PluginLifeSpan(Enum): """插件生命周期的枚举""" INITED = "i"
[文档] @dataclass(frozen=True) class PluginInfo: """插件信息类,用于添加描述信息""" desc: str = "" docs: Path | None = None keywords: list[str] | None = None url: str = "" author: str = ""
[文档] class PluginPlanner(HookMixin[PluginLifeSpan]): """插件管理器类 用于声明一个插件,并为插件添加功能 """
[文档] def __init__( self, version: str, flows: list[Flow] | None = None, shares: list[SyncShare | AsyncShare] | None = None, funcs: list[Callable] | None = None, *, info: PluginInfo | None = None, ) -> None: """插件管理器初始化 :param version: 版本号 :param flows: 事件流列表。可以先指定为空,后续使用 :meth:`use` 绑定 :param shares: 共享对象列表。可以先指定为空,后续使用 :meth:`use` 绑定 :param funcs: 导出函数列表。可以先指定为空,后续使用 :meth:`use` 绑定 :param info: 插件信息 """ super().__init__(hook_type=PluginLifeSpan) self.version = version self.init_flows = [] if flows is None else flows self.shares = [] if shares is None else shares self.funcs = [] if funcs is None else funcs self.info = PluginInfo() if info is None else info self._pname: str = "" self._built: bool = False self._plugin: Plugin
@final def __p_build__(self, name: str) -> Plugin: if not self._built: self._pname = name self._hook_bus.set_tag(name) self._plugin = Plugin(self) self._built = True return self._plugin @overload def use(self, obj: Flow) -> Flow: ... @overload def use(self, obj: SyncShare[T]) -> SyncShare[T]: ... # type: ignore[overload-overlap] @overload def use(self, obj: AsyncShare[T]) -> AsyncShare[T]: ... # type: ignore[overload-overlap] @overload def use(self, obj: Callable[P, T]) -> Callable[P, T]: ...
[文档] @final def use(self, obj: T) -> T: """装饰器 绑定一个组件(流,共享对象,导出函数),标记插件创建后使用该组件。 :param obj: 可用的组件 :return: 被绑定的组件本身 """ if isinstance(obj, Flow): self.init_flows.append(obj) elif isinstance(obj, (SyncShare, AsyncShare)): self.shares.append(obj) elif callable(obj): self.funcs.append(obj) else: raise PluginLoadError(f"插件无法使用 {type(obj)} 类型的对象") return obj
class Plugin: def __init__(self, planner: PluginPlanner) -> None: self.planner = planner self.name = planner._pname self.hook_bus = planner._hook_bus self.shares = planner.shares self.funcs = planner.funcs self.init_flows = planner.init_flows