2022-01-26 15:37:35 +08:00
|
|
|
import sys
|
2022-08-31 10:07:14 +08:00
|
|
|
from pathlib import Path
|
2024-10-26 15:36:01 +08:00
|
|
|
from functools import wraps
|
2022-06-20 15:49:53 +08:00
|
|
|
from dataclasses import asdict
|
2024-10-26 15:36:01 +08:00
|
|
|
from typing import TypeVar, Callable
|
|
|
|
from typing_extensions import ParamSpec
|
2022-01-26 15:37:35 +08:00
|
|
|
|
|
|
|
import pytest
|
|
|
|
|
2023-02-22 23:32:48 +08:00
|
|
|
import nonebot
|
2024-10-26 15:36:01 +08:00
|
|
|
from nonebot.plugin import (
|
|
|
|
Plugin,
|
|
|
|
PluginManager,
|
|
|
|
_plugins,
|
|
|
|
_managers,
|
|
|
|
inherit_supported_adapters,
|
|
|
|
)
|
|
|
|
|
|
|
|
P = ParamSpec("P")
|
|
|
|
R = TypeVar("R")
|
|
|
|
|
|
|
|
|
|
|
|
def _recover(func: Callable[P, R]) -> Callable[P, R]:
|
|
|
|
|
|
|
|
@wraps(func)
|
|
|
|
def _wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
|
|
|
|
origin_managers = _managers.copy()
|
|
|
|
origin_plugins = _plugins.copy()
|
|
|
|
try:
|
|
|
|
return func(*args, **kwargs)
|
|
|
|
finally:
|
|
|
|
_managers.clear()
|
|
|
|
_managers.extend(origin_managers)
|
|
|
|
_plugins.clear()
|
|
|
|
_plugins.update(origin_plugins)
|
|
|
|
|
|
|
|
return _wrapper
|
2022-01-26 15:37:35 +08:00
|
|
|
|
|
|
|
|
2024-10-26 15:36:01 +08:00
|
|
|
@_recover
|
|
|
|
def test_load_plugin():
|
2022-08-31 10:07:14 +08:00
|
|
|
# check regular
|
2023-02-22 23:32:48 +08:00
|
|
|
assert nonebot.load_plugin("dynamic.simple")
|
2022-08-31 10:07:14 +08:00
|
|
|
|
|
|
|
# check path
|
2023-02-22 23:32:48 +08:00
|
|
|
assert nonebot.load_plugin(Path("dynamic/path.py"))
|
2022-08-31 10:07:14 +08:00
|
|
|
|
|
|
|
# check not found
|
|
|
|
assert nonebot.load_plugin("some_plugin_not_exist") is None
|
|
|
|
|
|
|
|
|
2024-10-26 15:36:01 +08:00
|
|
|
def test_load_plugins(load_plugin: set[Plugin], load_builtin_plugin: set[Plugin]):
|
2022-05-26 16:35:47 +08:00
|
|
|
loaded_plugins = {
|
2022-01-26 15:37:35 +08:00
|
|
|
plugin for plugin in nonebot.get_loaded_plugins() if not plugin.parent_plugin
|
2022-05-26 16:35:47 +08:00
|
|
|
}
|
2023-05-30 15:20:31 +08:00
|
|
|
assert loaded_plugins >= load_plugin | load_builtin_plugin
|
2022-05-26 16:35:47 +08:00
|
|
|
|
|
|
|
# check simple plugin
|
2022-01-26 15:37:35 +08:00
|
|
|
assert "plugins.export" in sys.modules
|
2024-04-20 14:47:12 +08:00
|
|
|
assert "plugin._hidden" not in sys.modules
|
2022-01-26 15:37:35 +08:00
|
|
|
|
2022-05-26 16:35:47 +08:00
|
|
|
# check sub plugin
|
2024-04-20 14:47:12 +08:00
|
|
|
plugin = nonebot.get_plugin("nested:nested_subplugin")
|
2022-05-27 11:25:51 +08:00
|
|
|
assert plugin
|
2022-05-26 16:35:47 +08:00
|
|
|
assert "plugins.nested.plugins.nested_subplugin" in sys.modules
|
2024-04-20 14:47:12 +08:00
|
|
|
assert plugin.parent_plugin is nonebot.get_plugin("nested")
|
2022-05-26 16:35:47 +08:00
|
|
|
|
|
|
|
# check load again
|
|
|
|
with pytest.raises(RuntimeError):
|
|
|
|
PluginManager(plugins=["plugins.export"]).load_all_plugins()
|
|
|
|
with pytest.raises(RuntimeError):
|
|
|
|
PluginManager(search_path=["plugins"]).load_all_plugins()
|
2022-01-26 15:37:35 +08:00
|
|
|
|
|
|
|
|
2024-10-26 15:36:01 +08:00
|
|
|
def test_load_nested_plugin():
|
2022-08-04 13:39:20 +08:00
|
|
|
parent_plugin = nonebot.get_plugin("nested")
|
2024-04-20 14:47:12 +08:00
|
|
|
sub_plugin = nonebot.get_plugin("nested:nested_subplugin")
|
|
|
|
sub_plugin2 = nonebot.get_plugin("nested:nested_subplugin2")
|
2023-06-24 14:47:35 +08:00
|
|
|
assert parent_plugin
|
|
|
|
assert sub_plugin
|
|
|
|
assert sub_plugin2
|
2022-08-04 13:39:20 +08:00
|
|
|
assert sub_plugin.parent_plugin is parent_plugin
|
|
|
|
assert sub_plugin2.parent_plugin is parent_plugin
|
|
|
|
assert parent_plugin.sub_plugins == {sub_plugin, sub_plugin2}
|
|
|
|
|
|
|
|
|
2024-10-26 15:36:01 +08:00
|
|
|
@_recover
|
|
|
|
def test_load_json():
|
2022-08-16 10:03:37 +08:00
|
|
|
nonebot.load_from_json("./plugins.json")
|
|
|
|
|
|
|
|
with pytest.raises(TypeError):
|
|
|
|
nonebot.load_from_json("./plugins.invalid.json")
|
|
|
|
|
|
|
|
|
2024-10-26 15:36:01 +08:00
|
|
|
@_recover
|
|
|
|
def test_load_toml():
|
2022-08-16 10:03:37 +08:00
|
|
|
nonebot.load_from_toml("./plugins.toml")
|
|
|
|
|
2023-06-24 14:47:35 +08:00
|
|
|
with pytest.raises(ValueError, match="Cannot find"):
|
2022-08-16 10:03:37 +08:00
|
|
|
nonebot.load_from_toml("./plugins.empty.toml")
|
|
|
|
|
|
|
|
with pytest.raises(TypeError):
|
|
|
|
nonebot.load_from_toml("./plugins.invalid.toml")
|
|
|
|
|
|
|
|
|
2024-10-26 15:36:01 +08:00
|
|
|
@_recover
|
|
|
|
def test_bad_plugin():
|
2022-05-26 16:35:47 +08:00
|
|
|
nonebot.load_plugins("bad_plugins")
|
|
|
|
|
2023-10-31 17:26:06 +08:00
|
|
|
assert nonebot.get_plugin("bad_plugin") is None
|
2022-05-26 16:35:47 +08:00
|
|
|
|
|
|
|
|
2024-10-26 15:36:01 +08:00
|
|
|
@_recover
|
|
|
|
def test_require_loaded(monkeypatch: pytest.MonkeyPatch):
|
2022-01-26 15:37:35 +08:00
|
|
|
def _patched_find(name: str):
|
2023-02-22 23:32:48 +08:00
|
|
|
pytest.fail("require existing plugin should not call find_manager_by_name")
|
2022-01-26 15:37:35 +08:00
|
|
|
|
2024-10-26 15:36:01 +08:00
|
|
|
with monkeypatch.context() as m:
|
|
|
|
m.setattr("nonebot.plugin.load._find_manager_by_name", _patched_find)
|
2022-01-26 15:37:35 +08:00
|
|
|
|
2024-10-26 15:36:01 +08:00
|
|
|
# require use module name
|
|
|
|
nonebot.require("plugins.export")
|
|
|
|
# require use plugin id
|
|
|
|
nonebot.require("export")
|
|
|
|
nonebot.require("nested:nested_subplugin")
|
2022-01-26 15:37:35 +08:00
|
|
|
|
|
|
|
|
2024-10-26 15:36:01 +08:00
|
|
|
@_recover
|
|
|
|
def test_require_not_loaded(monkeypatch: pytest.MonkeyPatch):
|
|
|
|
pm = PluginManager(["dynamic.require_not_loaded"], ["dynamic/require_not_loaded/"])
|
|
|
|
_managers.append(pm)
|
2023-02-22 23:32:48 +08:00
|
|
|
num_managers = len(_managers)
|
2022-01-26 15:37:35 +08:00
|
|
|
|
|
|
|
origin_load = PluginManager.load_plugin
|
|
|
|
|
|
|
|
def _patched_load(self: PluginManager, name: str):
|
2024-10-26 15:36:01 +08:00
|
|
|
assert self is pm
|
2022-01-26 15:37:35 +08:00
|
|
|
return origin_load(self, name)
|
|
|
|
|
2024-10-26 15:36:01 +08:00
|
|
|
with monkeypatch.context() as m:
|
|
|
|
m.setattr(PluginManager, "load_plugin", _patched_load)
|
2022-01-26 15:37:35 +08:00
|
|
|
|
2024-10-26 15:36:01 +08:00
|
|
|
# require standalone plugin
|
|
|
|
nonebot.require("dynamic.require_not_loaded")
|
|
|
|
# require searched plugin
|
|
|
|
nonebot.require("dynamic.require_not_loaded.subplugin1")
|
|
|
|
nonebot.require("require_not_loaded:subplugin2")
|
2022-01-26 15:37:35 +08:00
|
|
|
|
2023-02-22 23:32:48 +08:00
|
|
|
assert len(_managers) == num_managers
|
2022-01-26 15:37:35 +08:00
|
|
|
|
|
|
|
|
2024-10-26 15:36:01 +08:00
|
|
|
@_recover
|
|
|
|
def test_require_not_declared():
|
2023-02-22 23:32:48 +08:00
|
|
|
num_managers = len(_managers)
|
2022-01-26 15:37:35 +08:00
|
|
|
|
2023-02-22 23:32:48 +08:00
|
|
|
nonebot.require("dynamic.require_not_declared")
|
2022-01-26 15:37:35 +08:00
|
|
|
|
2023-02-22 23:32:48 +08:00
|
|
|
assert len(_managers) == num_managers + 1
|
|
|
|
assert _managers[-1].plugins == {"dynamic.require_not_declared"}
|
2022-01-26 15:37:35 +08:00
|
|
|
|
|
|
|
|
2024-10-26 15:36:01 +08:00
|
|
|
@_recover
|
|
|
|
def test_require_not_found():
|
2022-05-26 16:35:47 +08:00
|
|
|
with pytest.raises(RuntimeError):
|
2022-01-26 15:37:35 +08:00
|
|
|
nonebot.require("some_plugin_not_exist")
|
2022-06-20 15:49:53 +08:00
|
|
|
|
|
|
|
|
2024-10-26 15:36:01 +08:00
|
|
|
def test_plugin_metadata():
|
2023-05-18 16:00:10 +08:00
|
|
|
from plugins.metadata import Config, FakeAdapter
|
2022-06-20 15:49:53 +08:00
|
|
|
|
|
|
|
plugin = nonebot.get_plugin("metadata")
|
|
|
|
assert plugin
|
|
|
|
assert plugin.metadata
|
|
|
|
assert asdict(plugin.metadata) == {
|
|
|
|
"name": "测试插件",
|
|
|
|
"description": "测试插件元信息",
|
|
|
|
"usage": "无法使用",
|
2023-05-18 16:00:10 +08:00
|
|
|
"type": "application",
|
2023-06-01 14:18:16 +08:00
|
|
|
"homepage": "https://nonebot.dev",
|
2022-06-20 15:49:53 +08:00
|
|
|
"config": Config,
|
2023-05-18 16:00:10 +08:00
|
|
|
"supported_adapters": {"~onebot.v11", "plugins.metadata:FakeAdapter"},
|
2022-06-20 15:49:53 +08:00
|
|
|
"extra": {"author": "NoneBot"},
|
|
|
|
}
|
2023-05-18 16:00:10 +08:00
|
|
|
|
|
|
|
assert plugin.metadata.get_supported_adapters() == {FakeAdapter}
|
2023-06-27 16:25:27 +08:00
|
|
|
|
|
|
|
|
2024-10-26 15:36:01 +08:00
|
|
|
def test_inherit_supported_adapters_not_found():
|
2023-06-27 16:25:27 +08:00
|
|
|
with pytest.raises(RuntimeError):
|
|
|
|
inherit_supported_adapters("some_plugin_not_exist")
|
|
|
|
|
|
|
|
with pytest.raises(ValueError, match="has no metadata!"):
|
|
|
|
inherit_supported_adapters("export")
|
|
|
|
|
|
|
|
|
2024-04-18 18:50:11 +08:00
|
|
|
@pytest.mark.parametrize(
|
|
|
|
("inherit_plugins", "expected"),
|
|
|
|
[
|
|
|
|
(("echo",), None),
|
|
|
|
(
|
|
|
|
("metadata",),
|
|
|
|
{
|
|
|
|
"nonebot.adapters.onebot.v11",
|
|
|
|
"plugins.metadata:FakeAdapter",
|
|
|
|
},
|
|
|
|
),
|
|
|
|
(
|
|
|
|
("metadata_2",),
|
|
|
|
{
|
|
|
|
"nonebot.adapters.onebot.v11",
|
|
|
|
"nonebot.adapters.onebot.v12",
|
|
|
|
},
|
|
|
|
),
|
|
|
|
(
|
|
|
|
("metadata_3",),
|
|
|
|
{
|
|
|
|
"nonebot.adapters.onebot.v11",
|
|
|
|
"nonebot.adapters.onebot.v12",
|
|
|
|
"nonebot.adapters.qq",
|
|
|
|
},
|
|
|
|
),
|
|
|
|
(
|
|
|
|
("metadata", "metadata_2"),
|
|
|
|
{
|
|
|
|
"nonebot.adapters.onebot.v11",
|
|
|
|
},
|
|
|
|
),
|
|
|
|
(
|
|
|
|
("metadata", "metadata_3"),
|
|
|
|
{
|
|
|
|
"nonebot.adapters.onebot.v11",
|
|
|
|
},
|
|
|
|
),
|
|
|
|
(
|
|
|
|
("metadata_2", "metadata_3"),
|
|
|
|
{
|
|
|
|
"nonebot.adapters.onebot.v11",
|
|
|
|
"nonebot.adapters.onebot.v12",
|
|
|
|
},
|
|
|
|
),
|
|
|
|
(
|
|
|
|
("metadata", "metadata_2", "metadata_3"),
|
|
|
|
{
|
|
|
|
"nonebot.adapters.onebot.v11",
|
|
|
|
},
|
|
|
|
),
|
|
|
|
(
|
|
|
|
("metadata", "echo"),
|
|
|
|
{
|
|
|
|
"nonebot.adapters.onebot.v11",
|
|
|
|
"plugins.metadata:FakeAdapter",
|
|
|
|
},
|
|
|
|
),
|
|
|
|
(
|
|
|
|
("metadata", "metadata_2", "echo"),
|
|
|
|
{
|
|
|
|
"nonebot.adapters.onebot.v11",
|
|
|
|
},
|
|
|
|
),
|
|
|
|
],
|
|
|
|
)
|
2024-10-26 15:36:01 +08:00
|
|
|
def test_inherit_supported_adapters_combine(
|
2024-04-18 18:50:11 +08:00
|
|
|
inherit_plugins: tuple[str], expected: set[str]
|
|
|
|
):
|
|
|
|
assert inherit_supported_adapters(*inherit_plugins) == expected
|