Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: 添加用于动态继承支持适配器数据的方法 #2127

Merged
merged 4 commits into from
Jun 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions nonebot/plugin/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,3 +134,4 @@ def get_available_plugin_names() -> Set[str]:
from .load import load_all_plugins as load_all_plugins
from .load import load_builtin_plugin as load_builtin_plugin
from .load import load_builtin_plugins as load_builtin_plugins
from .load import inherit_supported_adapters as inherit_supported_adapters
36 changes: 36 additions & 0 deletions nonebot/plugin/load.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,3 +182,39 @@ def require(name: str) -> ModuleType:
if not plugin:
raise RuntimeError(f'Cannot load plugin "{name}"!')
return plugin.module


def inherit_supported_adapters(*names: str) -> Optional[Set[str]]:
NCBM marked this conversation as resolved.
Show resolved Hide resolved
"""获取已加载插件的适配器支持状态集合。

如果传入了多个插件名称,返回值会自动取交集。

参数:
names: 插件名称列表。

异常:
RuntimeError: 插件未加载
ValueError: 插件缺少元数据
"""
final_supported: Optional[Set[str]] = None

for name in names:
plugin = get_plugin(_module_name_to_plugin_name(name))
if plugin is None:
raise RuntimeError(f'Plugin "{name}" is not loaded!')
meta = plugin.metadata
if meta is None:
raise ValueError(f'Plugin "{name}" has no metadata!')
support = meta.supported_adapters
if support is None:
continue
final_supported = (
support if final_supported is None else (final_supported & support)
)

return final_supported and {
f"nonebot.adapters.{adapter_name[1:]}"
if adapter_name.startswith("~")
else adapter_name
for adapter_name in final_supported
}
11 changes: 11 additions & 0 deletions tests/plugins/metadata_2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from nonebot.plugin import PluginMetadata

__plugin_meta__ = PluginMetadata(
name="测试插件2",
description="测试继承适配器",
usage="无法使用",
type="application",
homepage="https://nonebot.dev",
supported_adapters={"~onebot.v11", "~onebot.v12"},
extra={"author": "NoneBot"},
)
34 changes: 33 additions & 1 deletion tests/test_plugin/test_load.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import pytest

import nonebot
from nonebot.plugin import Plugin, PluginManager, _managers
from nonebot.plugin import Plugin, PluginManager, _managers, inherit_supported_adapters


@pytest.mark.asyncio
Expand Down Expand Up @@ -147,3 +147,35 @@ async def test_plugin_metadata():
}

assert plugin.metadata.get_supported_adapters() == {FakeAdapter}


@pytest.mark.asyncio
async def test_inherit_supported_adapters():
with pytest.raises(RuntimeError):
inherit_supported_adapters("some_plugin_not_exist")

with pytest.raises(ValueError, match="has no metadata!"):
inherit_supported_adapters("export")

echo = nonebot.get_plugin("echo")
assert echo
assert echo.metadata
assert inherit_supported_adapters("echo") is None

plugin_1 = nonebot.get_plugin("metadata")
assert plugin_1
assert plugin_1.metadata
assert inherit_supported_adapters("metadata") == {
"nonebot.adapters.onebot.v11",
"plugins.metadata:FakeAdapter",
}

plugin_2 = nonebot.get_plugin("metadata_2")
assert plugin_2
assert plugin_2.metadata
assert inherit_supported_adapters("metadata", "metadata_2") == {
"nonebot.adapters.onebot.v11"
}
assert inherit_supported_adapters("metadata", "echo", "metadata_2") == {
"nonebot.adapters.onebot.v11"
}