We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Bug: `require` 重复加载插件错误
**描述问题：**

`require` load plugin raises `RuntimeError: Plugin already exists`

**如何复现？**

使用 `nonebot.load_from_toml(["third_party_plugin"], ["plugin_dir"])`，并在插件中添加 `require("third_party_plugin")`

由于加载顺序随机，有一定概率失败


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `nonebot/plugin/load.py`
Content:
```
1 """本模块定义插件加载接口。
2 
3 FrontMatter:
4     sidebar_position: 1
5     description: nonebot.plugin.load 模块
6 """
7 import json
8 import warnings
9 from typing import Set, Iterable, Optional
10 
11 import tomlkit
12 
13 from . import _managers
14 from .export import Export
15 from .manager import PluginManager
16 from .plugin import Plugin, get_plugin
17 
18 
19 def load_plugin(module_path: str) -> Optional[Plugin]:
20     """加载单个插件，可以是本地插件或是通过 `pip` 安装的插件。
21 
22     参数:
23         module_path: 插件名称 `path.to.your.plugin`
24     """
25 
26     manager = PluginManager([module_path])
27     _managers.append(manager)
28     return manager.load_plugin(module_path)
29 
30 
31 def load_plugins(*plugin_dir: str) -> Set[Plugin]:
32     """导入文件夹下多个插件，以 `_` 开头的插件不会被导入!
33 
34     参数:
35         plugin_dir: 文件夹路径
36     """
37     manager = PluginManager(search_path=plugin_dir)
38     _managers.append(manager)
39     return manager.load_all_plugins()
40 
41 
42 def load_all_plugins(
43     module_path: Iterable[str], plugin_dir: Iterable[str]
44 ) -> Set[Plugin]:
45     """导入指定列表中的插件以及指定目录下多个插件，以 `_` 开头的插件不会被导入!
46 
47     参数:
48         module_path: 指定插件集合
49         plugin_dir: 指定文件夹路径集合
50     """
51     manager = PluginManager(module_path, plugin_dir)
52     _managers.append(manager)
53     return manager.load_all_plugins()
54 
55 
56 def load_from_json(file_path: str, encoding: str = "utf-8") -> Set[Plugin]:
57     """导入指定 json 文件中的 `plugins` 以及 `plugin_dirs` 下多个插件，以 `_` 开头的插件不会被导入!
58 
59     参数:
60         file_path: 指定 json 文件路径
61         encoding: 指定 json 文件编码
62 
63     用法:
64         ```json title=plugins.json
65         {
66             "plugins": ["some_plugin"],
67             "plugin_dirs": ["some_dir"]
68         }
69         ```
70 
71         ```python
72         nonebot.load_from_json("plugins.json")
73         ```
74     """
75     with open(file_path, "r", encoding=encoding) as f:
76         data = json.load(f)
77     plugins = data.get("plugins")
78     plugin_dirs = data.get("plugin_dirs")
79     assert isinstance(plugins, list), "plugins must be a list of plugin name"
80     assert isinstance(plugin_dirs, list), "plugin_dirs must be a list of directories"
81     return load_all_plugins(set(plugins), set(plugin_dirs))
82 
83 
84 def load_from_toml(file_path: str, encoding: str = "utf-8") -> Set[Plugin]:
85     """导入指定 toml 文件 `[tool.nonebot]` 中的 `plugins` 以及 `plugin_dirs` 下多个插件，以 `_` 开头的插件不会被导入!
86 
87     参数:
88         file_path: 指定 toml 文件路径
89         encoding: 指定 toml 文件编码
90 
91     用法:
92         ```toml title=pyproject.toml
93         [tool.nonebot]
94         plugins = ["some_plugin"]
95         plugin_dirs = ["some_dir"]
96         ```
97 
98         ```python
99         nonebot.load_from_toml("pyproject.toml")
100         ```
101     """
102     with open(file_path, "r", encoding=encoding) as f:
103         data = tomlkit.parse(f.read())  # type: ignore
104 
105     nonebot_data = data.get("tool", {}).get("nonebot")
106     if not nonebot_data:
107         nonebot_data = data.get("nonebot", {}).get("plugins")
108         if nonebot_data:
109             warnings.warn(
110                 "[nonebot.plugins] table are now deprecated. Use [tool.nonebot] instead.",
111                 DeprecationWarning,
112             )
113         else:
114             raise ValueError("Cannot find '[tool.nonebot]' in given toml file!")
115     plugins = nonebot_data.get("plugins", [])
116     plugin_dirs = nonebot_data.get("plugin_dirs", [])
117     assert isinstance(plugins, list), "plugins must be a list of plugin name"
118     assert isinstance(plugin_dirs, list), "plugin_dirs must be a list of directories"
119     return load_all_plugins(plugins, plugin_dirs)
120 
121 
122 def load_builtin_plugin(name: str) -> Optional[Plugin]:
123     """导入 NoneBot 内置插件。
124 
125     参数:
126         name: 插件名称
127     """
128     return load_plugin(f"nonebot.plugins.{name}")
129 
130 
131 def load_builtin_plugins(*plugins) -> Set[Plugin]:
132     """导入多个 NoneBot 内置插件。
133 
134     参数:
135         plugins: 插件名称列表
136     """
137     return load_all_plugins([f"nonebot.plugins.{p}" for p in plugins], [])
138 
139 
140 def require(name: str) -> Export:
141     """获取一个插件的导出内容。
142 
143     如果为 `load_plugins` 文件夹导入的插件，则为文件(夹)名。
144 
145     参数:
146         name: 插件名，即 {ref}`nonebot.plugin.plugin.Plugin.name`。
147 
148     异常:
149         RuntimeError: 插件无法加载
150     """
151     plugin = get_plugin(name) or load_plugin(name)
152     if not plugin:
153         raise RuntimeError(f'Cannot load plugin "{name}"!')
154     return plugin.export
155
```

Path: `nonebot/plugin/manager.py`
Content:
```
1 """本模块实现插件加载流程。
2 
3 参考: [import hooks](https://docs.python.org/3/reference/import.html#import-hooks), [PEP302](https://www.python.org/dev/peps/pep-0302/)
4 
5 FrontMatter:
6     sidebar_position: 5
7     description: nonebot.plugin.manager 模块
8 """
9 import sys
10 import pkgutil
11 import importlib
12 from pathlib import Path
13 from itertools import chain
14 from types import ModuleType
15 from importlib.abc import MetaPathFinder
16 from importlib.machinery import PathFinder, SourceFileLoader
17 from typing import Set, Dict, List, Union, Iterable, Optional, Sequence
18 
19 from nonebot.log import logger
20 from nonebot.utils import escape_tag
21 
22 from . import _managers, _current_plugin
23 from .plugin import Plugin, _new_plugin, _confirm_plugin
24 
25 
26 class PluginManager:
27     def __init__(
28         self,
29         plugins: Optional[Iterable[str]] = None,
30         search_path: Optional[Iterable[str]] = None,
31     ):
32 
33         # simple plugin not in search path
34         self.plugins: Set[str] = set(plugins or [])
35         self.search_path: Set[str] = set(search_path or [])
36         # cache plugins
37         self.searched_plugins: Dict[str, Path] = {}
38         self.list_plugins()
39 
40     def _path_to_module_name(self, path: Path) -> str:
41         rel_path = path.resolve().relative_to(Path(".").resolve())
42         if rel_path.stem == "__init__":
43             return ".".join(rel_path.parts[:-1])
44         else:
45             return ".".join(rel_path.parts[:-1] + (rel_path.stem,))
46 
47     def _previous_plugins(self) -> List[str]:
48         _pre_managers: List[PluginManager]
49         if self in _managers:
50             _pre_managers = _managers[: _managers.index(self)]
51         else:
52             _pre_managers = _managers[:]
53 
54         return [
55             *chain.from_iterable(
56                 [*manager.plugins, *manager.searched_plugins.keys()]
57                 for manager in _pre_managers
58             )
59         ]
60 
61     def list_plugins(self) -> Set[str]:
62         # get all previous ready to load plugins
63         previous_plugins = self._previous_plugins()
64         searched_plugins: Dict[str, Path] = {}
65         third_party_plugins: Set[str] = set()
66 
67         for plugin in self.plugins:
68             name = plugin.rsplit(".", 1)[-1] if "." in plugin else plugin
69             if name in third_party_plugins or name in previous_plugins:
70                 raise RuntimeError(
71                     f"Plugin already exists: {name}! Check your plugin name"
72                 )
73             third_party_plugins.add(plugin)
74 
75         for module_info in pkgutil.iter_modules(self.search_path):
76             if module_info.name.startswith("_"):
77                 continue
78             if (
79                 module_info.name in searched_plugins.keys()
80                 or module_info.name in previous_plugins
81                 or module_info.name in third_party_plugins
82             ):
83                 raise RuntimeError(
84                     f"Plugin already exists: {module_info.name}! Check your plugin name"
85                 )
86             module_spec = module_info.module_finder.find_spec(module_info.name, None)
87             if not module_spec:
88                 continue
89             module_path = module_spec.origin
90             if not module_path:
91                 continue
92             searched_plugins[module_info.name] = Path(module_path).resolve()
93 
94         self.searched_plugins = searched_plugins
95 
96         return third_party_plugins | set(self.searched_plugins.keys())
97 
98     def load_plugin(self, name) -> Optional[Plugin]:
99         try:
100             if name in self.plugins:
101                 module = importlib.import_module(name)
102             elif name not in self.searched_plugins:
103                 raise RuntimeError(f"Plugin not found: {name}! Check your plugin name")
104             else:
105                 module = importlib.import_module(
106                     self._path_to_module_name(self.searched_plugins[name])
107                 )
108 
109             logger.opt(colors=True).success(
110                 f'Succeeded to import "<y>{escape_tag(name)}</y>"'
111             )
112             return getattr(module, "__plugin__", None)
113         except Exception as e:
114             logger.opt(colors=True, exception=e).error(
115                 f'<r><bg #f8bbd0>Failed to import "{escape_tag(name)}"</bg #f8bbd0></r>'
116             )
117 
118     def load_all_plugins(self) -> Set[Plugin]:
119         return set(
120             filter(None, (self.load_plugin(name) for name in self.list_plugins()))
121         )
122 
123 
124 class PluginFinder(MetaPathFinder):
125     def find_spec(
126         self,
127         fullname: str,
128         path: Optional[Sequence[Union[bytes, str]]],
129         target: Optional[ModuleType] = None,
130     ):
131         if _managers:
132             index = -1
133             module_spec = PathFinder.find_spec(fullname, path, target)
134             if not module_spec:
135                 return
136             module_origin = module_spec.origin
137             if not module_origin:
138                 return
139             module_path = Path(module_origin).resolve()
140 
141             while -index <= len(_managers):
142                 manager = _managers[index]
143 
144                 if (
145                     fullname in manager.plugins
146                     or module_path in manager.searched_plugins.values()
147                 ):
148                     module_spec.loader = PluginLoader(manager, fullname, module_origin)
149                     return module_spec
150 
151                 index -= 1
152         return
153 
154 
155 class PluginLoader(SourceFileLoader):
156     def __init__(self, manager: PluginManager, fullname: str, path) -> None:
157         self.manager = manager
158         self.loaded = False
159         super().__init__(fullname, path)
160 
161     def create_module(self, spec) -> Optional[ModuleType]:
162         if self.name in sys.modules:
163             self.loaded = True
164             return sys.modules[self.name]
165         # return None to use default module creation
166         return super().create_module(spec)
167 
168     def exec_module(self, module: ModuleType) -> None:
169         if self.loaded:
170             return
171 
172         plugin = _new_plugin(self.name, module, self.manager)
173         parent_plugin = _current_plugin.get()
174         if parent_plugin and _managers.index(parent_plugin.manager) < _managers.index(
175             self.manager
176         ):
177             plugin.parent_plugin = parent_plugin
178             parent_plugin.sub_plugins.add(plugin)
179 
180         _plugin_token = _current_plugin.set(plugin)
181 
182         setattr(module, "__plugin__", plugin)
183 
184         # try:
185         #     super().exec_module(module)
186         # except Exception as e:
187         #     raise ImportError(
188         #         f"Error when executing module {module_name} from {module.__file__}."
189         #     ) from e
190         super().exec_module(module)
191 
192         _confirm_plugin(plugin)
193 
194         _current_plugin.reset(_plugin_token)
195         return
196 
197 
198 sys.meta_path.insert(0, PluginFinder())
199
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/nonebot/plugin/load.py b/nonebot/plugin/load.py
--- a/nonebot/plugin/load.py
+++ b/nonebot/plugin/load.py
@@ -137,6 +137,12 @@
     return load_all_plugins([f"nonebot.plugins.{p}" for p in plugins], [])
 
 
+def _find_manager_by_name(name: str) -> Optional[PluginManager]:
+    for manager in reversed(_managers):
+        if name in manager.plugins or name in manager.searched_plugins:
+            return manager
+
+
 def require(name: str) -> Export:
     """获取一个插件的导出内容。
 
@@ -148,7 +154,13 @@
     异常:
         RuntimeError: 插件无法加载
     """
-    plugin = get_plugin(name) or load_plugin(name)
+    plugin = get_plugin(name.rsplit(".", 1)[-1])
     if not plugin:
-        raise RuntimeError(f'Cannot load plugin "{name}"!')
+        manager = _find_manager_by_name(name)
+        if manager:
+            plugin = manager.load_plugin(name)
+        else:
+            plugin = load_plugin(name)
+        if not plugin:
+            raise RuntimeError(f'Cannot load plugin "{name}"!')
     return plugin.export
diff --git a/nonebot/plugin/manager.py b/nonebot/plugin/manager.py
--- a/nonebot/plugin/manager.py
+++ b/nonebot/plugin/manager.py
@@ -53,7 +53,10 @@
 
         return [
             *chain.from_iterable(
-                [*manager.plugins, *manager.searched_plugins.keys()]
+                [
+                    *map(lambda x: x.rsplit(".", 1)[-1], manager.plugins),
+                    *manager.searched_plugins.keys(),
+                ]
                 for manager in _pre_managers
             )
         ]
@@ -65,7 +68,7 @@
         third_party_plugins: Set[str] = set()
 
         for plugin in self.plugins:
-            name = plugin.rsplit(".", 1)[-1] if "." in plugin else plugin
+            name = plugin.rsplit(".", 1)[-1]
             if name in third_party_plugins or name in previous_plugins:
                 raise RuntimeError(
                     f"Plugin already exists: {name}! Check your plugin name"
@@ -95,21 +98,27 @@
 
         return third_party_plugins | set(self.searched_plugins.keys())
 
-    def load_plugin(self, name) -> Optional[Plugin]:
+    def load_plugin(self, name: str) -> 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:
+            elif name in self.searched_plugins:
                 module = importlib.import_module(
                     self._path_to_module_name(self.searched_plugins[name])
                 )
+            else:
+                raise RuntimeError(f"Plugin not found: {name}! Check your plugin name")
 
             logger.opt(colors=True).success(
                 f'Succeeded to import "<y>{escape_tag(name)}</y>"'
             )
-            return getattr(module, "__plugin__", None)
+            plugin = getattr(module, "__plugin__", None)
+            if plugin is None:
+                raise RuntimeError(
+                    f"Module {module.__name__} is not loaded as a plugin! "
+                    "Make sure not to import it before loading."
+                )
+            return plugin
         except Exception as e:
             logger.opt(colors=True, exception=e).error(
                 f'<r><bg #f8bbd0>Failed to import "{escape_tag(name)}"</bg #f8bbd0></r>'
@@ -129,7 +138,6 @@
         target: Optional[ModuleType] = None,
     ):
         if _managers:
-            index = -1
             module_spec = PathFinder.find_spec(fullname, path, target)
             if not module_spec:
                 return
@@ -138,17 +146,13 @@
                 return
             module_path = Path(module_origin).resolve()
 
-            while -index <= len(_managers):
-                manager = _managers[index]
-
+            for manager in reversed(_managers):
                 if (
                     fullname in manager.plugins
                     or module_path in manager.searched_plugins.values()
                 ):
                     module_spec.loader = PluginLoader(manager, fullname, module_origin)
                     return module_spec
-
-                index -= 1
         return

{"golden_diff": "diff --git a/nonebot/plugin/load.py b/nonebot/plugin/load.py\n--- a/nonebot/plugin/load.py\n+++ b/nonebot/plugin/load.py\n@@ -137,6 +137,12 @@\n     return load_all_plugins([f\"nonebot.plugins.{p}\" for p in plugins], [])\n \n \n+def _find_manager_by_name(name: str) -> Optional[PluginManager]:\n+    for manager in reversed(_managers):\n+        if name in manager.plugins or name in manager.searched_plugins:\n+            return manager\n+\n+\n def require(name: str) -> Export:\n     \"\"\"\u83b7\u53d6\u4e00\u4e2a\u63d2\u4ef6\u7684\u5bfc\u51fa\u5185\u5bb9\u3002\n \n@@ -148,7 +154,13 @@\n     \u5f02\u5e38:\n         RuntimeError: \u63d2\u4ef6\u65e0\u6cd5\u52a0\u8f7d\n     \"\"\"\n-    plugin = get_plugin(name) or load_plugin(name)\n+    plugin = get_plugin(name.rsplit(\".\", 1)[-1])\n     if not plugin:\n-        raise RuntimeError(f'Cannot load plugin \"{name}\"!')\n+        manager = _find_manager_by_name(name)\n+        if manager:\n+            plugin = manager.load_plugin(name)\n+        else:\n+            plugin = load_plugin(name)\n+        if not plugin:\n+            raise RuntimeError(f'Cannot load plugin \"{name}\"!')\n     return plugin.export\ndiff --git a/nonebot/plugin/manager.py b/nonebot/plugin/manager.py\n--- a/nonebot/plugin/manager.py\n+++ b/nonebot/plugin/manager.py\n@@ -53,7 +53,10 @@\n \n         return [\n             *chain.from_iterable(\n-                [*manager.plugins, *manager.searched_plugins.keys()]\n+                [\n+                    *map(lambda x: x.rsplit(\".\", 1)[-1], manager.plugins),\n+                    *manager.searched_plugins.keys(),\n+                ]\n                 for manager in _pre_managers\n             )\n         ]\n@@ -65,7 +68,7 @@\n         third_party_plugins: Set[str] = set()\n \n         for plugin in self.plugins:\n-            name = plugin.rsplit(\".\", 1)[-1] if \".\" in plugin else plugin\n+            name = plugin.rsplit(\".\", 1)[-1]\n             if name in third_party_plugins or name in previous_plugins:\n                 raise RuntimeError(\n                     f\"Plugin already exists: {name}! Check your plugin name\"\n@@ -95,21 +98,27 @@\n \n         return third_party_plugins | set(self.searched_plugins.keys())\n \n-    def load_plugin(self, name) -> Optional[Plugin]:\n+    def load_plugin(self, name: str) -> Optional[Plugin]:\n         try:\n             if name in self.plugins:\n                 module = importlib.import_module(name)\n-            elif name not in self.searched_plugins:\n-                raise RuntimeError(f\"Plugin not found: {name}! Check your plugin name\")\n-            else:\n+            elif name in self.searched_plugins:\n                 module = importlib.import_module(\n                     self._path_to_module_name(self.searched_plugins[name])\n                 )\n+            else:\n+                raise RuntimeError(f\"Plugin not found: {name}! Check your plugin name\")\n \n             logger.opt(colors=True).success(\n                 f'Succeeded to import \"<y>{escape_tag(name)}</y>\"'\n             )\n-            return getattr(module, \"__plugin__\", None)\n+            plugin = getattr(module, \"__plugin__\", None)\n+            if plugin is None:\n+                raise RuntimeError(\n+                    f\"Module {module.__name__} is not loaded as a plugin! \"\n+                    \"Make sure not to import it before loading.\"\n+                )\n+            return plugin\n         except Exception as e:\n             logger.opt(colors=True, exception=e).error(\n                 f'<r><bg #f8bbd0>Failed to import \"{escape_tag(name)}\"</bg #f8bbd0></r>'\n@@ -129,7 +138,6 @@\n         target: Optional[ModuleType] = None,\n     ):\n         if _managers:\n-            index = -1\n             module_spec = PathFinder.find_spec(fullname, path, target)\n             if not module_spec:\n                 return\n@@ -138,17 +146,13 @@\n                 return\n             module_path = Path(module_origin).resolve()\n \n-            while -index <= len(_managers):\n-                manager = _managers[index]\n-\n+            for manager in reversed(_managers):\n                 if (\n                     fullname in manager.plugins\n                     or module_path in manager.searched_plugins.values()\n                 ):\n                     module_spec.loader = PluginLoader(manager, fullname, module_origin)\n                     return module_spec\n-\n-                index -= 1\n         return\n", "issue": "Bug: `require` \u91cd\u590d\u52a0\u8f7d\u63d2\u4ef6\u9519\u8bef\n**\u63cf\u8ff0\u95ee\u9898\uff1a**\r\n\r\n`require` load plugin raises `RuntimeError: Plugin already exists`\r\n\r\n**\u5982\u4f55\u590d\u73b0\uff1f**\r\n\r\n\u4f7f\u7528 `nonebot.load_from_toml([\"third_party_plugin\"], [\"plugin_dir\"])`\uff0c\u5e76\u5728\u63d2\u4ef6\u4e2d\u6dfb\u52a0 `require(\"third_party_plugin\")`\r\n\r\n\u7531\u4e8e\u52a0\u8f7d\u987a\u5e8f\u968f\u673a\uff0c\u6709\u4e00\u5b9a\u6982\u7387\u5931\u8d25\r\n\n", "before_files": [{"content": "\"\"\"\u672c\u6a21\u5757\u5b9a\u4e49\u63d2\u4ef6\u52a0\u8f7d\u63a5\u53e3\u3002\n\nFrontMatter:\n    sidebar_position: 1\n    description: nonebot.plugin.load \u6a21\u5757\n\"\"\"\nimport json\nimport warnings\nfrom typing import Set, Iterable, Optional\n\nimport tomlkit\n\nfrom . import _managers\nfrom .export import Export\nfrom .manager import PluginManager\nfrom .plugin import Plugin, get_plugin\n\n\ndef load_plugin(module_path: str) -> Optional[Plugin]:\n    \"\"\"\u52a0\u8f7d\u5355\u4e2a\u63d2\u4ef6\uff0c\u53ef\u4ee5\u662f\u672c\u5730\u63d2\u4ef6\u6216\u662f\u901a\u8fc7 `pip` \u5b89\u88c5\u7684\u63d2\u4ef6\u3002\n\n    \u53c2\u6570:\n        module_path: \u63d2\u4ef6\u540d\u79f0 `path.to.your.plugin`\n    \"\"\"\n\n    manager = PluginManager([module_path])\n    _managers.append(manager)\n    return manager.load_plugin(module_path)\n\n\ndef load_plugins(*plugin_dir: str) -> Set[Plugin]:\n    \"\"\"\u5bfc\u5165\u6587\u4ef6\u5939\u4e0b\u591a\u4e2a\u63d2\u4ef6\uff0c\u4ee5 `_` \u5f00\u5934\u7684\u63d2\u4ef6\u4e0d\u4f1a\u88ab\u5bfc\u5165!\n\n    \u53c2\u6570:\n        plugin_dir: \u6587\u4ef6\u5939\u8def\u5f84\n    \"\"\"\n    manager = PluginManager(search_path=plugin_dir)\n    _managers.append(manager)\n    return manager.load_all_plugins()\n\n\ndef load_all_plugins(\n    module_path: Iterable[str], plugin_dir: Iterable[str]\n) -> Set[Plugin]:\n    \"\"\"\u5bfc\u5165\u6307\u5b9a\u5217\u8868\u4e2d\u7684\u63d2\u4ef6\u4ee5\u53ca\u6307\u5b9a\u76ee\u5f55\u4e0b\u591a\u4e2a\u63d2\u4ef6\uff0c\u4ee5 `_` \u5f00\u5934\u7684\u63d2\u4ef6\u4e0d\u4f1a\u88ab\u5bfc\u5165!\n\n    \u53c2\u6570:\n        module_path: \u6307\u5b9a\u63d2\u4ef6\u96c6\u5408\n        plugin_dir: \u6307\u5b9a\u6587\u4ef6\u5939\u8def\u5f84\u96c6\u5408\n    \"\"\"\n    manager = PluginManager(module_path, plugin_dir)\n    _managers.append(manager)\n    return manager.load_all_plugins()\n\n\ndef load_from_json(file_path: str, encoding: str = \"utf-8\") -> Set[Plugin]:\n    \"\"\"\u5bfc\u5165\u6307\u5b9a json \u6587\u4ef6\u4e2d\u7684 `plugins` \u4ee5\u53ca `plugin_dirs` \u4e0b\u591a\u4e2a\u63d2\u4ef6\uff0c\u4ee5 `_` \u5f00\u5934\u7684\u63d2\u4ef6\u4e0d\u4f1a\u88ab\u5bfc\u5165!\n\n    \u53c2\u6570:\n        file_path: \u6307\u5b9a json \u6587\u4ef6\u8def\u5f84\n        encoding: \u6307\u5b9a json \u6587\u4ef6\u7f16\u7801\n\n    \u7528\u6cd5:\n        ```json title=plugins.json\n        {\n            \"plugins\": [\"some_plugin\"],\n            \"plugin_dirs\": [\"some_dir\"]\n        }\n        ```\n\n        ```python\n        nonebot.load_from_json(\"plugins.json\")\n        ```\n    \"\"\"\n    with open(file_path, \"r\", encoding=encoding) as f:\n        data = json.load(f)\n    plugins = data.get(\"plugins\")\n    plugin_dirs = data.get(\"plugin_dirs\")\n    assert isinstance(plugins, list), \"plugins must be a list of plugin name\"\n    assert isinstance(plugin_dirs, list), \"plugin_dirs must be a list of directories\"\n    return load_all_plugins(set(plugins), set(plugin_dirs))\n\n\ndef load_from_toml(file_path: str, encoding: str = \"utf-8\") -> Set[Plugin]:\n    \"\"\"\u5bfc\u5165\u6307\u5b9a toml \u6587\u4ef6 `[tool.nonebot]` \u4e2d\u7684 `plugins` \u4ee5\u53ca `plugin_dirs` \u4e0b\u591a\u4e2a\u63d2\u4ef6\uff0c\u4ee5 `_` \u5f00\u5934\u7684\u63d2\u4ef6\u4e0d\u4f1a\u88ab\u5bfc\u5165!\n\n    \u53c2\u6570:\n        file_path: \u6307\u5b9a toml \u6587\u4ef6\u8def\u5f84\n        encoding: \u6307\u5b9a toml \u6587\u4ef6\u7f16\u7801\n\n    \u7528\u6cd5:\n        ```toml title=pyproject.toml\n        [tool.nonebot]\n        plugins = [\"some_plugin\"]\n        plugin_dirs = [\"some_dir\"]\n        ```\n\n        ```python\n        nonebot.load_from_toml(\"pyproject.toml\")\n        ```\n    \"\"\"\n    with open(file_path, \"r\", encoding=encoding) as f:\n        data = tomlkit.parse(f.read())  # type: ignore\n\n    nonebot_data = data.get(\"tool\", {}).get(\"nonebot\")\n    if not nonebot_data:\n        nonebot_data = data.get(\"nonebot\", {}).get(\"plugins\")\n        if nonebot_data:\n            warnings.warn(\n                \"[nonebot.plugins] table are now deprecated. Use [tool.nonebot] instead.\",\n                DeprecationWarning,\n            )\n        else:\n            raise ValueError(\"Cannot find '[tool.nonebot]' in given toml file!\")\n    plugins = nonebot_data.get(\"plugins\", [])\n    plugin_dirs = nonebot_data.get(\"plugin_dirs\", [])\n    assert isinstance(plugins, list), \"plugins must be a list of plugin name\"\n    assert isinstance(plugin_dirs, list), \"plugin_dirs must be a list of directories\"\n    return load_all_plugins(plugins, plugin_dirs)\n\n\ndef load_builtin_plugin(name: str) -> Optional[Plugin]:\n    \"\"\"\u5bfc\u5165 NoneBot \u5185\u7f6e\u63d2\u4ef6\u3002\n\n    \u53c2\u6570:\n        name: \u63d2\u4ef6\u540d\u79f0\n    \"\"\"\n    return load_plugin(f\"nonebot.plugins.{name}\")\n\n\ndef load_builtin_plugins(*plugins) -> Set[Plugin]:\n    \"\"\"\u5bfc\u5165\u591a\u4e2a NoneBot \u5185\u7f6e\u63d2\u4ef6\u3002\n\n    \u53c2\u6570:\n        plugins: \u63d2\u4ef6\u540d\u79f0\u5217\u8868\n    \"\"\"\n    return load_all_plugins([f\"nonebot.plugins.{p}\" for p in plugins], [])\n\n\ndef require(name: str) -> Export:\n    \"\"\"\u83b7\u53d6\u4e00\u4e2a\u63d2\u4ef6\u7684\u5bfc\u51fa\u5185\u5bb9\u3002\n\n    \u5982\u679c\u4e3a `load_plugins` \u6587\u4ef6\u5939\u5bfc\u5165\u7684\u63d2\u4ef6\uff0c\u5219\u4e3a\u6587\u4ef6(\u5939)\u540d\u3002\n\n    \u53c2\u6570:\n        name: \u63d2\u4ef6\u540d\uff0c\u5373 {ref}`nonebot.plugin.plugin.Plugin.name`\u3002\n\n    \u5f02\u5e38:\n        RuntimeError: \u63d2\u4ef6\u65e0\u6cd5\u52a0\u8f7d\n    \"\"\"\n    plugin = get_plugin(name) or load_plugin(name)\n    if not plugin:\n        raise RuntimeError(f'Cannot load plugin \"{name}\"!')\n    return plugin.export\n", "path": "nonebot/plugin/load.py"}, {"content": "\"\"\"\u672c\u6a21\u5757\u5b9e\u73b0\u63d2\u4ef6\u52a0\u8f7d\u6d41\u7a0b\u3002\n\n\u53c2\u8003: [import hooks](https://docs.python.org/3/reference/import.html#import-hooks), [PEP302](https://www.python.org/dev/peps/pep-0302/)\n\nFrontMatter:\n    sidebar_position: 5\n    description: nonebot.plugin.manager \u6a21\u5757\n\"\"\"\nimport sys\nimport pkgutil\nimport importlib\nfrom pathlib import Path\nfrom itertools import chain\nfrom types import ModuleType\nfrom importlib.abc import MetaPathFinder\nfrom importlib.machinery import PathFinder, SourceFileLoader\nfrom typing import Set, Dict, List, Union, Iterable, Optional, Sequence\n\nfrom nonebot.log import logger\nfrom nonebot.utils import escape_tag\n\nfrom . import _managers, _current_plugin\nfrom .plugin import Plugin, _new_plugin, _confirm_plugin\n\n\nclass PluginManager:\n    def __init__(\n        self,\n        plugins: Optional[Iterable[str]] = None,\n        search_path: Optional[Iterable[str]] = None,\n    ):\n\n        # simple plugin not in search path\n        self.plugins: Set[str] = set(plugins or [])\n        self.search_path: Set[str] = set(search_path or [])\n        # cache plugins\n        self.searched_plugins: Dict[str, Path] = {}\n        self.list_plugins()\n\n    def _path_to_module_name(self, path: Path) -> str:\n        rel_path = path.resolve().relative_to(Path(\".\").resolve())\n        if rel_path.stem == \"__init__\":\n            return \".\".join(rel_path.parts[:-1])\n        else:\n            return \".\".join(rel_path.parts[:-1] + (rel_path.stem,))\n\n    def _previous_plugins(self) -> List[str]:\n        _pre_managers: List[PluginManager]\n        if self in _managers:\n            _pre_managers = _managers[: _managers.index(self)]\n        else:\n            _pre_managers = _managers[:]\n\n        return [\n            *chain.from_iterable(\n                [*manager.plugins, *manager.searched_plugins.keys()]\n                for manager in _pre_managers\n            )\n        ]\n\n    def list_plugins(self) -> Set[str]:\n        # get all previous ready to load plugins\n        previous_plugins = self._previous_plugins()\n        searched_plugins: Dict[str, Path] = {}\n        third_party_plugins: Set[str] = set()\n\n        for plugin in self.plugins:\n            name = plugin.rsplit(\".\", 1)[-1] if \".\" in plugin else plugin\n            if name in third_party_plugins or name in previous_plugins:\n                raise RuntimeError(\n                    f\"Plugin already exists: {name}! Check your plugin name\"\n                )\n            third_party_plugins.add(plugin)\n\n        for module_info in pkgutil.iter_modules(self.search_path):\n            if module_info.name.startswith(\"_\"):\n                continue\n            if (\n                module_info.name in searched_plugins.keys()\n                or module_info.name in previous_plugins\n                or module_info.name in third_party_plugins\n            ):\n                raise RuntimeError(\n                    f\"Plugin already exists: {module_info.name}! Check your plugin name\"\n                )\n            module_spec = module_info.module_finder.find_spec(module_info.name, None)\n            if not module_spec:\n                continue\n            module_path = module_spec.origin\n            if not module_path:\n                continue\n            searched_plugins[module_info.name] = Path(module_path).resolve()\n\n        self.searched_plugins = searched_plugins\n\n        return third_party_plugins | set(self.searched_plugins.keys())\n\n    def load_plugin(self, name) -> Optional[Plugin]:\n        try:\n            if name in self.plugins:\n                module = importlib.import_module(name)\n            elif name not in self.searched_plugins:\n                raise RuntimeError(f\"Plugin not found: {name}! Check your plugin name\")\n            else:\n                module = importlib.import_module(\n                    self._path_to_module_name(self.searched_plugins[name])\n                )\n\n            logger.opt(colors=True).success(\n                f'Succeeded to import \"<y>{escape_tag(name)}</y>\"'\n            )\n            return getattr(module, \"__plugin__\", None)\n        except Exception as e:\n            logger.opt(colors=True, exception=e).error(\n                f'<r><bg #f8bbd0>Failed to import \"{escape_tag(name)}\"</bg #f8bbd0></r>'\n            )\n\n    def load_all_plugins(self) -> Set[Plugin]:\n        return set(\n            filter(None, (self.load_plugin(name) for name in self.list_plugins()))\n        )\n\n\nclass PluginFinder(MetaPathFinder):\n    def find_spec(\n        self,\n        fullname: str,\n        path: Optional[Sequence[Union[bytes, str]]],\n        target: Optional[ModuleType] = None,\n    ):\n        if _managers:\n            index = -1\n            module_spec = PathFinder.find_spec(fullname, path, target)\n            if not module_spec:\n                return\n            module_origin = module_spec.origin\n            if not module_origin:\n                return\n            module_path = Path(module_origin).resolve()\n\n            while -index <= len(_managers):\n                manager = _managers[index]\n\n                if (\n                    fullname in manager.plugins\n                    or module_path in manager.searched_plugins.values()\n                ):\n                    module_spec.loader = PluginLoader(manager, fullname, module_origin)\n                    return module_spec\n\n                index -= 1\n        return\n\n\nclass PluginLoader(SourceFileLoader):\n    def __init__(self, manager: PluginManager, fullname: str, path) -> None:\n        self.manager = manager\n        self.loaded = False\n        super().__init__(fullname, path)\n\n    def create_module(self, spec) -> Optional[ModuleType]:\n        if self.name in sys.modules:\n            self.loaded = True\n            return sys.modules[self.name]\n        # return None to use default module creation\n        return super().create_module(spec)\n\n    def exec_module(self, module: ModuleType) -> None:\n        if self.loaded:\n            return\n\n        plugin = _new_plugin(self.name, module, self.manager)\n        parent_plugin = _current_plugin.get()\n        if parent_plugin and _managers.index(parent_plugin.manager) < _managers.index(\n            self.manager\n        ):\n            plugin.parent_plugin = parent_plugin\n            parent_plugin.sub_plugins.add(plugin)\n\n        _plugin_token = _current_plugin.set(plugin)\n\n        setattr(module, \"__plugin__\", plugin)\n\n        # try:\n        #     super().exec_module(module)\n        # except Exception as e:\n        #     raise ImportError(\n        #         f\"Error when executing module {module_name} from {module.__file__}.\"\n        #     ) from e\n        super().exec_module(module)\n\n        _confirm_plugin(plugin)\n\n        _current_plugin.reset(_plugin_token)\n        return\n\n\nsys.meta_path.insert(0, PluginFinder())\n", "path": "nonebot/plugin/manager.py"}], "after_files": [{"content": "\"\"\"\u672c\u6a21\u5757\u5b9a\u4e49\u63d2\u4ef6\u52a0\u8f7d\u63a5\u53e3\u3002\n\nFrontMatter:\n    sidebar_position: 1\n    description: nonebot.plugin.load \u6a21\u5757\n\"\"\"\nimport json\nimport warnings\nfrom typing import Set, Iterable, Optional\n\nimport tomlkit\n\nfrom . import _managers\nfrom .export import Export\nfrom .manager import PluginManager\nfrom .plugin import Plugin, get_plugin\n\n\ndef load_plugin(module_path: str) -> Optional[Plugin]:\n    \"\"\"\u52a0\u8f7d\u5355\u4e2a\u63d2\u4ef6\uff0c\u53ef\u4ee5\u662f\u672c\u5730\u63d2\u4ef6\u6216\u662f\u901a\u8fc7 `pip` \u5b89\u88c5\u7684\u63d2\u4ef6\u3002\n\n    \u53c2\u6570:\n        module_path: \u63d2\u4ef6\u540d\u79f0 `path.to.your.plugin`\n    \"\"\"\n\n    manager = PluginManager([module_path])\n    _managers.append(manager)\n    return manager.load_plugin(module_path)\n\n\ndef load_plugins(*plugin_dir: str) -> Set[Plugin]:\n    \"\"\"\u5bfc\u5165\u6587\u4ef6\u5939\u4e0b\u591a\u4e2a\u63d2\u4ef6\uff0c\u4ee5 `_` \u5f00\u5934\u7684\u63d2\u4ef6\u4e0d\u4f1a\u88ab\u5bfc\u5165!\n\n    \u53c2\u6570:\n        plugin_dir: \u6587\u4ef6\u5939\u8def\u5f84\n    \"\"\"\n    manager = PluginManager(search_path=plugin_dir)\n    _managers.append(manager)\n    return manager.load_all_plugins()\n\n\ndef load_all_plugins(\n    module_path: Iterable[str], plugin_dir: Iterable[str]\n) -> Set[Plugin]:\n    \"\"\"\u5bfc\u5165\u6307\u5b9a\u5217\u8868\u4e2d\u7684\u63d2\u4ef6\u4ee5\u53ca\u6307\u5b9a\u76ee\u5f55\u4e0b\u591a\u4e2a\u63d2\u4ef6\uff0c\u4ee5 `_` \u5f00\u5934\u7684\u63d2\u4ef6\u4e0d\u4f1a\u88ab\u5bfc\u5165!\n\n    \u53c2\u6570:\n        module_path: \u6307\u5b9a\u63d2\u4ef6\u96c6\u5408\n        plugin_dir: \u6307\u5b9a\u6587\u4ef6\u5939\u8def\u5f84\u96c6\u5408\n    \"\"\"\n    manager = PluginManager(module_path, plugin_dir)\n    _managers.append(manager)\n    return manager.load_all_plugins()\n\n\ndef load_from_json(file_path: str, encoding: str = \"utf-8\") -> Set[Plugin]:\n    \"\"\"\u5bfc\u5165\u6307\u5b9a json \u6587\u4ef6\u4e2d\u7684 `plugins` \u4ee5\u53ca `plugin_dirs` \u4e0b\u591a\u4e2a\u63d2\u4ef6\uff0c\u4ee5 `_` \u5f00\u5934\u7684\u63d2\u4ef6\u4e0d\u4f1a\u88ab\u5bfc\u5165!\n\n    \u53c2\u6570:\n        file_path: \u6307\u5b9a json \u6587\u4ef6\u8def\u5f84\n        encoding: \u6307\u5b9a json \u6587\u4ef6\u7f16\u7801\n\n    \u7528\u6cd5:\n        ```json title=plugins.json\n        {\n            \"plugins\": [\"some_plugin\"],\n            \"plugin_dirs\": [\"some_dir\"]\n        }\n        ```\n\n        ```python\n        nonebot.load_from_json(\"plugins.json\")\n        ```\n    \"\"\"\n    with open(file_path, \"r\", encoding=encoding) as f:\n        data = json.load(f)\n    plugins = data.get(\"plugins\")\n    plugin_dirs = data.get(\"plugin_dirs\")\n    assert isinstance(plugins, list), \"plugins must be a list of plugin name\"\n    assert isinstance(plugin_dirs, list), \"plugin_dirs must be a list of directories\"\n    return load_all_plugins(set(plugins), set(plugin_dirs))\n\n\ndef load_from_toml(file_path: str, encoding: str = \"utf-8\") -> Set[Plugin]:\n    \"\"\"\u5bfc\u5165\u6307\u5b9a toml \u6587\u4ef6 `[tool.nonebot]` \u4e2d\u7684 `plugins` \u4ee5\u53ca `plugin_dirs` \u4e0b\u591a\u4e2a\u63d2\u4ef6\uff0c\u4ee5 `_` \u5f00\u5934\u7684\u63d2\u4ef6\u4e0d\u4f1a\u88ab\u5bfc\u5165!\n\n    \u53c2\u6570:\n        file_path: \u6307\u5b9a toml \u6587\u4ef6\u8def\u5f84\n        encoding: \u6307\u5b9a toml \u6587\u4ef6\u7f16\u7801\n\n    \u7528\u6cd5:\n        ```toml title=pyproject.toml\n        [tool.nonebot]\n        plugins = [\"some_plugin\"]\n        plugin_dirs = [\"some_dir\"]\n        ```\n\n        ```python\n        nonebot.load_from_toml(\"pyproject.toml\")\n        ```\n    \"\"\"\n    with open(file_path, \"r\", encoding=encoding) as f:\n        data = tomlkit.parse(f.read())  # type: ignore\n\n    nonebot_data = data.get(\"tool\", {}).get(\"nonebot\")\n    if not nonebot_data:\n        nonebot_data = data.get(\"nonebot\", {}).get(\"plugins\")\n        if nonebot_data:\n            warnings.warn(\n                \"[nonebot.plugins] table are now deprecated. Use [tool.nonebot] instead.\",\n                DeprecationWarning,\n            )\n        else:\n            raise ValueError(\"Cannot find '[tool.nonebot]' in given toml file!\")\n    plugins = nonebot_data.get(\"plugins\", [])\n    plugin_dirs = nonebot_data.get(\"plugin_dirs\", [])\n    assert isinstance(plugins, list), \"plugins must be a list of plugin name\"\n    assert isinstance(plugin_dirs, list), \"plugin_dirs must be a list of directories\"\n    return load_all_plugins(plugins, plugin_dirs)\n\n\ndef load_builtin_plugin(name: str) -> Optional[Plugin]:\n    \"\"\"\u5bfc\u5165 NoneBot \u5185\u7f6e\u63d2\u4ef6\u3002\n\n    \u53c2\u6570:\n        name: \u63d2\u4ef6\u540d\u79f0\n    \"\"\"\n    return load_plugin(f\"nonebot.plugins.{name}\")\n\n\ndef load_builtin_plugins(*plugins) -> Set[Plugin]:\n    \"\"\"\u5bfc\u5165\u591a\u4e2a NoneBot \u5185\u7f6e\u63d2\u4ef6\u3002\n\n    \u53c2\u6570:\n        plugins: \u63d2\u4ef6\u540d\u79f0\u5217\u8868\n    \"\"\"\n    return load_all_plugins([f\"nonebot.plugins.{p}\" for p in plugins], [])\n\n\ndef _find_manager_by_name(name: str) -> Optional[PluginManager]:\n    for manager in reversed(_managers):\n        if name in manager.plugins or name in manager.searched_plugins:\n            return manager\n\n\ndef require(name: str) -> Export:\n    \"\"\"\u83b7\u53d6\u4e00\u4e2a\u63d2\u4ef6\u7684\u5bfc\u51fa\u5185\u5bb9\u3002\n\n    \u5982\u679c\u4e3a `load_plugins` \u6587\u4ef6\u5939\u5bfc\u5165\u7684\u63d2\u4ef6\uff0c\u5219\u4e3a\u6587\u4ef6(\u5939)\u540d\u3002\n\n    \u53c2\u6570:\n        name: \u63d2\u4ef6\u540d\uff0c\u5373 {ref}`nonebot.plugin.plugin.Plugin.name`\u3002\n\n    \u5f02\u5e38:\n        RuntimeError: \u63d2\u4ef6\u65e0\u6cd5\u52a0\u8f7d\n    \"\"\"\n    plugin = get_plugin(name.rsplit(\".\", 1)[-1])\n    if not plugin:\n        manager = _find_manager_by_name(name)\n        if manager:\n            plugin = manager.load_plugin(name)\n        else:\n            plugin = load_plugin(name)\n        if not plugin:\n            raise RuntimeError(f'Cannot load plugin \"{name}\"!')\n    return plugin.export\n", "path": "nonebot/plugin/load.py"}, {"content": "\"\"\"\u672c\u6a21\u5757\u5b9e\u73b0\u63d2\u4ef6\u52a0\u8f7d\u6d41\u7a0b\u3002\n\n\u53c2\u8003: [import hooks](https://docs.python.org/3/reference/import.html#import-hooks), [PEP302](https://www.python.org/dev/peps/pep-0302/)\n\nFrontMatter:\n    sidebar_position: 5\n    description: nonebot.plugin.manager \u6a21\u5757\n\"\"\"\nimport sys\nimport pkgutil\nimport importlib\nfrom pathlib import Path\nfrom itertools import chain\nfrom types import ModuleType\nfrom importlib.abc import MetaPathFinder\nfrom importlib.machinery import PathFinder, SourceFileLoader\nfrom typing import Set, Dict, List, Union, Iterable, Optional, Sequence\n\nfrom nonebot.log import logger\nfrom nonebot.utils import escape_tag\n\nfrom . import _managers, _current_plugin\nfrom .plugin import Plugin, _new_plugin, _confirm_plugin\n\n\nclass PluginManager:\n    def __init__(\n        self,\n        plugins: Optional[Iterable[str]] = None,\n        search_path: Optional[Iterable[str]] = None,\n    ):\n\n        # simple plugin not in search path\n        self.plugins: Set[str] = set(plugins or [])\n        self.search_path: Set[str] = set(search_path or [])\n        # cache plugins\n        self.searched_plugins: Dict[str, Path] = {}\n        self.list_plugins()\n\n    def _path_to_module_name(self, path: Path) -> str:\n        rel_path = path.resolve().relative_to(Path(\".\").resolve())\n        if rel_path.stem == \"__init__\":\n            return \".\".join(rel_path.parts[:-1])\n        else:\n            return \".\".join(rel_path.parts[:-1] + (rel_path.stem,))\n\n    def _previous_plugins(self) -> List[str]:\n        _pre_managers: List[PluginManager]\n        if self in _managers:\n            _pre_managers = _managers[: _managers.index(self)]\n        else:\n            _pre_managers = _managers[:]\n\n        return [\n            *chain.from_iterable(\n                [\n                    *map(lambda x: x.rsplit(\".\", 1)[-1], manager.plugins),\n                    *manager.searched_plugins.keys(),\n                ]\n                for manager in _pre_managers\n            )\n        ]\n\n    def list_plugins(self) -> Set[str]:\n        # get all previous ready to load plugins\n        previous_plugins = self._previous_plugins()\n        searched_plugins: Dict[str, Path] = {}\n        third_party_plugins: Set[str] = set()\n\n        for plugin in self.plugins:\n            name = plugin.rsplit(\".\", 1)[-1]\n            if name in third_party_plugins or name in previous_plugins:\n                raise RuntimeError(\n                    f\"Plugin already exists: {name}! Check your plugin name\"\n                )\n            third_party_plugins.add(plugin)\n\n        for module_info in pkgutil.iter_modules(self.search_path):\n            if module_info.name.startswith(\"_\"):\n                continue\n            if (\n                module_info.name in searched_plugins.keys()\n                or module_info.name in previous_plugins\n                or module_info.name in third_party_plugins\n            ):\n                raise RuntimeError(\n                    f\"Plugin already exists: {module_info.name}! Check your plugin name\"\n                )\n            module_spec = module_info.module_finder.find_spec(module_info.name, None)\n            if not module_spec:\n                continue\n            module_path = module_spec.origin\n            if not module_path:\n                continue\n            searched_plugins[module_info.name] = Path(module_path).resolve()\n\n        self.searched_plugins = searched_plugins\n\n        return third_party_plugins | set(self.searched_plugins.keys())\n\n    def load_plugin(self, name: str) -> Optional[Plugin]:\n        try:\n            if name in self.plugins:\n                module = importlib.import_module(name)\n            elif name in self.searched_plugins:\n                module = importlib.import_module(\n                    self._path_to_module_name(self.searched_plugins[name])\n                )\n            else:\n                raise RuntimeError(f\"Plugin not found: {name}! Check your plugin name\")\n\n            logger.opt(colors=True).success(\n                f'Succeeded to import \"<y>{escape_tag(name)}</y>\"'\n            )\n            plugin = getattr(module, \"__plugin__\", None)\n            if plugin is None:\n                raise RuntimeError(\n                    f\"Module {module.__name__} is not loaded as a plugin! \"\n                    \"Make sure not to import it before loading.\"\n                )\n            return plugin\n        except Exception as e:\n            logger.opt(colors=True, exception=e).error(\n                f'<r><bg #f8bbd0>Failed to import \"{escape_tag(name)}\"</bg #f8bbd0></r>'\n            )\n\n    def load_all_plugins(self) -> Set[Plugin]:\n        return set(\n            filter(None, (self.load_plugin(name) for name in self.list_plugins()))\n        )\n\n\nclass PluginFinder(MetaPathFinder):\n    def find_spec(\n        self,\n        fullname: str,\n        path: Optional[Sequence[Union[bytes, str]]],\n        target: Optional[ModuleType] = None,\n    ):\n        if _managers:\n            module_spec = PathFinder.find_spec(fullname, path, target)\n            if not module_spec:\n                return\n            module_origin = module_spec.origin\n            if not module_origin:\n                return\n            module_path = Path(module_origin).resolve()\n\n            for manager in reversed(_managers):\n                if (\n                    fullname in manager.plugins\n                    or module_path in manager.searched_plugins.values()\n                ):\n                    module_spec.loader = PluginLoader(manager, fullname, module_origin)\n                    return module_spec\n        return\n\n\nclass PluginLoader(SourceFileLoader):\n    def __init__(self, manager: PluginManager, fullname: str, path) -> None:\n        self.manager = manager\n        self.loaded = False\n        super().__init__(fullname, path)\n\n    def create_module(self, spec) -> Optional[ModuleType]:\n        if self.name in sys.modules:\n            self.loaded = True\n            return sys.modules[self.name]\n        # return None to use default module creation\n        return super().create_module(spec)\n\n    def exec_module(self, module: ModuleType) -> None:\n        if self.loaded:\n            return\n\n        plugin = _new_plugin(self.name, module, self.manager)\n        parent_plugin = _current_plugin.get()\n        if parent_plugin and _managers.index(parent_plugin.manager) < _managers.index(\n            self.manager\n        ):\n            plugin.parent_plugin = parent_plugin\n            parent_plugin.sub_plugins.add(plugin)\n\n        _plugin_token = _current_plugin.set(plugin)\n\n        setattr(module, \"__plugin__\", plugin)\n\n        # try:\n        #     super().exec_module(module)\n        # except Exception as e:\n        #     raise ImportError(\n        #         f\"Error when executing module {module_name} from {module.__file__}.\"\n        #     ) from e\n        super().exec_module(module)\n\n        _confirm_plugin(plugin)\n\n        _current_plugin.reset(_plugin_token)\n        return\n\n\nsys.meta_path.insert(0, PluginFinder())\n", "path": "nonebot/plugin/manager.py"}]}