nonebot2/tests/test_plugin/test_load.py

265 lines
7.1 KiB
Python
Raw Permalink Normal View History

from dataclasses import asdict
from functools import wraps
from pathlib import Path
import sys
from typing import Callable, TypeVar
from typing_extensions import ParamSpec
2022-01-26 15:37:35 +08:00
import pytest
import nonebot
from nonebot.plugin import (
Plugin,
PluginManager,
_managers,
_plugins,
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
@_recover
def test_load_plugin():
# check regular
assert nonebot.load_plugin("dynamic.simple")
# check path
assert nonebot.load_plugin(Path("dynamic/path.py"))
# check not found
assert nonebot.load_plugin("some_plugin_not_exist") is None
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
}
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
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
plugin = nonebot.get_plugin("nested:nested_subplugin")
assert plugin
2022-05-26 16:35:47 +08:00
assert "plugins.nested.plugins.nested_subplugin" in sys.modules
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
def test_load_nested_plugin():
parent_plugin = nonebot.get_plugin("nested")
sub_plugin = nonebot.get_plugin("nested:nested_subplugin")
sub_plugin2 = nonebot.get_plugin("nested:nested_subplugin2")
assert parent_plugin
assert sub_plugin
assert sub_plugin2
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}
@_recover
def test_load_json():
nonebot.load_from_json("./plugins.json")
with pytest.raises(TypeError):
nonebot.load_from_json("./plugins.invalid.json")
@_recover
def test_load_toml():
nonebot.load_from_toml("./plugins.toml")
with pytest.raises(ValueError, match="Cannot find"):
nonebot.load_from_toml("./plugins.empty.toml")
with pytest.raises(TypeError):
nonebot.load_from_toml("./plugins.invalid.toml")
@_recover
def test_bad_plugin():
2022-05-26 16:35:47 +08:00
nonebot.load_plugins("bad_plugins")
assert nonebot.get_plugin("bad_plugin") is None
2022-05-26 16:35:47 +08:00
@_recover
def test_require_loaded(monkeypatch: pytest.MonkeyPatch):
2022-01-26 15:37:35 +08:00
def _patched_find(name: str):
pytest.fail("require existing plugin should not call find_manager_by_name")
2022-01-26 15:37:35 +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
# 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
@_recover
def test_require_not_loaded(monkeypatch: pytest.MonkeyPatch):
pm = PluginManager(["dynamic.require_not_loaded"], ["dynamic/require_not_loaded/"])
_managers.append(pm)
num_managers = len(_managers)
2022-01-26 15:37:35 +08:00
origin_load = PluginManager.load_plugin
def _patched_load(self: PluginManager, name: str):
assert self is pm
2022-01-26 15:37:35 +08:00
return origin_load(self, name)
with monkeypatch.context() as m:
m.setattr(PluginManager, "load_plugin", _patched_load)
2022-01-26 15:37:35 +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
assert len(_managers) == num_managers
2022-01-26 15:37:35 +08:00
@_recover
def test_require_not_declared():
num_managers = len(_managers)
2022-01-26 15:37:35 +08:00
nonebot.require("dynamic.require_not_declared")
2022-01-26 15:37:35 +08:00
assert len(_managers) == num_managers + 1
assert _managers[-1].plugins == {"dynamic.require_not_declared"}
2022-01-26 15:37:35 +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")
def test_plugin_metadata():
from plugins.metadata import Config, FakeAdapter
plugin = nonebot.get_plugin("metadata")
assert plugin
assert plugin.metadata
assert asdict(plugin.metadata) == {
"name": "测试插件",
"description": "测试插件元信息",
"usage": "无法使用",
"type": "application",
2023-06-01 14:18:16 +08:00
"homepage": "https://nonebot.dev",
"config": Config,
"supported_adapters": {"~onebot.v11", "plugins.metadata:FakeAdapter"},
"extra": {"author": "NoneBot"},
}
assert plugin.metadata.get_supported_adapters() == {FakeAdapter}
def test_inherit_supported_adapters_not_found():
with pytest.raises(RuntimeError):
inherit_supported_adapters("some_plugin_not_exist")
with pytest.raises(ValueError, match="has no metadata!"):
inherit_supported_adapters("export")
@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",
},
),
],
)
def test_inherit_supported_adapters_combine(
inherit_plugins: tuple[str], expected: set[str]
):
assert inherit_supported_adapters(*inherit_plugins) == expected