We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Bug: 插件加载日志存在歧义
1. 先 success 再报错
2. 当插件模块名内含 `.` 时，实际插件名和模块名不一致

https://github.com/nonebot/nonebot2/blob/1dc02bfe8e9e481b7b22f71fa878463e798f4114/nonebot/plugin/manager.py#L151-L158

3. 这里使用了已经处理过的名字即插件名，日志显示名称会与实际用户提供名称不一致，产生迷惑

https://github.com/nonebot/nonebot2/blob/1dc02bfe8e9e481b7b22f71fa878463e798f4114/nonebot/plugin/manager.py#L165-L170

--- 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/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, Iterable, Optional, Sequence
18 
19 from nonebot.log import logger
20 from nonebot.utils import escape_tag, path_to_module_name
21 
22 from .plugin import Plugin, PluginMetadata
23 from . import (
24     _managers,
25     _new_plugin,
26     _revert_plugin,
27     _current_plugin_chain,
28     _module_name_to_plugin_name,
29 )
30 
31 
32 class PluginManager:
33     """插件管理器。
34 
35     参数:
36         plugins: 独立插件模块名集合。
37         search_path: 插件搜索路径（文件夹）。
38     """
39 
40     def __init__(
41         self,
42         plugins: Optional[Iterable[str]] = None,
43         search_path: Optional[Iterable[str]] = None,
44     ):
45         # simple plugin not in search path
46         self.plugins: Set[str] = set(plugins or [])
47         self.search_path: Set[str] = set(search_path or [])
48 
49         # cache plugins
50         self._third_party_plugin_names: Dict[str, str] = {}
51         self._searched_plugin_names: Dict[str, Path] = {}
52         self.prepare_plugins()
53 
54     def __repr__(self) -> str:
55         return f"PluginManager(plugins={self.plugins}, search_path={self.search_path})"
56 
57     @property
58     def third_party_plugins(self) -> Set[str]:
59         """返回所有独立插件名称。"""
60         return set(self._third_party_plugin_names.keys())
61 
62     @property
63     def searched_plugins(self) -> Set[str]:
64         """返回已搜索到的插件名称。"""
65         return set(self._searched_plugin_names.keys())
66 
67     @property
68     def available_plugins(self) -> Set[str]:
69         """返回当前插件管理器中可用的插件名称。"""
70         return self.third_party_plugins | self.searched_plugins
71 
72     def _previous_plugins(self) -> Set[str]:
73         _pre_managers: List[PluginManager]
74         if self in _managers:
75             _pre_managers = _managers[: _managers.index(self)]
76         else:
77             _pre_managers = _managers[:]
78 
79         return {
80             *chain.from_iterable(manager.available_plugins for manager in _pre_managers)
81         }
82 
83     def prepare_plugins(self) -> Set[str]:
84         """搜索插件并缓存插件名称。"""
85         # get all previous ready to load plugins
86         previous_plugins = self._previous_plugins()
87         searched_plugins: Dict[str, Path] = {}
88         third_party_plugins: Dict[str, str] = {}
89 
90         # check third party plugins
91         for plugin in self.plugins:
92             name = _module_name_to_plugin_name(plugin)
93             if name in third_party_plugins or name in previous_plugins:
94                 raise RuntimeError(
95                     f"Plugin already exists: {name}! Check your plugin name"
96                 )
97             third_party_plugins[name] = plugin
98 
99         self._third_party_plugin_names = third_party_plugins
100 
101         # check plugins in search path
102         for module_info in pkgutil.iter_modules(self.search_path):
103             # ignore if startswith "_"
104             if module_info.name.startswith("_"):
105                 continue
106 
107             if (
108                 module_info.name in searched_plugins
109                 or module_info.name in previous_plugins
110                 or module_info.name in third_party_plugins
111             ):
112                 raise RuntimeError(
113                     f"Plugin already exists: {module_info.name}! Check your plugin name"
114                 )
115 
116             if not (
117                 module_spec := module_info.module_finder.find_spec(
118                     module_info.name, None
119                 )
120             ):
121                 continue
122             if not (module_path := module_spec.origin):
123                 continue
124             searched_plugins[module_info.name] = Path(module_path).resolve()
125 
126         self._searched_plugin_names = searched_plugins
127 
128         return self.available_plugins
129 
130     def load_plugin(self, name: str) -> Optional[Plugin]:
131         """加载指定插件。
132 
133         对于独立插件，可以使用完整插件模块名或者插件名称。
134 
135         参数:
136             name: 插件名称。
137         """
138 
139         try:
140             if name in self.plugins:
141                 module = importlib.import_module(name)
142             elif name in self._third_party_plugin_names:
143                 module = importlib.import_module(self._third_party_plugin_names[name])
144             elif name in self._searched_plugin_names:
145                 module = importlib.import_module(
146                     path_to_module_name(self._searched_plugin_names[name])
147                 )
148             else:
149                 raise RuntimeError(f"Plugin not found: {name}! Check your plugin name")
150 
151             logger.opt(colors=True).success(
152                 f'Succeeded to import "<y>{escape_tag(name)}</y>"'
153             )
154             if (plugin := getattr(module, "__plugin__", None)) is None:
155                 raise RuntimeError(
156                     f"Module {module.__name__} is not loaded as a plugin! "
157                     "Make sure not to import it before loading."
158                 )
159             return plugin
160         except Exception as e:
161             logger.opt(colors=True, exception=e).error(
162                 f'<r><bg #f8bbd0>Failed to import "{escape_tag(name)}"</bg #f8bbd0></r>'
163             )
164 
165     def load_all_plugins(self) -> Set[Plugin]:
166         """加载所有可用插件。"""
167 
168         return set(
169             filter(None, (self.load_plugin(name) for name in self.available_plugins))
170         )
171 
172 
173 class PluginFinder(MetaPathFinder):
174     def find_spec(
175         self,
176         fullname: str,
177         path: Optional[Sequence[str]],
178         target: Optional[ModuleType] = None,
179     ):
180         if _managers:
181             module_spec = PathFinder.find_spec(fullname, path, target)
182             if not module_spec:
183                 return
184             module_origin = module_spec.origin
185             if not module_origin:
186                 return
187             module_path = Path(module_origin).resolve()
188 
189             for manager in reversed(_managers):
190                 # use path instead of name in case of submodule name conflict
191                 if (
192                     fullname in manager.plugins
193                     or module_path in manager._searched_plugin_names.values()
194                 ):
195                     module_spec.loader = PluginLoader(manager, fullname, module_origin)
196                     return module_spec
197         return
198 
199 
200 class PluginLoader(SourceFileLoader):
201     def __init__(self, manager: PluginManager, fullname: str, path) -> None:
202         self.manager = manager
203         self.loaded = False
204         super().__init__(fullname, path)
205 
206     def create_module(self, spec) -> Optional[ModuleType]:
207         if self.name in sys.modules:
208             self.loaded = True
209             return sys.modules[self.name]
210         # return None to use default module creation
211         return super().create_module(spec)
212 
213     def exec_module(self, module: ModuleType) -> None:
214         if self.loaded:
215             return
216 
217         # create plugin before executing
218         plugin = _new_plugin(self.name, module, self.manager)
219         setattr(module, "__plugin__", plugin)
220 
221         # detect parent plugin before entering current plugin context
222         parent_plugins = _current_plugin_chain.get()
223         for pre_plugin in reversed(parent_plugins):
224             if _managers.index(pre_plugin.manager) < _managers.index(self.manager):
225                 plugin.parent_plugin = pre_plugin
226                 pre_plugin.sub_plugins.add(plugin)
227                 break
228 
229         # enter plugin context
230         _plugin_token = _current_plugin_chain.set(parent_plugins + (plugin,))
231 
232         try:
233             super().exec_module(module)
234         except Exception:
235             _revert_plugin(plugin)
236             raise
237         finally:
238             # leave plugin context
239             _current_plugin_chain.reset(_plugin_token)
240 
241         # get plugin metadata
242         metadata: Optional[PluginMetadata] = getattr(module, "__plugin_meta__", None)
243         plugin.metadata = metadata
244 
245         return
246 
247 
248 sys.meta_path.insert(0, PluginFinder())
249
```
--- 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/manager.py b/nonebot/plugin/manager.py
--- a/nonebot/plugin/manager.py
+++ b/nonebot/plugin/manager.py
@@ -148,14 +148,21 @@
             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>"'
-            )
-            if (plugin := getattr(module, "__plugin__", None)) is None:
+            if (
+                plugin := getattr(module, "__plugin__", None)
+            ) is None or not isinstance(plugin, Plugin):
                 raise RuntimeError(
                     f"Module {module.__name__} is not loaded as a plugin! "
                     "Make sure not to import it before loading."
                 )
+            logger.opt(colors=True).success(
+                f'Succeeded to load plugin "<y>{escape_tag(plugin.name)}</y>"'
+                + (
+                    f' from "<m>{escape_tag(plugin.module_name)}</m>"'
+                    if plugin.module_name != plugin.name
+                    else ""
+                )
+            )
             return plugin
         except Exception as e:
             logger.opt(colors=True, exception=e).error(

{"golden_diff": "diff --git a/nonebot/plugin/manager.py b/nonebot/plugin/manager.py\n--- a/nonebot/plugin/manager.py\n+++ b/nonebot/plugin/manager.py\n@@ -148,14 +148,21 @@\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-            if (plugin := getattr(module, \"__plugin__\", None)) is None:\n+            if (\n+                plugin := getattr(module, \"__plugin__\", None)\n+            ) is None or not isinstance(plugin, Plugin):\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+            logger.opt(colors=True).success(\n+                f'Succeeded to load plugin \"<y>{escape_tag(plugin.name)}</y>\"'\n+                + (\n+                    f' from \"<m>{escape_tag(plugin.module_name)}</m>\"'\n+                    if plugin.module_name != plugin.name\n+                    else \"\"\n+                )\n+            )\n             return plugin\n         except Exception as e:\n             logger.opt(colors=True, exception=e).error(\n", "issue": "Bug: \u63d2\u4ef6\u52a0\u8f7d\u65e5\u5fd7\u5b58\u5728\u6b67\u4e49\n1. \u5148 success \u518d\u62a5\u9519\r\n2. \u5f53\u63d2\u4ef6\u6a21\u5757\u540d\u5185\u542b `.` \u65f6\uff0c\u5b9e\u9645\u63d2\u4ef6\u540d\u548c\u6a21\u5757\u540d\u4e0d\u4e00\u81f4\r\n\r\nhttps://github.com/nonebot/nonebot2/blob/1dc02bfe8e9e481b7b22f71fa878463e798f4114/nonebot/plugin/manager.py#L151-L158\r\n\r\n3. \u8fd9\u91cc\u4f7f\u7528\u4e86\u5df2\u7ecf\u5904\u7406\u8fc7\u7684\u540d\u5b57\u5373\u63d2\u4ef6\u540d\uff0c\u65e5\u5fd7\u663e\u793a\u540d\u79f0\u4f1a\u4e0e\u5b9e\u9645\u7528\u6237\u63d0\u4f9b\u540d\u79f0\u4e0d\u4e00\u81f4\uff0c\u4ea7\u751f\u8ff7\u60d1\r\n\r\nhttps://github.com/nonebot/nonebot2/blob/1dc02bfe8e9e481b7b22f71fa878463e798f4114/nonebot/plugin/manager.py#L165-L170\n", "before_files": [{"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, Iterable, Optional, Sequence\n\nfrom nonebot.log import logger\nfrom nonebot.utils import escape_tag, path_to_module_name\n\nfrom .plugin import Plugin, PluginMetadata\nfrom . import (\n    _managers,\n    _new_plugin,\n    _revert_plugin,\n    _current_plugin_chain,\n    _module_name_to_plugin_name,\n)\n\n\nclass PluginManager:\n    \"\"\"\u63d2\u4ef6\u7ba1\u7406\u5668\u3002\n\n    \u53c2\u6570:\n        plugins: \u72ec\u7acb\u63d2\u4ef6\u6a21\u5757\u540d\u96c6\u5408\u3002\n        search_path: \u63d2\u4ef6\u641c\u7d22\u8def\u5f84\uff08\u6587\u4ef6\u5939\uff09\u3002\n    \"\"\"\n\n    def __init__(\n        self,\n        plugins: Optional[Iterable[str]] = None,\n        search_path: Optional[Iterable[str]] = None,\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\n        # cache plugins\n        self._third_party_plugin_names: Dict[str, str] = {}\n        self._searched_plugin_names: Dict[str, Path] = {}\n        self.prepare_plugins()\n\n    def __repr__(self) -> str:\n        return f\"PluginManager(plugins={self.plugins}, search_path={self.search_path})\"\n\n    @property\n    def third_party_plugins(self) -> Set[str]:\n        \"\"\"\u8fd4\u56de\u6240\u6709\u72ec\u7acb\u63d2\u4ef6\u540d\u79f0\u3002\"\"\"\n        return set(self._third_party_plugin_names.keys())\n\n    @property\n    def searched_plugins(self) -> Set[str]:\n        \"\"\"\u8fd4\u56de\u5df2\u641c\u7d22\u5230\u7684\u63d2\u4ef6\u540d\u79f0\u3002\"\"\"\n        return set(self._searched_plugin_names.keys())\n\n    @property\n    def available_plugins(self) -> Set[str]:\n        \"\"\"\u8fd4\u56de\u5f53\u524d\u63d2\u4ef6\u7ba1\u7406\u5668\u4e2d\u53ef\u7528\u7684\u63d2\u4ef6\u540d\u79f0\u3002\"\"\"\n        return self.third_party_plugins | self.searched_plugins\n\n    def _previous_plugins(self) -> Set[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(manager.available_plugins for manager in _pre_managers)\n        }\n\n    def prepare_plugins(self) -> Set[str]:\n        \"\"\"\u641c\u7d22\u63d2\u4ef6\u5e76\u7f13\u5b58\u63d2\u4ef6\u540d\u79f0\u3002\"\"\"\n        # get all previous ready to load plugins\n        previous_plugins = self._previous_plugins()\n        searched_plugins: Dict[str, Path] = {}\n        third_party_plugins: Dict[str, str] = {}\n\n        # check third party plugins\n        for plugin in self.plugins:\n            name = _module_name_to_plugin_name(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[name] = plugin\n\n        self._third_party_plugin_names = third_party_plugins\n\n        # check plugins in search path\n        for module_info in pkgutil.iter_modules(self.search_path):\n            # ignore if startswith \"_\"\n            if module_info.name.startswith(\"_\"):\n                continue\n\n            if (\n                module_info.name in searched_plugins\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\n            if not (\n                module_spec := module_info.module_finder.find_spec(\n                    module_info.name, None\n                )\n            ):\n                continue\n            if not (module_path := module_spec.origin):\n                continue\n            searched_plugins[module_info.name] = Path(module_path).resolve()\n\n        self._searched_plugin_names = searched_plugins\n\n        return self.available_plugins\n\n    def load_plugin(self, name: str) -> Optional[Plugin]:\n        \"\"\"\u52a0\u8f7d\u6307\u5b9a\u63d2\u4ef6\u3002\n\n        \u5bf9\u4e8e\u72ec\u7acb\u63d2\u4ef6\uff0c\u53ef\u4ee5\u4f7f\u7528\u5b8c\u6574\u63d2\u4ef6\u6a21\u5757\u540d\u6216\u8005\u63d2\u4ef6\u540d\u79f0\u3002\n\n        \u53c2\u6570:\n            name: \u63d2\u4ef6\u540d\u79f0\u3002\n        \"\"\"\n\n        try:\n            if name in self.plugins:\n                module = importlib.import_module(name)\n            elif name in self._third_party_plugin_names:\n                module = importlib.import_module(self._third_party_plugin_names[name])\n            elif name in self._searched_plugin_names:\n                module = importlib.import_module(\n                    path_to_module_name(self._searched_plugin_names[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            if (plugin := getattr(module, \"__plugin__\", None)) 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        \"\"\"\u52a0\u8f7d\u6240\u6709\u53ef\u7528\u63d2\u4ef6\u3002\"\"\"\n\n        return set(\n            filter(None, (self.load_plugin(name) for name in self.available_plugins))\n        )\n\n\nclass PluginFinder(MetaPathFinder):\n    def find_spec(\n        self,\n        fullname: str,\n        path: Optional[Sequence[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                # use path instead of name in case of submodule name conflict\n                if (\n                    fullname in manager.plugins\n                    or module_path in manager._searched_plugin_names.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        # create plugin before executing\n        plugin = _new_plugin(self.name, module, self.manager)\n        setattr(module, \"__plugin__\", plugin)\n\n        # detect parent plugin before entering current plugin context\n        parent_plugins = _current_plugin_chain.get()\n        for pre_plugin in reversed(parent_plugins):\n            if _managers.index(pre_plugin.manager) < _managers.index(self.manager):\n                plugin.parent_plugin = pre_plugin\n                pre_plugin.sub_plugins.add(plugin)\n                break\n\n        # enter plugin context\n        _plugin_token = _current_plugin_chain.set(parent_plugins + (plugin,))\n\n        try:\n            super().exec_module(module)\n        except Exception:\n            _revert_plugin(plugin)\n            raise\n        finally:\n            # leave plugin context\n            _current_plugin_chain.reset(_plugin_token)\n\n        # get plugin metadata\n        metadata: Optional[PluginMetadata] = getattr(module, \"__plugin_meta__\", None)\n        plugin.metadata = metadata\n\n        return\n\n\nsys.meta_path.insert(0, PluginFinder())\n", "path": "nonebot/plugin/manager.py"}], "after_files": [{"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, Iterable, Optional, Sequence\n\nfrom nonebot.log import logger\nfrom nonebot.utils import escape_tag, path_to_module_name\n\nfrom .plugin import Plugin, PluginMetadata\nfrom . import (\n    _managers,\n    _new_plugin,\n    _revert_plugin,\n    _current_plugin_chain,\n    _module_name_to_plugin_name,\n)\n\n\nclass PluginManager:\n    \"\"\"\u63d2\u4ef6\u7ba1\u7406\u5668\u3002\n\n    \u53c2\u6570:\n        plugins: \u72ec\u7acb\u63d2\u4ef6\u6a21\u5757\u540d\u96c6\u5408\u3002\n        search_path: \u63d2\u4ef6\u641c\u7d22\u8def\u5f84\uff08\u6587\u4ef6\u5939\uff09\u3002\n    \"\"\"\n\n    def __init__(\n        self,\n        plugins: Optional[Iterable[str]] = None,\n        search_path: Optional[Iterable[str]] = None,\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\n        # cache plugins\n        self._third_party_plugin_names: Dict[str, str] = {}\n        self._searched_plugin_names: Dict[str, Path] = {}\n        self.prepare_plugins()\n\n    def __repr__(self) -> str:\n        return f\"PluginManager(plugins={self.plugins}, search_path={self.search_path})\"\n\n    @property\n    def third_party_plugins(self) -> Set[str]:\n        \"\"\"\u8fd4\u56de\u6240\u6709\u72ec\u7acb\u63d2\u4ef6\u540d\u79f0\u3002\"\"\"\n        return set(self._third_party_plugin_names.keys())\n\n    @property\n    def searched_plugins(self) -> Set[str]:\n        \"\"\"\u8fd4\u56de\u5df2\u641c\u7d22\u5230\u7684\u63d2\u4ef6\u540d\u79f0\u3002\"\"\"\n        return set(self._searched_plugin_names.keys())\n\n    @property\n    def available_plugins(self) -> Set[str]:\n        \"\"\"\u8fd4\u56de\u5f53\u524d\u63d2\u4ef6\u7ba1\u7406\u5668\u4e2d\u53ef\u7528\u7684\u63d2\u4ef6\u540d\u79f0\u3002\"\"\"\n        return self.third_party_plugins | self.searched_plugins\n\n    def _previous_plugins(self) -> Set[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(manager.available_plugins for manager in _pre_managers)\n        }\n\n    def prepare_plugins(self) -> Set[str]:\n        \"\"\"\u641c\u7d22\u63d2\u4ef6\u5e76\u7f13\u5b58\u63d2\u4ef6\u540d\u79f0\u3002\"\"\"\n        # get all previous ready to load plugins\n        previous_plugins = self._previous_plugins()\n        searched_plugins: Dict[str, Path] = {}\n        third_party_plugins: Dict[str, str] = {}\n\n        # check third party plugins\n        for plugin in self.plugins:\n            name = _module_name_to_plugin_name(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[name] = plugin\n\n        self._third_party_plugin_names = third_party_plugins\n\n        # check plugins in search path\n        for module_info in pkgutil.iter_modules(self.search_path):\n            # ignore if startswith \"_\"\n            if module_info.name.startswith(\"_\"):\n                continue\n\n            if (\n                module_info.name in searched_plugins\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\n            if not (\n                module_spec := module_info.module_finder.find_spec(\n                    module_info.name, None\n                )\n            ):\n                continue\n            if not (module_path := module_spec.origin):\n                continue\n            searched_plugins[module_info.name] = Path(module_path).resolve()\n\n        self._searched_plugin_names = searched_plugins\n\n        return self.available_plugins\n\n    def load_plugin(self, name: str) -> Optional[Plugin]:\n        \"\"\"\u52a0\u8f7d\u6307\u5b9a\u63d2\u4ef6\u3002\n\n        \u5bf9\u4e8e\u72ec\u7acb\u63d2\u4ef6\uff0c\u53ef\u4ee5\u4f7f\u7528\u5b8c\u6574\u63d2\u4ef6\u6a21\u5757\u540d\u6216\u8005\u63d2\u4ef6\u540d\u79f0\u3002\n\n        \u53c2\u6570:\n            name: \u63d2\u4ef6\u540d\u79f0\u3002\n        \"\"\"\n\n        try:\n            if name in self.plugins:\n                module = importlib.import_module(name)\n            elif name in self._third_party_plugin_names:\n                module = importlib.import_module(self._third_party_plugin_names[name])\n            elif name in self._searched_plugin_names:\n                module = importlib.import_module(\n                    path_to_module_name(self._searched_plugin_names[name])\n                )\n            else:\n                raise RuntimeError(f\"Plugin not found: {name}! Check your plugin name\")\n\n            if (\n                plugin := getattr(module, \"__plugin__\", None)\n            ) is None or not isinstance(plugin, Plugin):\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            logger.opt(colors=True).success(\n                f'Succeeded to load plugin \"<y>{escape_tag(plugin.name)}</y>\"'\n                + (\n                    f' from \"<m>{escape_tag(plugin.module_name)}</m>\"'\n                    if plugin.module_name != plugin.name\n                    else \"\"\n                )\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        \"\"\"\u52a0\u8f7d\u6240\u6709\u53ef\u7528\u63d2\u4ef6\u3002\"\"\"\n\n        return set(\n            filter(None, (self.load_plugin(name) for name in self.available_plugins))\n        )\n\n\nclass PluginFinder(MetaPathFinder):\n    def find_spec(\n        self,\n        fullname: str,\n        path: Optional[Sequence[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                # use path instead of name in case of submodule name conflict\n                if (\n                    fullname in manager.plugins\n                    or module_path in manager._searched_plugin_names.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        # create plugin before executing\n        plugin = _new_plugin(self.name, module, self.manager)\n        setattr(module, \"__plugin__\", plugin)\n\n        # detect parent plugin before entering current plugin context\n        parent_plugins = _current_plugin_chain.get()\n        for pre_plugin in reversed(parent_plugins):\n            if _managers.index(pre_plugin.manager) < _managers.index(self.manager):\n                plugin.parent_plugin = pre_plugin\n                pre_plugin.sub_plugins.add(plugin)\n                break\n\n        # enter plugin context\n        _plugin_token = _current_plugin_chain.set(parent_plugins + (plugin,))\n\n        try:\n            super().exec_module(module)\n        except Exception:\n            _revert_plugin(plugin)\n            raise\n        finally:\n            # leave plugin context\n            _current_plugin_chain.reset(_plugin_token)\n\n        # get plugin metadata\n        metadata: Optional[PluginMetadata] = getattr(module, \"__plugin_meta__\", None)\n        plugin.metadata = metadata\n\n        return\n\n\nsys.meta_path.insert(0, PluginFinder())\n", "path": "nonebot/plugin/manager.py"}]}