From 2ccbc93e48ca591b87d523ecdd642d853cc59e88 Mon Sep 17 00:00:00 2001 From: yanyongyu Date: Thu, 11 Nov 2021 17:33:30 +0800 Subject: [PATCH] :recycle: remove plugin namespace --- nonebot/__init__.py | 2 +- nonebot/plugin/__init__.py | 24 ++++- nonebot/plugin/load.py | 83 ++++++---------- nonebot/plugin/manager.py | 199 ++++++++++++++++++------------------- nonebot/plugin/on.py | 96 ++++++++++-------- nonebot/plugin/plugin.py | 5 +- pages/changelog.md | 2 + pyproject.toml | 1 + tests/plugins.toml | 2 +- 9 files changed, 210 insertions(+), 204 deletions(-) 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"]