diff --git a/nonebot/__init__.py b/nonebot/__init__.py
index e5af0caf..a9c6d350 100644
--- a/nonebot/__init__.py
+++ b/nonebot/__init__.py
@@ -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(
diff --git a/nonebot/plugin/__init__.py b/nonebot/plugin/__init__.py
index fcfcbefc..69a34e63 100644
--- a/nonebot/plugin/__init__.py
+++ b/nonebot/plugin/__init__.py
@@ -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
diff --git a/nonebot/plugin/load.py b/nonebot/plugin/load.py
index cbac46c3..5e1002dc 100644
--- a/nonebot/plugin/load.py
+++ b/nonebot/plugin/load.py
@@ -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 "{escape_tag(plugin_name)}"')
- return plugin
- except Exception as e:
- logger.opt(colors=True, exception=e).error(
- f'Failed to import "{escape_tag(plugin_name)}"'
- )
- 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:
diff --git a/nonebot/plugin/manager.py b/nonebot/plugin/manager.py
index d0243c91..e98495d0 100644
--- a/nonebot/plugin/manager.py
+++ b/nonebot/plugin/manager.py
@@ -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 "{escape_tag(name)}"')
+ return getattr(module, "__plugin__", None)
+ except Exception as e:
+ logger.opt(colors=True, exception=e).error(
+ f'Failed to import "{escape_tag(name)}"'
+ )
+
+ 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
diff --git a/nonebot/plugin/on.py b/nonebot/plugin/on.py
index f8d22167..e4da8345 100644
--- a/nonebot/plugin/on.py
+++ b/nonebot/plugin/on.py
@@ -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
diff --git a/nonebot/plugin/plugin.py b/nonebot/plugin/plugin.py
index ec248d10..ea06b446 100644
--- a/nonebot/plugin/plugin.py
+++ b/nonebot/plugin/plugin.py
@@ -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)
diff --git a/pages/changelog.md b/pages/changelog.md
index b5012389..76c9f1c5 100644
--- a/pages/changelog.md
+++ b/pages/changelog.md
@@ -7,6 +7,8 @@ sidebar: auto
## v2.0.0a17
- 新增 `MessageTemplate` 对于 `str` 普通模板的支持
+- 移除插件加载的 `NameSpace` 模式
+- 修改 toml 加载插件时的键名为 `tool.nonebot` 以符合规范
## v2.0.0a16
diff --git a/pyproject.toml b/pyproject.toml
index 07ed326a..6d9a8330 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -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]
diff --git a/tests/plugins.toml b/tests/plugins.toml
index 85eefe30..a905f3dc 100644
--- a/tests/plugins.toml
+++ b/tests/plugins.toml
@@ -1,3 +1,3 @@
-[nonebot.plugins]
+[tool.nonebot]
plugins = ["nonebot_plugin_test"]
plugin_dirs = ["test_plugins"]