♻️ remove plugin namespace

This commit is contained in:
yanyongyu 2021-11-11 17:33:30 +08:00
parent 08f56db385
commit 2ccbc93e48
9 changed files with 210 additions and 204 deletions

View File

@ -37,7 +37,7 @@ from nonebot.adapters import Bot
from nonebot.utils import escape_tag
from nonebot.config import Env, Config
from nonebot.log import logger, default_filter
from nonebot.drivers import Driver, ForwardDriver, ReverseDriver
from nonebot.drivers import Driver, ReverseDriver
try:
_dist: pkg_resources.Distribution = pkg_resources.get_distribution(

View File

@ -5,14 +5,36 @@
NoneBot 插件开发提供便携的定义函数
"""
from typing import Optional
from typing import List, Optional
from contextvars import ContextVar
_managers: List["PluginManager"] = []
_current_plugin: ContextVar[Optional["Plugin"]] = ContextVar("_current_plugin",
default=None)
from .on import on as on
from .manager import PluginManager
from .export import Export as Export
from .export import export as export
from .load import require as require
from .on import on_regex as on_regex
from .plugin import Plugin as Plugin
from .on import on_notice as on_notice
from .on import on_command as on_command
from .on import on_keyword as on_keyword
from .on import on_message as on_message
from .on import on_request as on_request
from .on import on_endswith as on_endswith
from .load import load_plugin as load_plugin
from .on import CommandGroup as CommandGroup
from .on import MatcherGroup as MatcherGroup
from .on import on_metaevent as on_metaevent
from .plugin import get_plugin as get_plugin
from .load import load_plugins as load_plugins
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 .load import load_all_plugins as load_all_plugins
from .plugin import get_loaded_plugins as get_loaded_plugins
from .load import load_builtin_plugins as load_builtin_plugins

View File

@ -1,33 +1,14 @@
from typing import Set, Optional
import json
from typing import Set, Iterable, Optional
import tomlkit
from . import _managers
from .export import Export
from .manager import PluginManager
from .plugin import Plugin, get_plugin
# TODO
def _load_plugin(manager: PluginManager, plugin_name: str) -> Optional[Plugin]:
if plugin_name.startswith("_"):
return None
if plugin_name in plugins:
return None
try:
module = manager.load_plugin(plugin_name)
plugin = Plugin(plugin_name, module)
plugins[plugin_name] = plugin
logger.opt(colors=True).success(
f'Succeeded to import "<y>{escape_tag(plugin_name)}</y>"')
return plugin
except Exception as e:
logger.opt(colors=True, exception=e).error(
f'<r><bg #f8bbd0>Failed to import "{escape_tag(plugin_name)}"</bg #f8bbd0></r>'
)
return None
def load_plugin(module_path: str) -> Optional[Plugin]:
"""
:说明:
@ -43,9 +24,9 @@ def load_plugin(module_path: str) -> Optional[Plugin]:
- ``Optional[Plugin]``
"""
context: Context = copy_context()
manager = PluginManager(PLUGIN_NAMESPACE, plugins=[module_path])
return context.run(_load_plugin, manager, module_path)
manager = PluginManager([module_path])
_managers.append(manager)
return manager.load_plugin(module_path)
def load_plugins(*plugin_dir: str) -> Set[Plugin]:
@ -62,18 +43,13 @@ def load_plugins(*plugin_dir: str) -> Set[Plugin]:
- ``Set[Plugin]``
"""
loaded_plugins = set()
manager = PluginManager(PLUGIN_NAMESPACE, search_path=plugin_dir)
for plugin_name in manager.list_plugins():
context: Context = copy_context()
result = context.run(_load_plugin, manager, plugin_name)
if result:
loaded_plugins.add(result)
return loaded_plugins
manager = PluginManager(search_path=plugin_dir)
_managers.append(manager)
return manager.load_all_plugins()
def load_all_plugins(module_path: Set[str],
plugin_dir: Set[str]) -> Set[Plugin]:
def load_all_plugins(module_path: Iterable[str],
plugin_dir: Iterable[str]) -> Set[Plugin]:
"""
:说明:
@ -81,21 +57,16 @@ def load_all_plugins(module_path: Set[str],
:参数:
- ``module_path: Set[str]``: 指定插件集合
- ``plugin_dir: Set[str]``: 指定插件路径集合
- ``module_path: Iterable[str]``: 指定插件集合
- ``plugin_dir: Iterable[str]``: 指定插件路径集合
:返回:
- ``Set[Plugin]``
"""
loaded_plugins = set()
manager = PluginManager(PLUGIN_NAMESPACE, module_path, plugin_dir)
for plugin_name in manager.list_plugins():
context: Context = copy_context()
result = context.run(_load_plugin, manager, plugin_name)
if result:
loaded_plugins.add(result)
return loaded_plugins
manager = PluginManager(module_path, plugin_dir)
_managers.append(manager)
return manager.load_all_plugins()
def load_from_json(file_path: str, encoding: str = "utf-8") -> Set[Plugin]:
@ -127,7 +98,7 @@ def load_from_toml(file_path: str, encoding: str = "utf-8") -> Set[Plugin]:
"""
:说明:
导入指定 toml 文件 ``[nonebot.plugins]`` 中的 ``plugins`` 以及 ``plugin_dirs`` 下多个插件
导入指定 toml 文件 ``[tool.nonebot]`` 中的 ``plugins`` 以及 ``plugin_dirs`` 下多个插件
``_`` 开头的插件不会被导入
:参数:
@ -142,22 +113,23 @@ def load_from_toml(file_path: str, encoding: str = "utf-8") -> Set[Plugin]:
with open(file_path, "r", encoding=encoding) as f:
data = tomlkit.parse(f.read()) # type: ignore
nonebot_data = data.get("nonebot", {}).get("plugins")
nonebot_data = data.get("tool", {}).get("nonebot") or data.get(
"nonebot", {}).get("plugins")
if not nonebot_data:
raise ValueError("Cannot find '[nonebot.plugins]' in given toml file!")
raise ValueError("Cannot find '[tool.nonebot]' in given toml file!")
plugins = nonebot_data.get("plugins", [])
plugin_dirs = nonebot_data.get("plugin_dirs", [])
assert isinstance(plugins, list), "plugins must be a list of plugin name"
assert isinstance(plugin_dirs,
list), "plugin_dirs must be a list of directories"
return load_all_plugins(set(plugins), set(plugin_dirs))
return load_all_plugins(plugins, plugin_dirs)
def load_builtin_plugins(name: str = "echo") -> Optional[Plugin]:
"""
:说明:
导入 NoneBot 内置插件
导入 NoneBot 内置插件, 默认导入 ``echo`` 插件
:返回:
@ -166,7 +138,7 @@ def load_builtin_plugins(name: str = "echo") -> Optional[Plugin]:
return load_plugin(f"nonebot.plugins.{name}")
def require(name: str) -> Optional[Export]:
def require(name: str) -> Export:
"""
:说明:
@ -178,7 +150,10 @@ def require(name: str) -> Optional[Export]:
:返回:
- ``Optional[Export]``
- ``Export``
:异常:
- ``RuntimeError``: 插件无法加载
"""
plugin = get_plugin(name) or load_plugin(name)
if not plugin:

View File

@ -2,20 +2,18 @@ import sys
import pkgutil
import importlib
from pathlib import Path
from itertools import chain
from types import ModuleType
from collections import Counter
from importlib.abc import MetaPathFinder
from importlib.machinery import PathFinder, SourceFileLoader
from typing import Set, List, Union, Iterable, Optional, Sequence
from typing import Set, Dict, List, Union, Iterable, Optional, Sequence
from .export import Export
from . import _current_plugin
from nonebot.log import logger
from nonebot.utils import escape_tag
from .plugin import Plugin, _new_plugin
_manager_stack: List["PluginManager"] = []
from . import _managers, _current_plugin
# TODO
class PluginManager:
def __init__(
@ -27,81 +25,79 @@ class PluginManager:
# simple plugin not in search path
self.plugins: Set[str] = set(plugins or [])
self.search_path: Set[str] = set(search_path or [])
# ensure can be loaded
# cache plugins
self.searched_plugins: Dict[str, Path] = {}
self.list_plugins()
def search_plugins(self) -> List[str]:
def _path_to_module_name(self, path: Path) -> str:
rel_path = path.resolve().relative_to(Path(".").resolve())
if rel_path.stem == "__init__":
return ".".join(rel_path.parts[:-1])
else:
return ".".join(rel_path.parts[:-1] + (rel_path.stem,))
def _previous_plugins(self) -> List[str]:
_pre_managers: List[PluginManager]
if self in _managers:
_pre_managers = _managers[:_managers.index(self)]
else:
_pre_managers = _managers[:]
return [
module_info.name
for module_info in pkgutil.iter_modules(self.search_path)
*chain.from_iterable(
[*manager.plugins, *manager.searched_plugins.keys()]
for manager in _pre_managers)
]
def list_plugins(self) -> Set[str]:
_pre_managers: List[PluginManager]
if self in _manager_stack:
_pre_managers = _manager_stack[:_manager_stack.index(self)]
else:
_pre_managers = _manager_stack[:]
# get all previous ready to load plugins
previous_plugins = self._previous_plugins()
searched_plugins: Dict[str, Path] = {}
_search_path: Set[str] = set()
for manager in _pre_managers:
_search_path |= manager.search_path
if _search_path & self.search_path:
raise RuntimeError("Duplicate plugin search path!")
_search_plugins = self.search_plugins()
c = Counter([*_search_plugins, *self.plugins])
conflict = [name for name, num in c.items() if num > 1]
if conflict:
raise RuntimeError(
f"More than one plugin named {' / '.join(conflict)}!")
return set(_search_plugins) | self.plugins
def load_plugin(self, name) -> ModuleType:
if name in self.plugins:
return importlib.import_module(name)
if "." in name:
raise ValueError("Plugin name cannot contain '.'")
return importlib.import_module(f"{self.namespace}.{name}")
def load_all_plugins(self) -> List[ModuleType]:
return [self.load_plugin(name) for name in self.list_plugins()]
def _rewrite_module_name(self, module_name: str) -> Optional[str]:
prefix = f"{self.internal_module.__name__}."
raw_name = module_name[len(self.namespace) +
1:] if module_name.startswith(self.namespace +
".") else None
# dir plugins
if raw_name and raw_name.split(".")[0] in self.search_plugins():
return f"{prefix}{raw_name}"
# third party plugin or renamed dir plugins
elif module_name in self.plugins or module_name.startswith(prefix):
return module_name
# dir plugins
elif module_name in self.search_plugins():
return f"{prefix}{module_name}"
return None
def _check_absolute_import(self, origin_path: str) -> Optional[str]:
if not self.search_path:
return
paths = set([
*self.search_path,
*(str(Path(path).resolve()) for path in self.search_path)
])
for path in paths:
try:
rel_path = Path(origin_path).relative_to(path)
if rel_path.stem == "__init__":
return f"{self.internal_module.__name__}." + ".".join(
rel_path.parts[:-1])
return f"{self.internal_module.__name__}." + ".".join(
rel_path.parts[:-1] + (rel_path.stem,))
except ValueError:
for module_info in pkgutil.iter_modules(self.search_path):
if module_info.name.startswith("_"):
continue
if module_info.name in searched_plugins.keys(
) or module_info.name in previous_plugins:
raise RuntimeError(
f"Plugin already exists: {module_info.name}! Check your plugin name"
)
module_spec = module_info.module_finder.find_spec(
module_info.name, None)
if not module_spec:
continue
module_path = module_spec.origin
if not module_path:
continue
searched_plugins[module_info.name] = Path(module_path).resolve()
self.searched_plugins = searched_plugins
return self.plugins | set(self.searched_plugins.keys())
def load_plugin(self, name) -> Optional[Plugin]:
try:
if name in self.plugins:
module = importlib.import_module(name)
elif name not in self.searched_plugins:
raise RuntimeError(
f"Plugin not found: {name}! Check your plugin name")
else:
module = importlib.import_module(
self._path_to_module_name(self.searched_plugins[name]))
logger.opt(colors=True).success(
f'Succeeded to import "<y>{escape_tag(name)}</y>"')
return getattr(module, "__plugin__", None)
except Exception as e:
logger.opt(colors=True, exception=e).error(
f'<r><bg #f8bbd0>Failed to import "{escape_tag(name)}"</bg #f8bbd0></r>'
)
def load_all_plugins(self) -> Set[Plugin]:
return set(
filter(None,
(self.load_plugin(name) for name in self.list_plugins())))
class PluginFinder(MetaPathFinder):
@ -110,28 +106,27 @@ class PluginFinder(MetaPathFinder):
fullname: str,
path: Optional[Sequence[Union[bytes, str]]],
target: Optional[ModuleType] = None):
if _manager_stack:
if _managers:
index = -1
origin_spec = PathFinder.find_spec(fullname, path, target)
while -index <= len(_manager_stack):
manager = _manager_stack[index]
module_spec = PathFinder.find_spec(fullname, path, target)
if not module_spec:
return
module_origin = module_spec.origin
if not module_origin:
return
module_path = Path(module_origin).resolve()
rel_name = None
if origin_spec and origin_spec.origin:
rel_name = manager._check_absolute_import(
origin_spec.origin)
while -index <= len(_managers):
manager = _managers[index]
if fullname in manager.plugins or module_path in manager.searched_plugins.values(
):
module_spec.loader = PluginLoader(manager, fullname,
module_origin)
return module_spec
newname = manager._rewrite_module_name(rel_name or fullname)
if newname:
spec = PathFinder.find_spec(
newname, path or [*manager.search_path, *sys.path],
target)
if spec:
spec.loader = PluginLoader( # type: ignore
manager, newname, spec.origin)
return spec
index -= 1
return None
return
class PluginLoader(SourceFileLoader):
@ -152,20 +147,15 @@ class PluginLoader(SourceFileLoader):
if self.loaded:
return
export = Export()
_export_token = _export.set(export)
plugin = _new_plugin(self.name, module)
parent_plugin = _current_plugin.get()
if parent_plugin:
plugin.parent_plugin = parent_plugin
parent_plugin.sub_plugins.add(plugin)
prefix = self.manager.internal_module.__name__
is_dir_plugin = self.name.startswith(prefix + ".")
module_name = self.name[len(prefix) +
1:] if is_dir_plugin else self.name
_plugin_token = _current_plugin.set(module)
_plugin_token = _current_plugin.set(plugin)
setattr(module, "__export__", export)
setattr(module, "__plugin_name__",
module_name.split(".")[0] if is_dir_plugin else module_name)
setattr(module, "__module_name__", module_name)
setattr(module, "__module_prefix__", prefix if is_dir_plugin else "")
setattr(module, "__plugin__", plugin)
# try:
# super().exec_module(module)
@ -176,7 +166,6 @@ class PluginLoader(SourceFileLoader):
super().exec_module(module)
_current_plugin.reset(_plugin_token)
_export.reset(_export_token)
return

View File

@ -7,13 +7,12 @@ from typing import (TYPE_CHECKING, Any, Set, Dict, List, Type, Tuple, Union,
from nonebot.handler import Handler
from nonebot.matcher import Matcher
from .manager import _current_plugin
from nonebot.permission import Permission
from nonebot.typing import T_State, T_Handler, T_RuleChecker, T_StateFactory
from nonebot.rule import (Rule, ArgumentParser, regex, command, keyword,
endswith, startswith, shell_command)
from .manager import _current_plugin
if TYPE_CHECKING:
from nonebot.adapters import Bot, Event
@ -43,7 +42,8 @@ def on(type: str = "",
priority: int = 1,
block: bool = False,
state: Optional[T_State] = None,
state_factory: Optional[T_StateFactory] = None) -> Type[Matcher]:
state_factory: Optional[T_StateFactory] = None,
_depth: int = 0) -> Type[Matcher]:
"""
:说明:
@ -73,22 +73,22 @@ def on(type: str = "",
block=block,
handlers=handlers,
plugin=_current_plugin.get(),
module=_get_matcher_module(),
module=_get_matcher_module(_depth + 1),
default_state=state,
default_state_factory=state_factory)
_store_matcher(matcher)
return matcher
def on_metaevent(
rule: Optional[Union[Rule, T_RuleChecker]] = None,
*,
handlers: Optional[List[Union[T_Handler, Handler]]] = None,
temp: bool = False,
priority: int = 1,
block: bool = False,
state: Optional[T_State] = None,
state_factory: Optional[T_StateFactory] = None) -> Type[Matcher]:
def on_metaevent(rule: Optional[Union[Rule, T_RuleChecker]] = None,
*,
handlers: Optional[List[Union[T_Handler, Handler]]] = None,
temp: bool = False,
priority: int = 1,
block: bool = False,
state: Optional[T_State] = None,
state_factory: Optional[T_StateFactory] = None,
_depth: int = 0) -> Type[Matcher]:
"""
:说明:
@ -116,7 +116,7 @@ def on_metaevent(
block=block,
handlers=handlers,
plugin=_current_plugin.get(),
module=_get_matcher_module(),
module=_get_matcher_module(_depth + 1),
default_state=state,
default_state_factory=state_factory)
_store_matcher(matcher)
@ -131,7 +131,8 @@ def on_message(rule: Optional[Union[Rule, T_RuleChecker]] = None,
priority: int = 1,
block: bool = True,
state: Optional[T_State] = None,
state_factory: Optional[T_StateFactory] = None) -> Type[Matcher]:
state_factory: Optional[T_StateFactory] = None,
_depth: int = 0) -> Type[Matcher]:
"""
:说明:
@ -160,7 +161,7 @@ def on_message(rule: Optional[Union[Rule, T_RuleChecker]] = None,
block=block,
handlers=handlers,
plugin=_current_plugin.get(),
module=_get_matcher_module(),
module=_get_matcher_module(_depth + 1),
default_state=state,
default_state_factory=state_factory)
_store_matcher(matcher)
@ -174,7 +175,8 @@ def on_notice(rule: Optional[Union[Rule, T_RuleChecker]] = None,
priority: int = 1,
block: bool = False,
state: Optional[T_State] = None,
state_factory: Optional[T_StateFactory] = None) -> Type[Matcher]:
state_factory: Optional[T_StateFactory] = None,
_depth: int = 0) -> Type[Matcher]:
"""
:说明:
@ -202,7 +204,7 @@ def on_notice(rule: Optional[Union[Rule, T_RuleChecker]] = None,
block=block,
handlers=handlers,
plugin=_current_plugin.get(),
module=_get_matcher_module(),
module=_get_matcher_module(_depth + 1),
default_state=state,
default_state_factory=state_factory)
_store_matcher(matcher)
@ -216,7 +218,8 @@ def on_request(rule: Optional[Union[Rule, T_RuleChecker]] = None,
priority: int = 1,
block: bool = False,
state: Optional[T_State] = None,
state_factory: Optional[T_StateFactory] = None) -> Type[Matcher]:
state_factory: Optional[T_StateFactory] = None,
_depth: int = 0) -> Type[Matcher]:
"""
:说明:
@ -244,7 +247,7 @@ def on_request(rule: Optional[Union[Rule, T_RuleChecker]] = None,
block=block,
handlers=handlers,
plugin=_current_plugin.get(),
module=_get_matcher_module(),
module=_get_matcher_module(_depth + 1),
default_state=state,
default_state_factory=state_factory)
_store_matcher(matcher)
@ -254,6 +257,7 @@ def on_request(rule: Optional[Union[Rule, T_RuleChecker]] = None,
def on_startswith(msg: Union[str, Tuple[str, ...]],
rule: Optional[Optional[Union[Rule, T_RuleChecker]]] = None,
ignorecase: bool = False,
_depth: int = 0,
**kwargs) -> Type[Matcher]:
"""
:说明:
@ -277,12 +281,15 @@ def on_startswith(msg: Union[str, Tuple[str, ...]],
- ``Type[Matcher]``
"""
return on_message(startswith(msg, ignorecase) & rule, **kwargs)
return on_message(startswith(msg, ignorecase) & rule,
**kwargs,
_depth=_depth + 1)
def on_endswith(msg: Union[str, Tuple[str, ...]],
rule: Optional[Optional[Union[Rule, T_RuleChecker]]] = None,
ignorecase: bool = False,
_depth: int = 0,
**kwargs) -> Type[Matcher]:
"""
:说明:
@ -306,11 +313,14 @@ def on_endswith(msg: Union[str, Tuple[str, ...]],
- ``Type[Matcher]``
"""
return on_message(endswith(msg, ignorecase) & rule, **kwargs)
return on_message(endswith(msg, ignorecase) & rule,
**kwargs,
_depth=_depth + 1)
def on_keyword(keywords: Set[str],
rule: Optional[Union[Rule, T_RuleChecker]] = None,
_depth: int = 0,
**kwargs) -> Type[Matcher]:
"""
:说明:
@ -333,12 +343,13 @@ def on_keyword(keywords: Set[str],
- ``Type[Matcher]``
"""
return on_message(keyword(*keywords) & rule, **kwargs)
return on_message(keyword(*keywords) & rule, **kwargs, _depth=_depth + 1)
def on_command(cmd: Union[str, Tuple[str, ...]],
rule: Optional[Union[Rule, T_RuleChecker]] = None,
aliases: Optional[Set[Union[str, Tuple[str, ...]]]] = None,
_depth: int = 0,
**kwargs) -> Type[Matcher]:
"""
:说明:
@ -382,13 +393,17 @@ def on_command(cmd: Union[str, Tuple[str, ...]],
handlers.insert(0, _strip_cmd)
commands = set([cmd]) | (aliases or set())
return on_message(command(*commands) & rule, handlers=handlers, **kwargs)
return on_message(command(*commands) & rule,
handlers=handlers,
**kwargs,
_depth=_depth + 1)
def on_shell_command(cmd: Union[str, Tuple[str, ...]],
rule: Optional[Union[Rule, T_RuleChecker]] = None,
aliases: Optional[Set[Union[str, Tuple[str, ...]]]] = None,
parser: Optional[ArgumentParser] = None,
_depth: int = 0,
**kwargs) -> Type[Matcher]:
"""
:说明:
@ -433,12 +448,14 @@ def on_shell_command(cmd: Union[str, Tuple[str, ...]],
commands = set([cmd]) | (aliases or set())
return on_message(shell_command(*commands, parser=parser) & rule,
handlers=handlers,
**kwargs)
**kwargs,
_depth=_depth + 1)
def on_regex(pattern: str,
flags: Union[int, re.RegexFlag] = 0,
rule: Optional[Union[Rule, T_RuleChecker]] = None,
_depth: int = 0,
**kwargs) -> Type[Matcher]:
"""
:说明:
@ -464,7 +481,7 @@ def on_regex(pattern: str,
- ``Type[Matcher]``
"""
return on_message(regex(pattern, flags) & rule, **kwargs)
return on_message(regex(pattern, flags) & rule, **kwargs, _depth=_depth + 1)
class CommandGroup:
@ -511,7 +528,7 @@ class CommandGroup:
final_kwargs = self.base_kwargs.copy()
final_kwargs.update(kwargs)
return on_command(cmd, **final_kwargs)
return on_command(cmd, **final_kwargs, _depth=1)
def shell_command(self, cmd: Union[str, Tuple[str, ...]],
**kwargs) -> Type[Matcher]:
@ -534,7 +551,7 @@ class CommandGroup:
final_kwargs = self.base_kwargs.copy()
final_kwargs.update(kwargs)
return on_shell_command(cmd, **final_kwargs)
return on_shell_command(cmd, **final_kwargs, _depth=1)
class MatcherGroup:
@ -581,7 +598,7 @@ class MatcherGroup:
"""
final_kwargs = self.base_kwargs.copy()
final_kwargs.update(kwargs)
matcher = on(**final_kwargs)
matcher = on(**final_kwargs, _depth=1)
self.matchers.append(matcher)
return matcher
@ -609,7 +626,7 @@ class MatcherGroup:
final_kwargs.update(kwargs)
final_kwargs.pop("type", None)
final_kwargs.pop("permission", None)
matcher = on_metaevent(**final_kwargs)
matcher = on_metaevent(**final_kwargs, _depth=1)
self.matchers.append(matcher)
return matcher
@ -637,7 +654,7 @@ class MatcherGroup:
final_kwargs = self.base_kwargs.copy()
final_kwargs.update(kwargs)
final_kwargs.pop("type", None)
matcher = on_message(**final_kwargs)
matcher = on_message(**final_kwargs, _depth=1)
self.matchers.append(matcher)
return matcher
@ -664,7 +681,7 @@ class MatcherGroup:
final_kwargs = self.base_kwargs.copy()
final_kwargs.update(kwargs)
final_kwargs.pop("type", None)
matcher = on_notice(**final_kwargs)
matcher = on_notice(**final_kwargs, _depth=1)
self.matchers.append(matcher)
return matcher
@ -691,7 +708,7 @@ class MatcherGroup:
final_kwargs = self.base_kwargs.copy()
final_kwargs.update(kwargs)
final_kwargs.pop("type", None)
matcher = on_request(**final_kwargs)
matcher = on_request(**final_kwargs, _depth=1)
self.matchers.append(matcher)
return matcher
@ -722,7 +739,7 @@ class MatcherGroup:
final_kwargs = self.base_kwargs.copy()
final_kwargs.update(kwargs)
final_kwargs.pop("type", None)
matcher = on_startswith(msg, **final_kwargs)
matcher = on_startswith(msg, **final_kwargs, _depth=1)
self.matchers.append(matcher)
return matcher
@ -753,7 +770,7 @@ class MatcherGroup:
final_kwargs = self.base_kwargs.copy()
final_kwargs.update(kwargs)
final_kwargs.pop("type", None)
matcher = on_endswith(msg, **final_kwargs)
matcher = on_endswith(msg, **final_kwargs, _depth=1)
self.matchers.append(matcher)
return matcher
@ -782,7 +799,7 @@ class MatcherGroup:
final_kwargs = self.base_kwargs.copy()
final_kwargs.update(kwargs)
final_kwargs.pop("type", None)
matcher = on_keyword(keywords, **final_kwargs)
matcher = on_keyword(keywords, **final_kwargs, _depth=1)
self.matchers.append(matcher)
return matcher
@ -817,7 +834,7 @@ class MatcherGroup:
final_kwargs = self.base_kwargs.copy()
final_kwargs.update(kwargs)
final_kwargs.pop("type", None)
matcher = on_command(cmd, aliases=aliases, **final_kwargs)
matcher = on_command(cmd, aliases=aliases, **final_kwargs, _depth=1)
self.matchers.append(matcher)
return matcher
@ -860,7 +877,8 @@ class MatcherGroup:
matcher = on_shell_command(cmd,
aliases=aliases,
parser=parser,
**final_kwargs)
**final_kwargs,
_depth=1)
self.matchers.append(matcher)
return matcher
@ -895,6 +913,6 @@ class MatcherGroup:
final_kwargs = self.base_kwargs.copy()
final_kwargs.update(kwargs)
final_kwargs.pop("type", None)
matcher = on_regex(pattern, flags=flags, **final_kwargs)
matcher = on_regex(pattern, flags=flags, **final_kwargs, _depth=1)
self.matchers.append(matcher)
return matcher

View File

@ -2,9 +2,8 @@ from types import ModuleType
from dataclasses import field, dataclass
from typing import Set, Dict, Type, Optional
from nonebot.matcher import Matcher
from .export import Export
from nonebot.matcher import Matcher
plugins: Dict[str, "Plugin"] = {}
"""
@ -77,7 +76,7 @@ def get_loaded_plugins() -> Set[Plugin]:
def _new_plugin(fullname: str, module: ModuleType) -> Plugin:
_, name = fullname.rsplit(".", 1)
name = fullname.rsplit(".", 1)[-1] if "." in fullname else fullname
if name in plugins:
raise RuntimeError("Plugin already exists! Check your plugin name.")
plugin = Plugin(name, module, fullname)

View File

@ -7,6 +7,8 @@ sidebar: auto
## v2.0.0a17
- 新增 `MessageTemplate` 对于 `str` 普通模板的支持
- 移除插件加载的 `NameSpace` 模式
- 修改 toml 加载插件时的键名为 `tool.nonebot` 以符合规范
## v2.0.0a16

View File

@ -59,6 +59,7 @@ line_length = 80
length_sort = true
skip_gitignore = true
force_sort_within_sections = true
known_local_folder = "nonebot"
extra_standard_library = "typing_extensions"
[build-system]

View File

@ -1,3 +1,3 @@
[nonebot.plugins]
[tool.nonebot]
plugins = ["nonebot_plugin_test"]
plugin_dirs = ["test_plugins"]