From c03ff4e6760e5db3bf31e5c6f16018530e60454e Mon Sep 17 00:00:00 2001 From: worldmozara <37037264+NCBM@users.noreply.github.com> Date: Tue, 27 Jun 2023 16:25:27 +0800 Subject: [PATCH] =?UTF-8?q?:sparkles:=20Feature:=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E7=94=A8=E4=BA=8E=E5=8A=A8=E6=80=81=E7=BB=A7=E6=89=BF=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E9=80=82=E9=85=8D=E5=99=A8=E6=95=B0=E6=8D=AE=E7=9A=84?= =?UTF-8?q?=E6=96=B9=E6=B3=95=20(#2127)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nonebot/plugin/__init__.py | 1 + nonebot/plugin/load.py | 36 ++++++++++++++++++++++++++++++++++ tests/plugins/metadata_2.py | 11 +++++++++++ tests/test_plugin/test_load.py | 34 +++++++++++++++++++++++++++++++- 4 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 tests/plugins/metadata_2.py diff --git a/nonebot/plugin/__init__.py b/nonebot/plugin/__init__.py index b973d378..4f0df882 100644 --- a/nonebot/plugin/__init__.py +++ b/nonebot/plugin/__init__.py @@ -134,3 +134,4 @@ from .plugin import PluginMetadata as PluginMetadata 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 diff --git a/nonebot/plugin/load.py b/nonebot/plugin/load.py index 8e83b1ea..375fb205 100644 --- a/nonebot/plugin/load.py +++ b/nonebot/plugin/load.py @@ -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]]: + """获取已加载插件的适配器支持状态集合。 + + 如果传入了多个插件名称,返回值会自动取交集。 + + 参数: + 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 + } diff --git a/tests/plugins/metadata_2.py b/tests/plugins/metadata_2.py new file mode 100644 index 00000000..8cf4cb00 --- /dev/null +++ b/tests/plugins/metadata_2.py @@ -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"}, +) diff --git a/tests/test_plugin/test_load.py b/tests/test_plugin/test_load.py index fcbf3586..b297deb2 100644 --- a/tests/test_plugin/test_load.py +++ b/tests/test_plugin/test_load.py @@ -6,7 +6,7 @@ from dataclasses import asdict import pytest import nonebot -from nonebot.plugin import Plugin, PluginManager, _managers +from nonebot.plugin import Plugin, PluginManager, _managers, inherit_supported_adapters @pytest.mark.asyncio @@ -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" + }