From 06ee47edcd246408bc315ba6a239486d3d439dfa Mon Sep 17 00:00:00 2001 From: Ju4tCode <42488585+yanyongyu@users.noreply.github.com> Date: Mon, 20 Jun 2022 15:49:53 +0800 Subject: [PATCH] =?UTF-8?q?:sparkles:=20Feature:=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E6=8F=92=E4=BB=B6=E5=85=83=E4=BF=A1=E6=81=AF=E5=AE=9A=E4=B9=89?= =?UTF-8?q?=20(#1046)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nonebot/plugin/__init__.py | 1 + nonebot/plugin/manager.py | 6 +++++- nonebot/plugin/plugin.py | 24 +++++++++++++++++++++--- tests/plugins/metadata.py | 16 ++++++++++++++++ tests/test_plugin/test_load.py | 18 ++++++++++++++++++ 5 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 tests/plugins/metadata.py diff --git a/nonebot/plugin/__init__.py b/nonebot/plugin/__init__.py index 6358a884..52b65e07 100644 --- a/nonebot/plugin/__init__.py +++ b/nonebot/plugin/__init__.py @@ -129,6 +129,7 @@ from .on import on_startswith as on_startswith from .load import load_from_json as load_from_json from .load import load_from_toml as load_from_toml from .on import on_shell_command as on_shell_command +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 diff --git a/nonebot/plugin/manager.py b/nonebot/plugin/manager.py index 4b85111a..b136f27d 100644 --- a/nonebot/plugin/manager.py +++ b/nonebot/plugin/manager.py @@ -19,7 +19,7 @@ from typing import Set, Dict, List, Union, Iterable, Optional, Sequence from nonebot.log import logger from nonebot.utils import escape_tag -from .plugin import Plugin +from .plugin import Plugin, PluginMetadata from . import ( _managers, _new_plugin, @@ -242,6 +242,10 @@ class PluginLoader(SourceFileLoader): # leave plugin context _current_plugin.reset(_plugin_token) + # get plugin metadata + metadata: Optional[PluginMetadata] = getattr(module, "__plugin_meta__", None) + plugin.metadata = metadata + return diff --git a/nonebot/plugin/plugin.py b/nonebot/plugin/plugin.py index 658c073b..a55061fc 100644 --- a/nonebot/plugin/plugin.py +++ b/nonebot/plugin/plugin.py @@ -6,7 +6,9 @@ FrontMatter: """ from types import ModuleType from dataclasses import field, dataclass -from typing import TYPE_CHECKING, Set, Type, Optional +from typing import TYPE_CHECKING, Any, Set, Dict, Type, Optional + +from pydantic import BaseModel from nonebot.matcher import Matcher @@ -18,11 +20,26 @@ if TYPE_CHECKING: @dataclass(eq=False) -class Plugin(object): +class PluginMetadata: + """插件元信息,由插件编写者提供""" + + name: str + """插件可阅读名称""" + description: str + """插件功能介绍""" + usage: str + """插件使用方法""" + config: Optional[Type[BaseModel]] = None + """插件配置项""" + extra: Dict[Any, Any] = field(default_factory=dict) + + +@dataclass(eq=False) +class Plugin: """存储插件信息""" name: str - """插件名称,使用 文件/文件夹 名称作为插件名""" + """插件索引标识,NoneBot 使用 文件/文件夹 名称作为标识符""" module: ModuleType """插件模块对象""" module_name: str @@ -37,3 +54,4 @@ class Plugin(object): """父插件""" sub_plugins: Set["Plugin"] = field(default_factory=set) """子插件集合""" + metadata: Optional[PluginMetadata] = None diff --git a/tests/plugins/metadata.py b/tests/plugins/metadata.py new file mode 100644 index 00000000..4c775dc6 --- /dev/null +++ b/tests/plugins/metadata.py @@ -0,0 +1,16 @@ +from pydantic import BaseModel + +from nonebot.plugin import PluginMetadata + + +class Config(BaseModel): + custom: str = "" + + +__plugin_meta__ = PluginMetadata( + name="测试插件", + description="测试插件元信息", + usage="无法使用", + config=Config, + extra={"author": "NoneBot"}, +) diff --git a/tests/test_plugin/test_load.py b/tests/test_plugin/test_load.py index 080d053c..a99852ec 100644 --- a/tests/test_plugin/test_load.py +++ b/tests/test_plugin/test_load.py @@ -1,4 +1,5 @@ import sys +from dataclasses import asdict from typing import TYPE_CHECKING, Set import pytest @@ -98,3 +99,20 @@ async def test_require_not_found(app: App): with pytest.raises(RuntimeError): nonebot.require("some_plugin_not_exist") + + +@pytest.mark.asyncio +async def test_plugin_metadata(app: App, load_plugin: Set["Plugin"]): + import nonebot + from plugins.metadata import Config + + plugin = nonebot.get_plugin("metadata") + assert plugin + assert plugin.metadata + assert asdict(plugin.metadata) == { + "name": "测试插件", + "description": "测试插件元信息", + "usage": "无法使用", + "config": Config, + "extra": {"author": "NoneBot"}, + }