Skip to content

Commit

Permalink
[melobot] Prepare release for v3.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
aicorein committed Dec 16, 2024
1 parent 412767d commit ec518f5
Show file tree
Hide file tree
Showing 9 changed files with 16 additions and 184 deletions.
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

## 🔄 工作计划

melobot v3 pre-release 已发布。v3 支持各种协议以扩展至各种平台提供机器人服务。
melobot v3 现已发布。支持各种协议以扩展至各种平台提供机器人服务。

v3 目前可用的协议实现:

Expand Down Expand Up @@ -57,11 +57,11 @@ melobot v3 是跨平台、跨协议、支持多路 IO 及其他高级特性的 b
| 实用接口 | 封装高频使用的异步逻辑,使业务开发更简洁 |
| 插件管理 | 低耦合度、无序的插件加载与通信 |
| 处理流设计 | 可自由组合“处理中间件”为处理流,提升了各组件的复用率 |
| 热插拔/重启 | 事件处理器支持动态热插拔,支持 bot 级别的重启 |
| 热插拔/重启 | 处理流支持动态热插拔,支持 bot 级别的重启 |
| 会话支持 | 可在处理流中自动传递的、可自定义的会话上下文 |
| 协议支持 | 所有协议被描述为 IO 过程,因此支持各类协议 |
| 跨平台 | 更简洁的跨平台接口,便捷实现跨平台插件开发 |
| 多路 IO | 支持多个协议实现端同时输入,自由输出到指定协议实现端 |
| 跨协议 IO | 支持多个协议实现端同时输入,自由输出到指定协议实现端 |
| 日志支持 | 日志记录兼容标准库和绝大多数日志框架,可自行选择 |


Expand All @@ -83,13 +83,13 @@ melobot v3 是跨平台、跨协议、支持多路 IO 及其他高级特性的 b

> Python 版本需求:>= 3.10
如果您对 melobot 完全不熟悉,建议配合文档开始学习。文档以 OneBot v11 协议为例,通过以下命令安装所有必要的组件
如果您对 melobot 完全不熟悉,建议配合文档开始学习。文档以 OneBot v11 协议为例,通过以下命令安装文档教程中必需的组件

```shell
pip install 'melobot[onebot]>=3.0.0rc13'
pip install melobot[onebot]
```

如果您对 melobot 已经十分了解,请自由地安装核心+任何可选依赖。
如果您对 melobot 已经十分了解,请自由地安装核心 + 任何可选依赖。

也可以通过源码构建:(对于普通用户不推荐)

Expand Down
7 changes: 0 additions & 7 deletions docs/source/api/melobot.plugin.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,6 @@ melobot.plugin
:members:
:exclude-members: version, desc, docs, keywords, url, author

.. autoclass:: melobot.plugin.Plugin
:members:

.. autoclass:: melobot.plugin.LegacyPlugin
:members:
:exclude-members: __init__

.. autoclass:: melobot.plugin.PluginLifeSpan
:members:

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ readme = "README.md"
license = {text = "BSD"}
keywords = ["melobot", "bot framework", "asyncio", "coroutine", "concurrency"]
classifiers = [
"Development Status :: 4 - Beta",
"Development Status :: 5 - Production/Stable",
"Environment :: Console",
"Intended Audience :: Developers",
"License :: OSI Approved :: BSD License",
Expand Down
11 changes: 1 addition & 10 deletions src/melobot/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,6 @@
from .di import Depends
from .handle import Flow, FlowStore, node, rewind, stop
from .log import GenericLogger, Logger, LogLevel, get_logger

# REMOVE: 3.0.0 (Plugin)
from .plugin import (
AsyncShare,
Plugin,
PluginInfo,
PluginLifeSpan,
PluginPlanner,
SyncShare,
)
from .plugin import AsyncShare, PluginInfo, PluginLifeSpan, PluginPlanner, SyncShare
from .session import Rule, SessionStore, enter_session, suspend
from .typ import HandleLevel, LogicMode
23 changes: 1 addition & 22 deletions src/melobot/ctx.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from typing_extensions import TYPE_CHECKING, Any, Callable, Generator, Generic, Union

from .exceptions import AdapterError, BotError, FlowError, LogError, SessionError
from .typ import SingletonMeta, T, deprecated
from .typ import SingletonMeta, T

if TYPE_CHECKING:
from .adapter import model
Expand Down Expand Up @@ -93,27 +93,6 @@ def unfold(self, obj: T) -> Generator[T, None, None]:
finally:
self.remove(token)

# REMOVE: 3.0.0
@deprecated("将于 melobot v3.0.0 移除,使用 unfold 方法代替")
@contextmanager
def in_ctx(self, obj: T) -> Generator[None, None, None]:
"""展开一个上下文值为 `obj` 的上下文环境,返回上下文管理器
退出上下文管理器作用域后自动清理
.. admonition:: 重要提示
:class: caution
已弃用。将于 `v3.0.0` 移除,使用 :meth:`unfold` 代替
:param obj: 上下文值
"""
token = self.add(obj)
try:
yield
finally:
self.remove(token)


_OutSrcFilterType = Callable[["OutSourceT"], bool]

Expand Down
4 changes: 0 additions & 4 deletions src/melobot/plugin/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,2 @@
# pylint: disable=reimported
# REMOVE: 3.0.0
from .base import LegacyPlugin
from .base import LegacyPlugin as Plugin
from .base import PluginInfo, PluginLifeSpan, PluginPlanner
from .ipc import AsyncShare, SyncShare
85 changes: 2 additions & 83 deletions src/melobot/plugin/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,14 @@
from enum import Enum
from pathlib import Path

from typing_extensions import Iterable, final, overload
from typing_extensions import final, overload

from .._hook import HookBus
from ..ctx import BotCtx
from ..exceptions import PluginLoadError
from ..handle.base import EventHandler
from ..handle.process import Flow
from ..typ import (
AsyncCallable,
Callable,
P,
SingletonBetterABCMeta,
T,
abstractattr,
deprecate_warn,
)
from ..typ import AsyncCallable, Callable, P, T
from ..utils import to_async
from .ipc import AsyncShare, SyncShare

Expand Down Expand Up @@ -77,36 +69,6 @@ def __init__(
self._built: bool = False
self._plugin: Plugin

# REMOVE: 3.0.0
@classmethod
def __from_legacy__(cls, legacy: LegacyPlugin) -> PluginPlanner:
deprecate_warn(
"继承 melobot.plugin.Plugin 类声明插件的方式已弃用,将在 3.0.0 移除。"
"实例化 melobot.plugin.PluginPlanner 类来代替。"
f"触发此警告的插件是:{legacy.__class__.__module__}.{legacy.__class__.__name__}"
)
planner = PluginPlanner(
legacy.version,
list(legacy.flows),
list(legacy.shares),
list(legacy.funcs),
info=PluginInfo(
legacy.version,
f"{legacy.desc}\n{legacy.docs}" if legacy.desc != "" else "",
None,
legacy.keywords,
legacy.url,
legacy.author,
),
)
if not hasattr(legacy, "__hook_bus__"):
bus = HookBus[PluginLifeSpan](PluginLifeSpan)
planner._hook_bus = bus
legacy.__class__.__hook_bus__ = bus
else:
planner._hook_bus = legacy.__class__.__hook_bus__
return planner

@final
def on(
self, *periods: PluginLifeSpan
Expand Down Expand Up @@ -226,46 +188,3 @@ def __init__(self, planner: PluginPlanner) -> None:
self.shares = planner.shares
self.funcs = planner.funcs
self.handlers = list(EventHandler(self, f) for f in self.planner.flows)


# REMOVE: 3.0.0
class LegacyPlugin(metaclass=SingletonBetterABCMeta):
"""旧版插件类
.. admonition:: 重要提示
:class: caution
已弃用使用该类声明插件,将于 `v3.0.0` 移除。请使用 :class:`.PluginPlanner` 代替。
"""

version: str = abstractattr()
shares: Iterable[SyncShare | AsyncShare] = ()
funcs: Iterable[Callable] = ()
flows: Iterable[Flow] = ()
desc: str = ""
docs: str = ""
keywords: list[str] = []
url: str = ""
author: str = ""

__hook_bus__: HookBus[PluginLifeSpan]

@classmethod
@final
def on(
cls, *periods: PluginLifeSpan
) -> Callable[[AsyncCallable[P, None]], AsyncCallable[P, None]]:
"""注册一个 hook
:param periods: 要绑定的 hook 类型
:return: 装饰器
"""
if not hasattr(cls, "__hook_bus__"):
cls.__hook_bus__ = HookBus[PluginLifeSpan](PluginLifeSpan)

def wrapped(func: AsyncCallable[P, None]) -> AsyncCallable[P, None]:
for type in periods:
cls.__hook_bus__.register(type, func)
return func

return wrapped
37 changes: 4 additions & 33 deletions src/melobot/plugin/load.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@
from ..ctx import BotCtx, LoggerCtx
from ..exceptions import PluginAutoGenError, PluginLoadError
from ..utils import singleton

# REMOVE: 3.0.0 (LegacyPlugin)
from .base import LegacyPlugin, Plugin, PluginPlanner
from .base import Plugin, PluginPlanner
from .ipc import AsyncShare, SyncShare


Expand Down Expand Up @@ -184,23 +182,12 @@ def run_init(*plugin_dirs: str | PathLike[str], load_depth: int = 1) -> None:
p_shares = p_planner.shares
p_funcs = p_planner.funcs
break

# REMOVE: 3.0.0
if (
isinstance(val, type)
and issubclass(val, LegacyPlugin)
and val is not LegacyPlugin
):
p_planner = PluginPlanner.__from_legacy__(val())
p_shares = p_planner.shares
p_funcs = p_planner.funcs
break
# REMOVE END ##########
else:
raise PluginAutoGenError(
f"插件的 __plugin__.py 未实例化 {PluginPlanner.__name__} 类,"
f"无法解析。对应插件:{p_dir}"
)

for share in p_shares:
if share.name in p_conflicts:
raise PluginAutoGenError(
Expand Down Expand Up @@ -246,23 +233,13 @@ def _build_plugin(
self, p_name: str, entry: ModuleType | None, p_planner: PluginPlanner | None
) -> tuple[Plugin, bool]:
if p_planner is None:

if not hasattr(entry, P_PLANNER_ATTR):
for k in dir(entry):
val = getattr(entry, k)
if isinstance(val, PluginPlanner):
setattr(entry, P_PLANNER_ATTR, val)
break
# REMOVE: 3.0.0
if (
isinstance(val, type)
and issubclass(val, LegacyPlugin)
and val is not LegacyPlugin
):
setattr(
entry, P_PLANNER_ATTR, PluginPlanner.__from_legacy__(val())
)
break
# REMOVE END ########

else:
entry = cast(ModuleType, entry)
Expand All @@ -278,11 +255,6 @@ def _build_plugin(

p_planner = getattr(entry, P_PLANNER_ATTR)

# REMOVE: 3.0.0
if isinstance(p_planner, LegacyPlugin):
p_planner = PluginPlanner.__from_legacy__(p_planner)
# REMOVE END ########

p_planner = cast(PluginPlanner, p_planner)
if p_planner._built:
p = p_planner._plugin
Expand All @@ -298,8 +270,7 @@ def load(
logger = LoggerCtx().get()
_plugin_repr = repr(plugin)

# REMOVE: 3.0.0
if isinstance(plugin, (PluginPlanner, LegacyPlugin)):
if isinstance(plugin, PluginPlanner):
p_name = f"_DynamicPlugin_0x{id(plugin):0x}"
return self._build_plugin(p_name, entry=None, p_planner=plugin)

Expand Down
19 changes: 1 addition & 18 deletions src/melobot/protocols/onebot/v11/handle.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from melobot.di import Depends, inject_deps
from melobot.handle import Flow, get_event, no_deps_node
from melobot.session import Rule, Session, enter_session
from melobot.typ import AsyncCallable, HandleLevel, LogicMode, deprecated
from melobot.typ import AsyncCallable, HandleLevel, LogicMode
from melobot.utils import get_obj_name

from .adapter.event import Event, MessageEvent, MetaEvent, NoticeEvent, RequestEvent
Expand All @@ -31,23 +31,6 @@ def GetParseArgs() -> ParseArgs: # pylint: disable=invalid-name
return cast(ParseArgs, Depends(ParseArgsCtx().get, recursive=False))


# REMOVE: 3.0.0
@deprecated(
"将于 melobot v3.0.0 移除,使用 melobot.protocols.onebot.v11.handle.GetParseArgs 代替"
)
def Args() -> ParseArgs: # pylint: disable=invalid-name
"""获取解析参数,与 :func:`~.v11.handle.GetParseArgs` 等价
.. admonition:: 重要提示
:class: caution
已弃用。将于 `v3.0.0` 移除,使用 :func:`~.v11.handle.GetParseArgs` 代替
:return: 解析参数
"""
return GetParseArgs()


FlowDecorator = Callable[[AsyncCallable[..., bool | None]], Flow]

_DefaultRule = Rule[MessageEvent].new(lambda e1, e2: e1.scope == e2.scope)
Expand Down

0 comments on commit ec518f5

Please sign in to comment.