ErisPulse 2.2.1.dev0__py3-none-any.whl → 2.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ErisPulse/Core/Bases/__init__.py +14 -0
- ErisPulse/Core/Bases/adapter.py +196 -0
- ErisPulse/Core/Bases/module.py +54 -0
- ErisPulse/Core/Event/__init__.py +14 -0
- ErisPulse/Core/Event/base.py +15 -2
- ErisPulse/Core/Event/command.py +21 -2
- ErisPulse/Core/Event/message.py +15 -0
- ErisPulse/Core/Event/meta.py +15 -0
- ErisPulse/Core/Event/notice.py +15 -0
- ErisPulse/Core/Event/request.py +16 -1
- ErisPulse/Core/__init__.py +38 -19
- ErisPulse/Core/{erispulse_config.py → _self_config.py} +27 -2
- ErisPulse/Core/adapter.py +374 -377
- ErisPulse/Core/config.py +137 -38
- ErisPulse/Core/exceptions.py +6 -1
- ErisPulse/Core/lifecycle.py +167 -0
- ErisPulse/Core/logger.py +97 -49
- ErisPulse/Core/module.py +279 -56
- ErisPulse/Core/router.py +112 -23
- ErisPulse/Core/storage.py +258 -77
- ErisPulse/Core/ux.py +635 -0
- ErisPulse/__init__.py +722 -244
- ErisPulse/__main__.py +1 -1999
- ErisPulse/utils/__init__.py +17 -0
- ErisPulse/utils/cli.py +1092 -0
- ErisPulse/utils/console.py +53 -0
- ErisPulse/utils/package_manager.py +845 -0
- ErisPulse/utils/reload_handler.py +111 -0
- {erispulse-2.2.1.dev0.dist-info → erispulse-2.3.0.dist-info}/METADATA +24 -6
- erispulse-2.3.0.dist-info/RECORD +34 -0
- {erispulse-2.2.1.dev0.dist-info → erispulse-2.3.0.dist-info}/WHEEL +1 -1
- {erispulse-2.2.1.dev0.dist-info → erispulse-2.3.0.dist-info}/licenses/LICENSE +1 -1
- ErisPulse/Core/env.py +0 -15
- ErisPulse/Core/module_registry.py +0 -227
- erispulse-2.2.1.dev0.dist-info/RECORD +0 -26
- {erispulse-2.2.1.dev0.dist-info → erispulse-2.3.0.dist-info}/entry_points.txt +0 -0
ErisPulse/__init__.py
CHANGED
|
@@ -5,13 +5,14 @@ ErisPulse SDK 主模块
|
|
|
5
5
|
|
|
6
6
|
{!--< tips >!--}
|
|
7
7
|
1. 使用前请确保已正确安装所有依赖
|
|
8
|
-
2. 调用sdk.init()进行初始化
|
|
8
|
+
2. 调用await sdk.init()进行初始化
|
|
9
9
|
3. 模块加载采用懒加载机制
|
|
10
10
|
{!--< /tips >!--}
|
|
11
11
|
"""
|
|
12
12
|
|
|
13
13
|
import os
|
|
14
14
|
import sys
|
|
15
|
+
import types
|
|
15
16
|
import importlib
|
|
16
17
|
import asyncio
|
|
17
18
|
import inspect
|
|
@@ -20,16 +21,23 @@ from typing import Dict, List, Tuple, Type, Any
|
|
|
20
21
|
from pathlib import Path
|
|
21
22
|
|
|
22
23
|
# BaseModules: SDK核心模块
|
|
23
|
-
|
|
24
|
-
from .Core import
|
|
25
|
-
|
|
26
|
-
from .Core import
|
|
27
|
-
|
|
24
|
+
# 事件处理模块
|
|
25
|
+
from .Core import Event
|
|
26
|
+
# 基础设施
|
|
27
|
+
from .Core import lifecycle, logger, exceptions
|
|
28
|
+
# 存储和配置相关
|
|
29
|
+
from .Core import storage, env, config
|
|
30
|
+
# 适配器相关
|
|
31
|
+
from .Core import adapter, AdapterFather, BaseAdapter, SendDSL
|
|
32
|
+
# 模块相关
|
|
28
33
|
from .Core import module
|
|
34
|
+
# 路由相关
|
|
29
35
|
from .Core import router, adapter_server
|
|
30
|
-
|
|
31
|
-
from .Core import
|
|
32
|
-
|
|
36
|
+
# 用户体验相关
|
|
37
|
+
from .Core import ux, UXManager
|
|
38
|
+
|
|
39
|
+
# SDK统一对外接口
|
|
40
|
+
sdk = types.ModuleType('sdk')
|
|
33
41
|
|
|
34
42
|
try:
|
|
35
43
|
__version__ = importlib.metadata.version('ErisPulse')
|
|
@@ -37,31 +45,42 @@ except importlib.metadata.PackageNotFoundError:
|
|
|
37
45
|
logger.critical("未找到ErisPulse版本信息,请检查是否正确安装ErisPulse")
|
|
38
46
|
__author__ = "ErisPulse"
|
|
39
47
|
|
|
40
|
-
|
|
48
|
+
logger.debug("ErisPulse 正在挂载SDK核心模块...")
|
|
41
49
|
|
|
42
50
|
BaseModules = {
|
|
43
|
-
"Event": Event,
|
|
44
|
-
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
51
|
+
"Event" : Event,
|
|
52
|
+
|
|
53
|
+
"lifecycle" : lifecycle,
|
|
54
|
+
"logger" : logger,
|
|
55
|
+
"exceptions" : exceptions,
|
|
56
|
+
|
|
57
|
+
"storage" : storage,
|
|
58
|
+
"env" : env,
|
|
59
|
+
"config" : config,
|
|
60
|
+
|
|
61
|
+
"adapter" : adapter,
|
|
62
|
+
"AdapterFather" : AdapterFather,
|
|
63
|
+
"BaseAdapter" : BaseAdapter,
|
|
64
|
+
"SendDSL" : SendDSL,
|
|
65
|
+
|
|
66
|
+
"module" : module,
|
|
67
|
+
|
|
52
68
|
"router": router,
|
|
53
69
|
"adapter_server": adapter_server,
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"BaseAdapter": AdapterFather
|
|
70
|
+
"ux": ux,
|
|
71
|
+
"UXManager": UXManager,
|
|
57
72
|
}
|
|
58
73
|
|
|
59
|
-
|
|
74
|
+
for module_name, moduleObj in BaseModules.items():
|
|
75
|
+
setattr(sdk, module_name, moduleObj)
|
|
76
|
+
|
|
77
|
+
logger.debug("ErisPulse 正在挂载loop循环器...")
|
|
60
78
|
|
|
79
|
+
# 设置默认loop循环捕捉器
|
|
80
|
+
asyncio_loop = asyncio.get_event_loop()
|
|
61
81
|
exceptions.setup_async_loop(asyncio_loop)
|
|
62
82
|
|
|
63
|
-
|
|
64
|
-
setattr(sdk, module, moduleObj)
|
|
83
|
+
logger.debug("SDK核心模块挂载完毕")
|
|
65
84
|
|
|
66
85
|
class LazyModule:
|
|
67
86
|
"""
|
|
@@ -72,6 +91,7 @@ class LazyModule:
|
|
|
72
91
|
{!--< tips >!--}
|
|
73
92
|
1. 模块的实际实例化会在第一次属性访问时进行
|
|
74
93
|
2. 依赖模块会在被使用时自动初始化
|
|
94
|
+
3. 对于继承自 BaseModule 的模块,会自动调用生命周期方法
|
|
75
95
|
{!--< /tips >!--}
|
|
76
96
|
"""
|
|
77
97
|
|
|
@@ -84,110 +104,305 @@ class LazyModule:
|
|
|
84
104
|
:param sdk_ref: Any SDK引用
|
|
85
105
|
:param module_info: Dict[str, Any] 模块信息字典
|
|
86
106
|
"""
|
|
87
|
-
|
|
88
|
-
self
|
|
89
|
-
self
|
|
90
|
-
self
|
|
91
|
-
self
|
|
92
|
-
self
|
|
107
|
+
# 使用object.__setattr__避免触发自定义的__setattr__
|
|
108
|
+
object.__setattr__(self, '_module_name', module_name)
|
|
109
|
+
object.__setattr__(self, '_module_class', module_class)
|
|
110
|
+
object.__setattr__(self, '_sdk_ref', sdk_ref)
|
|
111
|
+
object.__setattr__(self, '_module_info', module_info)
|
|
112
|
+
object.__setattr__(self, '_instance', None)
|
|
113
|
+
object.__setattr__(self, '_initialized', False)
|
|
114
|
+
object.__setattr__(self, '_is_base_module', module_info.get("meta", {}).get("is_base_module", False))
|
|
93
115
|
|
|
94
|
-
def _initialize(self):
|
|
116
|
+
async def _initialize(self):
|
|
95
117
|
"""
|
|
96
118
|
实际初始化模块
|
|
97
119
|
|
|
98
120
|
:raises LazyLoadError: 当模块初始化失败时抛出
|
|
99
121
|
"""
|
|
122
|
+
# 避免重复初始化
|
|
123
|
+
if object.__getattribute__(self, '_initialized'):
|
|
124
|
+
return
|
|
125
|
+
|
|
126
|
+
logger.debug(f"正在初始化懒加载模块 {object.__getattribute__(self, '_module_name')}...")
|
|
127
|
+
|
|
100
128
|
try:
|
|
101
129
|
# 获取类的__init__参数信息
|
|
102
|
-
|
|
130
|
+
logger.debug(f"正在获取模块 {object.__getattribute__(self, '_module_name')} 的 __init__ 参数信息...")
|
|
131
|
+
init_signature = inspect.signature(object.__getattribute__(self, '_module_class').__init__)
|
|
103
132
|
params = init_signature.parameters
|
|
104
133
|
|
|
105
134
|
# 根据参数决定是否传入sdk
|
|
106
135
|
if 'sdk' in params:
|
|
107
|
-
|
|
136
|
+
logger.debug(f"模块 {object.__getattribute__(self, '_module_name')} 需要传入 sdk 参数")
|
|
137
|
+
instance = object.__getattribute__(self, '_module_class')(object.__getattribute__(self, '_sdk_ref'))
|
|
108
138
|
else:
|
|
109
|
-
|
|
139
|
+
logger.debug(f"模块 {object.__getattribute__(self, '_module_name')} 不需要传入 sdk 参数")
|
|
140
|
+
instance = object.__getattribute__(self, '_module_class')()
|
|
141
|
+
|
|
142
|
+
logger.debug(f"正在设置模块 {object.__getattribute__(self, '_module_name')} 的 moduleInfo 属性...")
|
|
143
|
+
setattr(instance, "moduleInfo", object.__getattribute__(self, '_module_info'))
|
|
144
|
+
|
|
145
|
+
# 使用object.__setattr__避免触发自定义的__setattr__
|
|
146
|
+
object.__setattr__(self, '_instance', instance)
|
|
147
|
+
object.__setattr__(self, '_initialized', True)
|
|
148
|
+
|
|
149
|
+
# 如果是 BaseModule 子类,在初始化后调用 on_load 方法
|
|
150
|
+
if object.__getattribute__(self, '_is_base_module'):
|
|
151
|
+
logger.debug(f"正在调用模块 {object.__getattribute__(self, '_module_name')} 的 on_load 方法...")
|
|
152
|
+
|
|
153
|
+
try:
|
|
154
|
+
await module.load(object.__getattribute__(self, '_module_name'))
|
|
155
|
+
except Exception as e:
|
|
156
|
+
logger.error(f"调用模块 {object.__getattribute__(self, '_module_name')} 的 on_load 方法时出错: {e}")
|
|
157
|
+
|
|
158
|
+
await lifecycle.submit_event(
|
|
159
|
+
"module.init",
|
|
160
|
+
msg=f"模块 {object.__getattribute__(self, '_module_name')} 初始化完毕",
|
|
161
|
+
data={
|
|
162
|
+
"module_name": object.__getattribute__(self, '_module_name'),
|
|
163
|
+
"success": True,
|
|
164
|
+
}
|
|
165
|
+
)
|
|
166
|
+
logger.debug(f"懒加载模块 {object.__getattribute__(self, '_module_name')} 初始化完成")
|
|
110
167
|
|
|
111
|
-
setattr(self._instance, "moduleInfo", self._module_info)
|
|
112
|
-
self._initialized = True
|
|
113
|
-
logger.debug(f"模块 {self._module_name} 初始化完成")
|
|
114
168
|
except Exception as e:
|
|
115
|
-
|
|
116
|
-
|
|
169
|
+
await lifecycle.submit_event(
|
|
170
|
+
"module.init",
|
|
171
|
+
msg=f"模块初始化失败: {e}",
|
|
172
|
+
data={
|
|
173
|
+
"module_name": object.__getattribute__(self, '_module_name'),
|
|
174
|
+
"success": False,
|
|
175
|
+
}
|
|
176
|
+
)
|
|
177
|
+
logger.error(f"懒加载模块 {object.__getattribute__(self, '_module_name')} 初始化失败: {e}")
|
|
178
|
+
raise e
|
|
117
179
|
|
|
118
|
-
def
|
|
180
|
+
def _initialize_sync(self):
|
|
119
181
|
"""
|
|
120
|
-
|
|
182
|
+
同步初始化模块,用于在异步上下文中进行同步调用
|
|
121
183
|
|
|
122
|
-
:
|
|
123
|
-
:return: Any 模块属性值
|
|
184
|
+
:raises LazyLoadError: 当模块初始化失败时抛出
|
|
124
185
|
"""
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
186
|
+
# 避免重复初始化
|
|
187
|
+
if object.__getattribute__(self, '_initialized'):
|
|
188
|
+
return
|
|
189
|
+
|
|
190
|
+
logger.debug(f"正在同步初始化懒加载模块 {object.__getattribute__(self, '_module_name')}...")
|
|
191
|
+
|
|
192
|
+
try:
|
|
193
|
+
# 获取类的__init__参数信息
|
|
194
|
+
logger.debug(f"正在获取模块 {object.__getattribute__(self, '_module_name')} 的 __init__ 参数信息...")
|
|
195
|
+
init_signature = inspect.signature(object.__getattribute__(self, '_module_class').__init__)
|
|
196
|
+
params = init_signature.parameters
|
|
197
|
+
|
|
198
|
+
# 根据参数决定是否传入sdk
|
|
199
|
+
if 'sdk' in params:
|
|
200
|
+
logger.debug(f"模块 {object.__getattribute__(self, '_module_name')} 需要传入 sdk 参数")
|
|
201
|
+
instance = object.__getattribute__(self, '_module_class')(object.__getattribute__(self, '_sdk_ref'))
|
|
202
|
+
else:
|
|
203
|
+
logger.debug(f"模块 {object.__getattribute__(self, '_module_name')} 不需要传入 sdk 参数")
|
|
204
|
+
instance = object.__getattribute__(self, '_module_class')()
|
|
205
|
+
|
|
206
|
+
logger.debug(f"正在设置模块 {object.__getattribute__(self, '_module_name')} 的 moduleInfo 属性...")
|
|
207
|
+
setattr(instance, "moduleInfo", object.__getattribute__(self, '_module_info'))
|
|
208
|
+
|
|
209
|
+
# 使用object.__setattr__避免触发自定义的__setattr__
|
|
210
|
+
object.__setattr__(self, '_instance', instance)
|
|
211
|
+
object.__setattr__(self, '_initialized', True)
|
|
212
|
+
object.__setattr__(self, '_needs_async_init', False) # 确保清除异步初始化标志
|
|
213
|
+
|
|
214
|
+
# 注意:在同步初始化中,我们不能调用异步的 module.load 和 lifecycle.submit_event
|
|
215
|
+
# 这些将在异步上下文中延迟处理
|
|
216
|
+
|
|
217
|
+
logger.debug(f"懒加载模块 {object.__getattribute__(self, '_module_name')} 同步初始化完成")
|
|
218
|
+
|
|
219
|
+
except Exception as e:
|
|
220
|
+
logger.error(f"懒加载模块 {object.__getattribute__(self, '_module_name')} 同步初始化失败: {e}")
|
|
221
|
+
raise e
|
|
128
222
|
|
|
129
|
-
def
|
|
223
|
+
async def _complete_async_init(self):
|
|
130
224
|
"""
|
|
131
|
-
|
|
225
|
+
完成异步初始化部分,用于同步初始化后的异步处理
|
|
132
226
|
|
|
133
|
-
|
|
134
|
-
:param kwargs: 关键字参数
|
|
135
|
-
:return: Any 模块调用结果
|
|
227
|
+
这个方法用于处理 module.load 和事件提交等异步操作
|
|
136
228
|
"""
|
|
137
|
-
if not self
|
|
138
|
-
|
|
139
|
-
|
|
229
|
+
if not object.__getattribute__(self, '_initialized'):
|
|
230
|
+
return
|
|
231
|
+
|
|
232
|
+
try:
|
|
233
|
+
# 如果是 BaseModule 子类,在初始化后调用 on_load 方法
|
|
234
|
+
if object.__getattribute__(self, '_is_base_module'):
|
|
235
|
+
logger.debug(f"正在异步调用模块 {object.__getattribute__(self, '_module_name')} 的 on_load 方法...")
|
|
236
|
+
|
|
237
|
+
try:
|
|
238
|
+
await module.load(object.__getattribute__(self, '_module_name'))
|
|
239
|
+
except Exception as e:
|
|
240
|
+
logger.error(f"异步调用模块 {object.__getattribute__(self, '_module_name')} 的 on_load 方法时出错: {e}")
|
|
241
|
+
|
|
242
|
+
await lifecycle.submit_event(
|
|
243
|
+
"module.init",
|
|
244
|
+
msg=f"模块 {object.__getattribute__(self, '_module_name')} 初始化完毕",
|
|
245
|
+
data={
|
|
246
|
+
"module_name": object.__getattribute__(self, '_module_name'),
|
|
247
|
+
"success": True,
|
|
248
|
+
}
|
|
249
|
+
)
|
|
250
|
+
logger.debug(f"懒加载模块 {object.__getattribute__(self, '_module_name')} 异步初始化部分完成")
|
|
251
|
+
except Exception as e:
|
|
252
|
+
await lifecycle.submit_event(
|
|
253
|
+
"module.init",
|
|
254
|
+
msg=f"模块初始化失败: {e}",
|
|
255
|
+
data={
|
|
256
|
+
"module_name": object.__getattribute__(self, '_module_name'),
|
|
257
|
+
"success": False,
|
|
258
|
+
}
|
|
259
|
+
)
|
|
260
|
+
logger.error(f"懒加载模块 {object.__getattribute__(self, '_module_name')} 异步初始化部分失败: {e}")
|
|
140
261
|
|
|
141
|
-
def
|
|
262
|
+
def _ensure_initialized(self) -> None:
|
|
142
263
|
"""
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
:
|
|
264
|
+
确保模块已初始化
|
|
265
|
+
|
|
266
|
+
:raises LazyLoadError: 当模块未初始化时抛出
|
|
146
267
|
"""
|
|
147
|
-
if not self
|
|
148
|
-
|
|
149
|
-
|
|
268
|
+
if not object.__getattribute__(self, '_initialized'):
|
|
269
|
+
# 检查当前是否在异步上下文中
|
|
270
|
+
try:
|
|
271
|
+
loop = asyncio.get_running_loop()
|
|
272
|
+
# 如果在异步上下文中,我们需要检查模块初始化方法是否需要异步
|
|
273
|
+
init_method = getattr(object.__getattribute__(self, '_module_class'), '__init__', None)
|
|
274
|
+
|
|
275
|
+
# 检查__init__方法是否是协程函数
|
|
276
|
+
if asyncio.iscoroutinefunction(init_method):
|
|
277
|
+
# 对于需要异步初始化的模块,我们只能设置一个标志,提示需要异步初始化
|
|
278
|
+
object.__setattr__(self, '_needs_async_init', True)
|
|
279
|
+
logger.warning(f"模块 {object.__getattribute__(self, '_module_name')} 需要异步初始化,请在异步上下文中调用")
|
|
280
|
+
return
|
|
281
|
+
else:
|
|
282
|
+
# 对于同步初始化的模块,使用同步初始化方式
|
|
283
|
+
self._initialize_sync()
|
|
284
|
+
|
|
285
|
+
# 异步处理需要在初始化后完成的事件
|
|
286
|
+
if object.__getattribute__(self, '_is_base_module'):
|
|
287
|
+
# 调度异步任务来处理 module.load 和事件提交
|
|
288
|
+
try:
|
|
289
|
+
loop = asyncio.get_running_loop()
|
|
290
|
+
loop.create_task(self._complete_async_init())
|
|
291
|
+
except Exception as e:
|
|
292
|
+
logger.warning(f"无法调度异步初始化任务: {e}")
|
|
293
|
+
except RuntimeError:
|
|
294
|
+
# 没有运行中的事件循环,可以安全地创建新的事件循环
|
|
295
|
+
asyncio.run(self._initialize())
|
|
150
296
|
|
|
151
|
-
def
|
|
297
|
+
def __getattr__(self, name: str) -> Any:
|
|
152
298
|
"""
|
|
153
|
-
|
|
299
|
+
属性访问时触发初始化
|
|
154
300
|
|
|
155
|
-
:
|
|
301
|
+
:param name: str 属性名
|
|
302
|
+
:return: Any 属性值
|
|
156
303
|
"""
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
304
|
+
logger.debug(f"正在访问懒加载模块 {object.__getattribute__(self, '_module_name')} 的属性 {name}...")
|
|
305
|
+
|
|
306
|
+
# 检查是否需要异步初始化
|
|
307
|
+
if hasattr(self, '_needs_async_init') and object.__getattribute__(self, '_needs_async_init'):
|
|
308
|
+
raise RuntimeError(
|
|
309
|
+
f"模块 {object.__getattribute__(self, '_module_name')} 需要异步初始化,"
|
|
310
|
+
f"请使用 'await sdk.load_module(\"{object.__getattribute__(self, '_module_name')}\")' 来初始化模块"
|
|
311
|
+
)
|
|
312
|
+
|
|
313
|
+
self._ensure_initialized()
|
|
314
|
+
return getattr(object.__getattribute__(self, '_instance'), name)
|
|
161
315
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
# 首先尝试获取常规属性
|
|
166
|
-
return super().__getattribute__(name)
|
|
167
|
-
except AttributeError:
|
|
168
|
-
# 如果常规属性不存在,触发初始化
|
|
169
|
-
if name != '_initialized' and not self._initialized:
|
|
170
|
-
self._initialize()
|
|
171
|
-
return getattr(self._instance, name)
|
|
172
|
-
raise
|
|
316
|
+
def __setattr__(self, name: str, value: Any) -> None:
|
|
317
|
+
"""
|
|
318
|
+
属性设置
|
|
173
319
|
|
|
174
|
-
|
|
320
|
+
:param name: str 属性名
|
|
321
|
+
:param value: Any 属性值
|
|
175
322
|
"""
|
|
176
|
-
|
|
323
|
+
logger.debug(f"正在设置懒加载模块 {object.__getattribute__(self, '_module_name')} 的属性 {name}...")
|
|
177
324
|
|
|
178
|
-
|
|
325
|
+
# 特殊属性直接设置到包装器上
|
|
326
|
+
if name.startswith('_') or name in ('moduleInfo',):
|
|
327
|
+
object.__setattr__(self, name, value)
|
|
328
|
+
else:
|
|
329
|
+
# 其他属性在初始化前设置到包装器上,初始化后设置到实际模块实例上
|
|
330
|
+
if name == '_instance' or not hasattr(self, '_initialized') or not object.__getattribute__(self, '_initialized'):
|
|
331
|
+
object.__setattr__(self, name, value)
|
|
332
|
+
else:
|
|
333
|
+
setattr(object.__getattribute__(self, '_instance'), name, value)
|
|
334
|
+
|
|
335
|
+
def __delattr__(self, name: str) -> None:
|
|
336
|
+
"""
|
|
337
|
+
属性删除
|
|
338
|
+
|
|
339
|
+
:param name: str 属性名
|
|
179
340
|
"""
|
|
180
|
-
|
|
341
|
+
logger.debug(f"正在删除懒加载模块 {object.__getattribute__(self, '_module_name')} 的属性 {name}...")
|
|
181
342
|
|
|
182
|
-
|
|
343
|
+
self._ensure_initialized()
|
|
344
|
+
delattr(object.__getattribute__(self, '_instance'), name)
|
|
345
|
+
|
|
346
|
+
def __getattribute__(self, name: str) -> Any:
|
|
183
347
|
"""
|
|
184
|
-
|
|
348
|
+
属性访问,初始化后直接委托给实际实例
|
|
349
|
+
|
|
350
|
+
:param name: str 属性名
|
|
351
|
+
:return: Any 属性值
|
|
352
|
+
"""
|
|
353
|
+
# 特殊属性直接从包装器获取
|
|
354
|
+
if name.startswith('_') or name in ('moduleInfo',):
|
|
355
|
+
return object.__getattribute__(self, name)
|
|
356
|
+
|
|
357
|
+
# 检查是否已初始化
|
|
358
|
+
try:
|
|
359
|
+
initialized = object.__getattribute__(self, '_initialized')
|
|
360
|
+
except AttributeError:
|
|
361
|
+
# 避免在初始化过程中访问_initialized时出现递归
|
|
362
|
+
return object.__getattribute__(self, name)
|
|
363
|
+
|
|
364
|
+
if not initialized:
|
|
365
|
+
# 确保初始化
|
|
366
|
+
self._ensure_initialized()
|
|
367
|
+
# 重新获取initialized状态
|
|
368
|
+
initialized = object.__getattribute__(self, '_initialized')
|
|
369
|
+
|
|
370
|
+
# 初始化后直接委托给实际实例
|
|
371
|
+
if initialized:
|
|
372
|
+
instance = object.__getattribute__(self, '_instance')
|
|
373
|
+
return getattr(instance, name)
|
|
374
|
+
else:
|
|
375
|
+
return object.__getattribute__(self, name)
|
|
376
|
+
|
|
377
|
+
def __dir__(self) -> List[str]:
|
|
378
|
+
"""
|
|
379
|
+
返回模块属性列表
|
|
380
|
+
|
|
381
|
+
:return: List[str] 属性列表
|
|
382
|
+
"""
|
|
383
|
+
logger.debug(f"正在获取懒加载模块 {object.__getattribute__(self, '_module_name')} 的属性列表...")
|
|
185
384
|
|
|
186
|
-
|
|
187
|
-
|
|
385
|
+
self._ensure_initialized()
|
|
386
|
+
return dir(object.__getattribute__(self, '_instance'))
|
|
387
|
+
|
|
388
|
+
def __repr__(self) -> str:
|
|
389
|
+
"""
|
|
390
|
+
返回模块表示字符串
|
|
391
|
+
|
|
392
|
+
:return: str 表示字符串
|
|
188
393
|
"""
|
|
189
|
-
|
|
394
|
+
logger.debug(f"正在获取懒加载模块 {object.__getattribute__(self, '_module_name')} 的表示字符串...")
|
|
190
395
|
|
|
396
|
+
if object.__getattribute__(self, '_initialized'):
|
|
397
|
+
return repr(object.__getattribute__(self, '_instance'))
|
|
398
|
+
return f"<LazyModule {object.__getattribute__(self, '_module_name')} (not initialized)>"
|
|
399
|
+
|
|
400
|
+
# 代理所有其他魔术方法到实际模块实例
|
|
401
|
+
def __call__(self, *args, **kwargs):
|
|
402
|
+
"""代理函数调用"""
|
|
403
|
+
self._ensure_initialized()
|
|
404
|
+
return object.__getattribute__(self, '_instance')(*args, **kwargs)
|
|
405
|
+
|
|
191
406
|
|
|
192
407
|
class AdapterLoader:
|
|
193
408
|
"""
|
|
@@ -203,7 +418,7 @@ class AdapterLoader:
|
|
|
203
418
|
"""
|
|
204
419
|
|
|
205
420
|
@staticmethod
|
|
206
|
-
def load() -> Tuple[Dict[str, object], List[str], List[str]]:
|
|
421
|
+
async def load() -> Tuple[Dict[str, object], List[str], List[str]]:
|
|
207
422
|
"""
|
|
208
423
|
从PyPI包entry-points加载适配器
|
|
209
424
|
|
|
@@ -218,27 +433,33 @@ class AdapterLoader:
|
|
|
218
433
|
enabled_adapters = []
|
|
219
434
|
disabled_adapters = []
|
|
220
435
|
|
|
436
|
+
logger.info("正在加载适配器entry-points...")
|
|
437
|
+
|
|
221
438
|
try:
|
|
222
439
|
# 加载适配器entry-points
|
|
440
|
+
logger.debug("正在获取适配器entry-points...")
|
|
223
441
|
entry_points = importlib.metadata.entry_points()
|
|
224
442
|
if hasattr(entry_points, 'select'):
|
|
225
443
|
adapter_entries = entry_points.select(group='erispulse.adapter')
|
|
226
444
|
else:
|
|
227
|
-
adapter_entries = entry_points.get('erispulse.adapter', [])
|
|
445
|
+
adapter_entries = entry_points.get('erispulse.adapter', []) # type: ignore[attr-defined] || 原因: 3.10.0后entry_points不再支持select方法
|
|
228
446
|
|
|
229
447
|
# 处理适配器
|
|
448
|
+
logger.debug("正在处理适配器entry-points...")
|
|
230
449
|
for entry_point in adapter_entries:
|
|
231
|
-
adapter_objs, enabled_adapters, disabled_adapters = AdapterLoader._process_adapter(
|
|
450
|
+
adapter_objs, enabled_adapters, disabled_adapters = await AdapterLoader._process_adapter(
|
|
232
451
|
entry_point, adapter_objs, enabled_adapters, disabled_adapters)
|
|
233
|
-
|
|
452
|
+
|
|
453
|
+
logger.info("适配器加载完成")
|
|
454
|
+
|
|
234
455
|
except Exception as e:
|
|
235
456
|
logger.error(f"加载适配器entry-points失败: {e}")
|
|
236
457
|
raise ImportError(f"无法加载适配器: {e}")
|
|
237
|
-
|
|
458
|
+
|
|
238
459
|
return adapter_objs, enabled_adapters, disabled_adapters
|
|
239
460
|
|
|
240
461
|
@staticmethod
|
|
241
|
-
def _process_adapter(
|
|
462
|
+
async def _process_adapter(
|
|
242
463
|
entry_point: Any,
|
|
243
464
|
adapter_objs: Dict[str, object],
|
|
244
465
|
enabled_adapters: List[str],
|
|
@@ -261,12 +482,22 @@ class AdapterLoader:
|
|
|
261
482
|
:raises ImportError: 当适配器加载失败时抛出
|
|
262
483
|
"""
|
|
263
484
|
meta_name = entry_point.name
|
|
264
|
-
|
|
485
|
+
|
|
486
|
+
# # 检查适配器是否已经注册,如果未注册则进行注册(默认禁用)
|
|
487
|
+
# if not sdk.adapter.exists(meta_name):
|
|
488
|
+
# sdk.adapter._config_register(meta_name, False)
|
|
489
|
+
# logger.info(f"发现新适配器 {meta_name},默认已禁用,请在配置文件中配置适配器并决定是否启用")
|
|
490
|
+
if not sdk.adapter.exists(meta_name):
|
|
491
|
+
sdk.adapter._config_register(meta_name, True)
|
|
492
|
+
logger.info(f"发现新适配器 {meta_name},默认已启用")
|
|
493
|
+
|
|
494
|
+
# 获取适配器当前状态
|
|
495
|
+
adapter_status = sdk.adapter.is_enabled(meta_name)
|
|
265
496
|
logger.debug(f"适配器 {meta_name} 状态: {adapter_status}")
|
|
266
497
|
|
|
267
|
-
if adapter_status
|
|
498
|
+
if not adapter_status:
|
|
268
499
|
disabled_adapters.append(meta_name)
|
|
269
|
-
logger.
|
|
500
|
+
logger.debug(f"适配器 {meta_name} 已禁用, 跳过...")
|
|
270
501
|
return adapter_objs, enabled_adapters, disabled_adapters
|
|
271
502
|
|
|
272
503
|
try:
|
|
@@ -287,12 +518,9 @@ class AdapterLoader:
|
|
|
287
518
|
}
|
|
288
519
|
|
|
289
520
|
if not hasattr(adapter_obj, 'adapterInfo'):
|
|
290
|
-
adapter_obj
|
|
521
|
+
setattr(adapter_obj, 'adapterInfo', {})
|
|
291
522
|
|
|
292
523
|
adapter_obj.adapterInfo[meta_name] = adapter_info
|
|
293
|
-
|
|
294
|
-
# 存储适配器信息
|
|
295
|
-
module_registry.set_module(meta_name, adapter_info)
|
|
296
524
|
|
|
297
525
|
adapter_objs[meta_name] = adapter_obj
|
|
298
526
|
enabled_adapters.append(meta_name)
|
|
@@ -304,7 +532,6 @@ class AdapterLoader:
|
|
|
304
532
|
|
|
305
533
|
return adapter_objs, enabled_adapters, disabled_adapters
|
|
306
534
|
|
|
307
|
-
|
|
308
535
|
class ModuleLoader:
|
|
309
536
|
"""
|
|
310
537
|
模块加载器
|
|
@@ -318,7 +545,7 @@ class ModuleLoader:
|
|
|
318
545
|
"""
|
|
319
546
|
|
|
320
547
|
@staticmethod
|
|
321
|
-
def load() -> Tuple[Dict[str, object], List[str], List[str]]:
|
|
548
|
+
async def load() -> Tuple[Dict[str, object], List[str], List[str]]:
|
|
322
549
|
"""
|
|
323
550
|
从PyPI包entry-points加载模块
|
|
324
551
|
|
|
@@ -333,19 +560,23 @@ class ModuleLoader:
|
|
|
333
560
|
enabled_modules = []
|
|
334
561
|
disabled_modules = []
|
|
335
562
|
|
|
563
|
+
logger.info("正在加载模块entry-points...")
|
|
564
|
+
|
|
336
565
|
try:
|
|
337
566
|
# 加载模块entry-points
|
|
338
567
|
entry_points = importlib.metadata.entry_points()
|
|
339
568
|
if hasattr(entry_points, 'select'):
|
|
340
569
|
module_entries = entry_points.select(group='erispulse.module')
|
|
341
570
|
else:
|
|
342
|
-
module_entries = entry_points.get('erispulse.module', [])
|
|
571
|
+
module_entries = entry_points.get('erispulse.module', []) # type: ignore[attr-defined] || 原因: 3.10.0后entry_points不再支持select方法
|
|
343
572
|
|
|
344
573
|
# 处理模块
|
|
345
574
|
for entry_point in module_entries:
|
|
346
|
-
module_objs, enabled_modules, disabled_modules = ModuleLoader._process_module(
|
|
575
|
+
module_objs, enabled_modules, disabled_modules = await ModuleLoader._process_module(
|
|
347
576
|
entry_point, module_objs, enabled_modules, disabled_modules)
|
|
348
|
-
|
|
577
|
+
|
|
578
|
+
logger.info("模块加载完成")
|
|
579
|
+
|
|
349
580
|
except Exception as e:
|
|
350
581
|
logger.error(f"加载模块entry-points失败: {e}")
|
|
351
582
|
raise ImportError(f"无法加载模块: {e}")
|
|
@@ -353,7 +584,7 @@ class ModuleLoader:
|
|
|
353
584
|
return module_objs, enabled_modules, disabled_modules
|
|
354
585
|
|
|
355
586
|
@staticmethod
|
|
356
|
-
def _process_module(
|
|
587
|
+
async def _process_module(
|
|
357
588
|
entry_point: Any,
|
|
358
589
|
module_objs: Dict[str, object],
|
|
359
590
|
enabled_modules: List[str],
|
|
@@ -376,13 +607,23 @@ class ModuleLoader:
|
|
|
376
607
|
:raises ImportError: 当模块加载失败时抛出
|
|
377
608
|
"""
|
|
378
609
|
meta_name = entry_point.name
|
|
379
|
-
|
|
610
|
+
|
|
611
|
+
logger.debug(f"正在处理模块: {meta_name}")
|
|
612
|
+
# # 检查模块是否已经注册,如果未注册则进行注册(默认禁用)
|
|
613
|
+
# if not sdk.module.exists(meta_name):
|
|
614
|
+
# sdk.module._config_register(meta_name, False) # 默认禁用
|
|
615
|
+
# logger.info(f"发现新模块 {meta_name},默认已禁用,请在配置文件中手动启用")
|
|
616
|
+
|
|
617
|
+
if not sdk.module.exists(meta_name):
|
|
618
|
+
sdk.module._config_register(meta_name, True) # 默认启用
|
|
619
|
+
logger.info(f"发现新模块 {meta_name},默认已启用。如需禁用,请在配置文件中设置 ErisPulse.modules.status.{meta_name} = false")
|
|
620
|
+
|
|
621
|
+
# 获取模块当前状态
|
|
622
|
+
module_status = sdk.module.is_enabled(meta_name)
|
|
380
623
|
logger.debug(f"模块 {meta_name} 状态: {module_status}")
|
|
381
624
|
|
|
382
|
-
|
|
383
|
-
if module_status is False:
|
|
625
|
+
if not module_status:
|
|
384
626
|
disabled_modules.append(meta_name)
|
|
385
|
-
logger.warning(f"模块 {meta_name} 已禁用,跳过加载")
|
|
386
627
|
return module_objs, enabled_modules, disabled_modules
|
|
387
628
|
|
|
388
629
|
try:
|
|
@@ -390,6 +631,14 @@ class ModuleLoader:
|
|
|
390
631
|
module_obj = sys.modules[loaded_obj.__module__]
|
|
391
632
|
dist = importlib.metadata.distribution(entry_point.dist.name)
|
|
392
633
|
|
|
634
|
+
# 检查模块是否继承自 BaseModule
|
|
635
|
+
from .Core.Bases.module import BaseModule
|
|
636
|
+
is_base_module = inspect.isclass(loaded_obj) and issubclass(loaded_obj, BaseModule)
|
|
637
|
+
|
|
638
|
+
if not is_base_module:
|
|
639
|
+
logger.warning(f"模块 {meta_name} 未继承自 BaseModule,"\
|
|
640
|
+
"如果你是这个模块的作者,请检查 ErisPulse 的文档更新 并尽快迁移!")
|
|
641
|
+
|
|
393
642
|
lazy_load = ModuleLoader._should_lazy_load(loaded_obj)
|
|
394
643
|
|
|
395
644
|
module_info = {
|
|
@@ -400,16 +649,14 @@ class ModuleLoader:
|
|
|
400
649
|
"author": getattr(module_obj, "__author__", ""),
|
|
401
650
|
"license": getattr(module_obj, "__license__", ""),
|
|
402
651
|
"package": entry_point.dist.name,
|
|
403
|
-
"lazy_load": lazy_load
|
|
652
|
+
"lazy_load": lazy_load,
|
|
653
|
+
"is_base_module": is_base_module
|
|
404
654
|
},
|
|
405
655
|
"module_class": loaded_obj
|
|
406
656
|
}
|
|
407
657
|
|
|
408
|
-
module_obj
|
|
658
|
+
setattr(module_obj, "moduleInfo", module_info)
|
|
409
659
|
|
|
410
|
-
# 存储模块信息
|
|
411
|
-
module_registry.set_module(meta_name, module_info)
|
|
412
|
-
|
|
413
660
|
module_objs[meta_name] = module_obj
|
|
414
661
|
enabled_modules.append(meta_name)
|
|
415
662
|
logger.debug(f"从PyPI包加载模块: {meta_name}")
|
|
@@ -428,6 +675,22 @@ class ModuleLoader:
|
|
|
428
675
|
:param module_class: Type 模块类
|
|
429
676
|
:return: bool 如果返回 False,则立即加载;否则懒加载
|
|
430
677
|
"""
|
|
678
|
+
|
|
679
|
+
logger.debug(f"检查模块 {module_class.__name__} 是否应该懒加载")
|
|
680
|
+
|
|
681
|
+
# 首先检查全局懒加载配置
|
|
682
|
+
try:
|
|
683
|
+
from .Core._self_config import get_framework_config
|
|
684
|
+
framework_config = get_framework_config()
|
|
685
|
+
global_lazy_loading = framework_config.get("enable_lazy_loading", True)
|
|
686
|
+
|
|
687
|
+
# 如果全局禁用懒加载,则直接返回False
|
|
688
|
+
if not global_lazy_loading:
|
|
689
|
+
logger.debug(f"全局懒加载已禁用,模块 {module_class.__name__} 将立即加载")
|
|
690
|
+
return False
|
|
691
|
+
except Exception as e:
|
|
692
|
+
logger.warning(f"获取框架配置失败: {e},将使用模块默认配置")
|
|
693
|
+
|
|
431
694
|
# 检查模块是否定义了 should_eager_load() 方法
|
|
432
695
|
if hasattr(module_class, "should_eager_load"):
|
|
433
696
|
try:
|
|
@@ -441,7 +704,7 @@ class ModuleLoader:
|
|
|
441
704
|
|
|
442
705
|
class ModuleInitializer:
|
|
443
706
|
"""
|
|
444
|
-
|
|
707
|
+
模块初始化器(注意:适配器是一个特殊的模块)
|
|
445
708
|
|
|
446
709
|
负责协调适配器和模块的初始化流程
|
|
447
710
|
|
|
@@ -452,10 +715,10 @@ class ModuleInitializer:
|
|
|
452
715
|
"""
|
|
453
716
|
|
|
454
717
|
@staticmethod
|
|
455
|
-
def init() -> bool:
|
|
718
|
+
async def init() -> bool:
|
|
456
719
|
"""
|
|
457
720
|
初始化所有模块和适配器
|
|
458
|
-
|
|
721
|
+
|
|
459
722
|
执行步骤:
|
|
460
723
|
1. 从PyPI包加载适配器
|
|
461
724
|
2. 从PyPI包加载模块
|
|
@@ -469,14 +732,36 @@ class ModuleInitializer:
|
|
|
469
732
|
logger.info("[Init] SDK 正在初始化...")
|
|
470
733
|
|
|
471
734
|
try:
|
|
472
|
-
# 1.
|
|
473
|
-
|
|
474
|
-
|
|
735
|
+
# 1. 并行加载适配器和模块
|
|
736
|
+
(adapter_result, module_result) = await asyncio.gather(
|
|
737
|
+
AdapterLoader.load(),
|
|
738
|
+
ModuleLoader.load(),
|
|
739
|
+
return_exceptions=True
|
|
740
|
+
)
|
|
475
741
|
|
|
476
|
-
#
|
|
477
|
-
|
|
478
|
-
|
|
742
|
+
# 检查是否有异常
|
|
743
|
+
if isinstance(adapter_result, Exception):
|
|
744
|
+
logger.error(f"[Init] 适配器加载失败: {adapter_result}")
|
|
745
|
+
return False
|
|
746
|
+
|
|
747
|
+
if isinstance(module_result, Exception):
|
|
748
|
+
logger.error(f"[Init] 模块加载失败: {module_result}")
|
|
749
|
+
return False
|
|
479
750
|
|
|
751
|
+
# 解包结果
|
|
752
|
+
if not isinstance(adapter_result, Exception):
|
|
753
|
+
adapter_objs, enabled_adapters, disabled_adapters = adapter_result # type: ignore[assignment] || 原因: 已经在方法中进行了类型检查
|
|
754
|
+
else:
|
|
755
|
+
return False
|
|
756
|
+
|
|
757
|
+
if not isinstance(module_result, Exception):
|
|
758
|
+
module_objs, enabled_modules, disabled_modules = module_result # type: ignore[assignment] || 原因: 已经在方法中进行了类型检查
|
|
759
|
+
else:
|
|
760
|
+
return False
|
|
761
|
+
|
|
762
|
+
logger.info(f"[Init] 加载了 {len(enabled_adapters)} 个适配器, {len(disabled_adapters)} 个适配器被禁用")
|
|
763
|
+
logger.info(f"[Init] 加载了 {len(enabled_modules)} 个模块, {len(disabled_modules)} 个模块被禁用")
|
|
764
|
+
|
|
480
765
|
modules_dir = os.path.join(os.path.dirname(__file__), "modules")
|
|
481
766
|
if os.path.exists(modules_dir) and os.listdir(modules_dir):
|
|
482
767
|
logger.warning("[Warning] 你的项目使用了已经弃用的模块加载方式, 请尽快使用 PyPI 模块加载方式代替")
|
|
@@ -487,21 +772,43 @@ class ModuleInitializer:
|
|
|
487
772
|
|
|
488
773
|
# 3. 注册适配器
|
|
489
774
|
logger.debug("[Init] 正在注册适配器...")
|
|
490
|
-
if not ModuleInitializer._register_adapters(enabled_adapters, adapter_objs):
|
|
775
|
+
if not await ModuleInitializer._register_adapters(enabled_adapters, adapter_objs):
|
|
491
776
|
return False
|
|
492
|
-
|
|
777
|
+
|
|
493
778
|
# 4. 初始化模块
|
|
494
779
|
logger.debug("[Init] 正在初始化模块...")
|
|
495
|
-
success = ModuleInitializer._initialize_modules(enabled_modules, module_objs)
|
|
496
|
-
|
|
780
|
+
success = await ModuleInitializer._initialize_modules(enabled_modules, module_objs)
|
|
781
|
+
|
|
782
|
+
if success:
|
|
783
|
+
logger.info("[Init] SDK初始化成功")
|
|
784
|
+
else:
|
|
785
|
+
logger.error("[Init] SDK初始化失败")
|
|
786
|
+
|
|
787
|
+
load_duration = lifecycle.stop_timer("core.init")
|
|
788
|
+
await lifecycle.submit_event(
|
|
789
|
+
"core.init.complete",
|
|
790
|
+
msg="模块初始化完成" if success else "模块初始化失败",
|
|
791
|
+
data={
|
|
792
|
+
"duration": load_duration,
|
|
793
|
+
"success": success
|
|
794
|
+
}
|
|
795
|
+
)
|
|
497
796
|
return success
|
|
498
797
|
|
|
499
798
|
except Exception as e:
|
|
799
|
+
load_duration = lifecycle.stop_timer("core.init")
|
|
800
|
+
await lifecycle.submit_event(
|
|
801
|
+
"core.init.complete",
|
|
802
|
+
msg="模块初始化失败",
|
|
803
|
+
data={
|
|
804
|
+
"duration": load_duration,
|
|
805
|
+
"success": False
|
|
806
|
+
}
|
|
807
|
+
)
|
|
500
808
|
logger.critical(f"SDK初始化严重错误: {e}")
|
|
501
809
|
return False
|
|
502
|
-
|
|
503
810
|
@staticmethod
|
|
504
|
-
def _initialize_modules(modules: List[str], module_objs: Dict[str, Any]) -> bool:
|
|
811
|
+
async def _initialize_modules(modules: List[str], module_objs: Dict[str, Any]) -> bool:
|
|
505
812
|
"""
|
|
506
813
|
{!--< internal-use >!--}
|
|
507
814
|
初始化模块
|
|
@@ -511,73 +818,112 @@ class ModuleInitializer:
|
|
|
511
818
|
|
|
512
819
|
:return: bool 模块初始化是否成功
|
|
513
820
|
"""
|
|
514
|
-
#
|
|
821
|
+
# 并行注册所有模块类
|
|
822
|
+
register_tasks = []
|
|
515
823
|
for module_name in modules:
|
|
516
824
|
module_obj = module_objs[module_name]
|
|
517
825
|
meta_name = module_obj.moduleInfo["meta"]["name"]
|
|
518
826
|
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
module_entries = entry_points.get('erispulse.module', [])
|
|
529
|
-
module_entry_map = {entry.name: entry for entry in module_entries}
|
|
530
|
-
|
|
531
|
-
entry_point = module_entry_map.get(meta_name)
|
|
532
|
-
if entry_point:
|
|
533
|
-
module_class = entry_point.load()
|
|
827
|
+
async def register_module(name, obj):
|
|
828
|
+
try:
|
|
829
|
+
entry_points = importlib.metadata.entry_points()
|
|
830
|
+
if hasattr(entry_points, 'select'):
|
|
831
|
+
module_entries = entry_points.select(group='erispulse.module')
|
|
832
|
+
module_entry_map = {entry.name: entry for entry in module_entries}
|
|
833
|
+
else:
|
|
834
|
+
module_entries = entry_points.get('erispulse.module', []) # type: ignore[assignment] || 原因: 已经在方法中进行了类型检查,这是一个兼容性的写法
|
|
835
|
+
module_entry_map = {entry.name: entry for entry in module_entries}
|
|
534
836
|
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
837
|
+
entry_point = module_entry_map.get(name)
|
|
838
|
+
if entry_point:
|
|
839
|
+
module_class = entry_point.load()
|
|
840
|
+
|
|
841
|
+
module.register(name, module_class, obj.moduleInfo)
|
|
842
|
+
logger.debug(f"注册模块类: {name}")
|
|
843
|
+
return True
|
|
844
|
+
return False
|
|
845
|
+
except Exception as e:
|
|
846
|
+
logger.error(f"注册模块 {name} 失败: {e}")
|
|
847
|
+
return False
|
|
848
|
+
|
|
849
|
+
register_tasks.append(register_module(meta_name, module_obj))
|
|
850
|
+
|
|
851
|
+
# 等待所有注册任务完成
|
|
852
|
+
register_results = await asyncio.gather(*register_tasks, return_exceptions=True)
|
|
853
|
+
|
|
854
|
+
# 检查是否有注册失败的情况
|
|
855
|
+
if any(isinstance(result, Exception) or result is False for result in register_results):
|
|
856
|
+
return False
|
|
545
857
|
|
|
546
|
-
#
|
|
858
|
+
# 将所有模块挂载到sdk对象上
|
|
547
859
|
for module_name in modules:
|
|
548
860
|
module_obj = module_objs[module_name]
|
|
549
861
|
meta_name = module_obj.moduleInfo["meta"]["name"]
|
|
862
|
+
lazy_load = module_obj.moduleInfo["meta"].get("lazy_load", True)
|
|
550
863
|
|
|
551
|
-
if
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
864
|
+
if lazy_load:
|
|
865
|
+
# 使用懒加载方式挂载
|
|
866
|
+
lazy_module = LazyModule(
|
|
867
|
+
meta_name,
|
|
868
|
+
module_obj.moduleInfo["module_class"],
|
|
869
|
+
sdk,
|
|
870
|
+
module_obj.moduleInfo
|
|
871
|
+
)
|
|
872
|
+
setattr(sdk, meta_name, lazy_module)
|
|
873
|
+
logger.debug(f"挂载懒加载模块到sdk: {meta_name}")
|
|
874
|
+
else:
|
|
875
|
+
# 立即加载的模块暂时挂载为None,稍后会加载
|
|
876
|
+
setattr(sdk, meta_name, None)
|
|
877
|
+
logger.debug(f"预挂载立即加载模块到sdk: {meta_name}")
|
|
878
|
+
|
|
879
|
+
# 并行初始化需要立即加载的模块
|
|
880
|
+
eager_load_tasks = []
|
|
881
|
+
for module_name in modules:
|
|
882
|
+
module_obj = module_objs[module_name]
|
|
883
|
+
meta_name = module_obj.moduleInfo["meta"]["name"]
|
|
884
|
+
|
|
885
|
+
async def load_module_if_eager(name, obj):
|
|
886
|
+
try:
|
|
567
887
|
# 检查是否需要立即加载
|
|
568
|
-
|
|
569
|
-
if
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
888
|
+
entry_points = importlib.metadata.entry_points()
|
|
889
|
+
if hasattr(entry_points, 'select'):
|
|
890
|
+
module_entries = entry_points.select(group='erispulse.module')
|
|
891
|
+
module_entry_map = {entry.name: entry for entry in module_entries}
|
|
892
|
+
else:
|
|
893
|
+
module_entries = entry_points.get('erispulse.module', []) # type: ignore[assignment] || 原因: 已经在方法中进行了类型检查,这是一个兼容性的写法
|
|
894
|
+
module_entry_map = {entry.name: entry for entry in module_entries}
|
|
895
|
+
|
|
896
|
+
entry_point = module_entry_map.get(name)
|
|
897
|
+
if entry_point:
|
|
898
|
+
module_class = entry_point.load()
|
|
573
899
|
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
900
|
+
# 检查是否需要立即加载
|
|
901
|
+
lazy_load = ModuleLoader._should_lazy_load(module_class)
|
|
902
|
+
if not lazy_load:
|
|
903
|
+
# 立即加载模块
|
|
904
|
+
result = await module.load(name)
|
|
905
|
+
if not result:
|
|
906
|
+
logger.error(f"加载模块 {name} 失败")
|
|
907
|
+
else:
|
|
908
|
+
logger.debug(f"立即加载模块: {name}")
|
|
909
|
+
# 更新sdk上的引用
|
|
910
|
+
setattr(sdk, name, module.get(name))
|
|
911
|
+
return result
|
|
912
|
+
return True # 不需要立即加载的模块返回True
|
|
913
|
+
except Exception as e:
|
|
914
|
+
logger.error(f"初始化模块 {name} 失败: {e}")
|
|
915
|
+
return False
|
|
916
|
+
|
|
917
|
+
eager_load_tasks.append(load_module_if_eager(meta_name, module_obj))
|
|
918
|
+
|
|
919
|
+
# 等待所有立即加载任务完成
|
|
920
|
+
load_results = await asyncio.gather(*eager_load_tasks, return_exceptions=True)
|
|
921
|
+
|
|
922
|
+
# 检查是否有加载失败的情况
|
|
923
|
+
return not any(isinstance(result, Exception) or result is False for result in load_results)
|
|
924
|
+
|
|
579
925
|
@staticmethod
|
|
580
|
-
def _register_adapters(adapters: List[str], adapter_objs: Dict[str, Any]) -> bool:
|
|
926
|
+
async def _register_adapters(adapters: List[str], adapter_objs: Dict[str, Any]) -> bool:
|
|
581
927
|
"""
|
|
582
928
|
{!--< internal-use >!--}
|
|
583
929
|
注册适配器
|
|
@@ -587,46 +933,57 @@ class ModuleInitializer:
|
|
|
587
933
|
|
|
588
934
|
:return: bool 适配器注册是否成功
|
|
589
935
|
"""
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
936
|
+
# 并行注册所有适配器
|
|
937
|
+
register_tasks = []
|
|
938
|
+
|
|
593
939
|
for adapter_name in adapters:
|
|
594
940
|
adapter_obj = adapter_objs[adapter_name]
|
|
595
941
|
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
instance = registered_classes[adapter_class]
|
|
606
|
-
# 改为直接操作适配器字典而不是调用register
|
|
607
|
-
sdk.adapter._adapters[platform] = instance
|
|
608
|
-
sdk.adapter._platform_to_instance[platform] = instance
|
|
609
|
-
logger.debug(f"复用适配器实例 {adapter_class.__name__} 到平台别称 {platform}")
|
|
610
|
-
else:
|
|
611
|
-
init_signature = inspect.signature(adapter_class.__init__)
|
|
612
|
-
params = init_signature.parameters
|
|
613
|
-
|
|
614
|
-
if 'sdk' in params:
|
|
615
|
-
instance = adapter_class(sdk)
|
|
616
|
-
else:
|
|
617
|
-
instance = adapter_class()
|
|
942
|
+
async def register_single_adapter(name, obj):
|
|
943
|
+
try:
|
|
944
|
+
success = True
|
|
945
|
+
if hasattr(obj, "adapterInfo") and isinstance(obj.adapterInfo, dict):
|
|
946
|
+
for platform, adapter_info in obj.adapterInfo.items():
|
|
947
|
+
if platform in adapter._adapters:
|
|
948
|
+
continue
|
|
949
|
+
|
|
950
|
+
adapter_class = adapter_info["adapter_class"]
|
|
618
951
|
|
|
619
|
-
|
|
620
|
-
sdk.adapter._adapters[platform] = instance
|
|
621
|
-
sdk.adapter._platform_to_instance[platform] = instance
|
|
622
|
-
registered_classes[adapter_class] = instance
|
|
952
|
+
adapter.register(platform, adapter_class, adapter_info)
|
|
623
953
|
logger.info(f"注册适配器: {platform} ({adapter_class.__name__})")
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
954
|
+
|
|
955
|
+
# 提交适配器加载完成事件
|
|
956
|
+
await lifecycle.submit_event(
|
|
957
|
+
"adapter.load",
|
|
958
|
+
msg=f"适配器 {platform} 加载完成",
|
|
959
|
+
data={
|
|
960
|
+
"platform": platform,
|
|
961
|
+
"success": True
|
|
962
|
+
}
|
|
963
|
+
)
|
|
964
|
+
return success
|
|
965
|
+
except Exception as e:
|
|
966
|
+
logger.error(f"适配器 {name} 注册失败: {e}")
|
|
967
|
+
# 提交适配器加载失败事件
|
|
968
|
+
await lifecycle.submit_event(
|
|
969
|
+
"adapter.load",
|
|
970
|
+
msg=f"适配器 {name} 加载失败: {e}",
|
|
971
|
+
data={
|
|
972
|
+
"platform": name,
|
|
973
|
+
"success": False
|
|
974
|
+
}
|
|
975
|
+
)
|
|
976
|
+
return False
|
|
977
|
+
|
|
978
|
+
register_tasks.append(register_single_adapter(adapter_name, adapter_obj))
|
|
979
|
+
|
|
980
|
+
# 等待所有注册任务完成
|
|
981
|
+
register_results = await asyncio.gather(*register_tasks, return_exceptions=True)
|
|
982
|
+
|
|
983
|
+
# 检查是否有注册失败的情况
|
|
984
|
+
return not any(isinstance(result, Exception) or result is False for result in register_results)
|
|
985
|
+
|
|
986
|
+
async def init_progress() -> bool:
|
|
630
987
|
"""
|
|
631
988
|
初始化项目环境文件
|
|
632
989
|
|
|
@@ -653,7 +1010,7 @@ from ErisPulse import sdk
|
|
|
653
1010
|
|
|
654
1011
|
async def main():
|
|
655
1012
|
try:
|
|
656
|
-
isInit = await sdk.
|
|
1013
|
+
isInit = await sdk.init()
|
|
657
1014
|
|
|
658
1015
|
if not isInit:
|
|
659
1016
|
sdk.logger.error("ErisPulse 初始化失败,请检查日志")
|
|
@@ -679,11 +1036,10 @@ if __name__ == "__main__":
|
|
|
679
1036
|
|
|
680
1037
|
return main_init
|
|
681
1038
|
except Exception as e:
|
|
682
|
-
|
|
1039
|
+
logger.error(f"无法初始化项目环境: {e}")
|
|
683
1040
|
return False
|
|
684
1041
|
|
|
685
|
-
|
|
686
|
-
def _prepare_environment() -> bool:
|
|
1042
|
+
async def _prepare_environment() -> bool:
|
|
687
1043
|
"""
|
|
688
1044
|
{!--< internal-use >!--}
|
|
689
1045
|
准备运行环境
|
|
@@ -692,29 +1048,45 @@ def _prepare_environment() -> bool:
|
|
|
692
1048
|
|
|
693
1049
|
:return: bool 环境准备是否成功
|
|
694
1050
|
"""
|
|
1051
|
+
await lifecycle.submit_event(
|
|
1052
|
+
"core.init.start",
|
|
1053
|
+
msg="开始初始化"
|
|
1054
|
+
)
|
|
1055
|
+
lifecycle.start_timer("core.init")
|
|
1056
|
+
|
|
695
1057
|
logger.info("[Init] 准备初始化环境...")
|
|
696
1058
|
try:
|
|
697
|
-
from .Core.
|
|
1059
|
+
from .Core._self_config import get_erispulse_config
|
|
698
1060
|
get_erispulse_config()
|
|
699
1061
|
logger.info("[Init] 配置文件已加载")
|
|
700
|
-
|
|
701
|
-
main_init = init_progress()
|
|
1062
|
+
|
|
1063
|
+
main_init = await init_progress()
|
|
702
1064
|
if main_init:
|
|
703
1065
|
logger.info("[Init] 项目入口已生成, 你可以在 main.py 中编写一些代码")
|
|
704
1066
|
return True
|
|
705
1067
|
except Exception as e:
|
|
1068
|
+
load_duration = lifecycle.stop_timer("core.init")
|
|
1069
|
+
await lifecycle.submit_event(
|
|
1070
|
+
"core.init.complete",
|
|
1071
|
+
msg="模块初始化失败",
|
|
1072
|
+
data={
|
|
1073
|
+
"duration": load_duration,
|
|
1074
|
+
"success": False
|
|
1075
|
+
}
|
|
1076
|
+
)
|
|
706
1077
|
logger.error(f"环境准备失败: {e}")
|
|
707
1078
|
return False
|
|
708
1079
|
|
|
709
|
-
def init() -> bool:
|
|
1080
|
+
async def init() -> bool:
|
|
710
1081
|
"""
|
|
711
1082
|
SDK初始化入口
|
|
712
1083
|
|
|
713
1084
|
:return: bool SDK初始化是否成功
|
|
714
1085
|
"""
|
|
715
|
-
if not _prepare_environment():
|
|
1086
|
+
if not await _prepare_environment():
|
|
716
1087
|
return False
|
|
717
|
-
|
|
1088
|
+
|
|
1089
|
+
return await ModuleInitializer.init()
|
|
718
1090
|
|
|
719
1091
|
def init_task() -> asyncio.Task:
|
|
720
1092
|
"""
|
|
@@ -723,9 +1095,9 @@ def init_task() -> asyncio.Task:
|
|
|
723
1095
|
:return: asyncio.Task 初始化任务
|
|
724
1096
|
"""
|
|
725
1097
|
async def _async_init():
|
|
726
|
-
if not _prepare_environment():
|
|
1098
|
+
if not await _prepare_environment():
|
|
727
1099
|
return False
|
|
728
|
-
return ModuleInitializer.init()
|
|
1100
|
+
return await ModuleInitializer.init()
|
|
729
1101
|
|
|
730
1102
|
try:
|
|
731
1103
|
return asyncio.create_task(_async_init())
|
|
@@ -733,8 +1105,96 @@ def init_task() -> asyncio.Task:
|
|
|
733
1105
|
loop = asyncio.new_event_loop()
|
|
734
1106
|
asyncio.set_event_loop(loop)
|
|
735
1107
|
return loop.create_task(_async_init())
|
|
1108
|
+
async def uninit() -> bool:
|
|
1109
|
+
"""
|
|
1110
|
+
SDK反初始化
|
|
1111
|
+
|
|
1112
|
+
执行以下操作:
|
|
1113
|
+
1. 关闭所有适配器
|
|
1114
|
+
2. 卸载所有模块
|
|
1115
|
+
3. 清理所有事件处理器
|
|
1116
|
+
4. 清理僵尸线程
|
|
1117
|
+
|
|
1118
|
+
:return: bool 反初始化是否成功
|
|
1119
|
+
"""
|
|
1120
|
+
try:
|
|
1121
|
+
logger.info("[Uninit] 开始反初始化SDK...")
|
|
1122
|
+
|
|
1123
|
+
# 1. 关闭所有适配器
|
|
1124
|
+
logger.debug("[Uninit] 正在关闭适配器...")
|
|
1125
|
+
await adapter.shutdown()
|
|
1126
|
+
|
|
1127
|
+
# 2. 卸载所有模块
|
|
1128
|
+
logger.debug("[Uninit] 正在卸载模块...")
|
|
1129
|
+
await module.unload()
|
|
1130
|
+
|
|
1131
|
+
# 3. 清理Event模块中的所有事件处理器
|
|
1132
|
+
Event._clear_all_handlers()
|
|
1133
|
+
|
|
1134
|
+
# 4. 清理僵尸线程
|
|
1135
|
+
logger.debug("[Uninit] 正在清理线程...")
|
|
1136
|
+
# SDK本身不创建线程,但可以记录可能的线程泄漏
|
|
1137
|
+
current_task = asyncio.current_task()
|
|
1138
|
+
logger.debug(f"[Uninit] 当前任务: {current_task}")
|
|
1139
|
+
|
|
1140
|
+
logger.info("[Uninit] SDK反初始化完成")
|
|
1141
|
+
return True
|
|
1142
|
+
|
|
1143
|
+
except Exception as e:
|
|
1144
|
+
logger.error(f"[Uninit] SDK反初始化失败: {e}")
|
|
1145
|
+
return False
|
|
1146
|
+
|
|
1147
|
+
async def restart() -> bool:
|
|
1148
|
+
"""
|
|
1149
|
+
SDK重新启动
|
|
1150
|
+
|
|
1151
|
+
执行完整的反初始化后再初始化过程
|
|
1152
|
+
|
|
1153
|
+
:return: bool 重新加载是否成功
|
|
1154
|
+
"""
|
|
1155
|
+
logger.info("[Reload] 开始重新加载SDK...")
|
|
1156
|
+
|
|
1157
|
+
# 先执行反初始化
|
|
1158
|
+
if not await uninit():
|
|
1159
|
+
logger.error("[Reload] 反初始化失败,无法继续重新加载")
|
|
1160
|
+
return False
|
|
1161
|
+
|
|
1162
|
+
# 再执行初始化
|
|
1163
|
+
logger.info("[Reload] 开始重新初始化SDK...")
|
|
1164
|
+
if not await init():
|
|
1165
|
+
logger.error("[Reload] 初始化失败,请检查日志")
|
|
1166
|
+
return False
|
|
1167
|
+
|
|
1168
|
+
logger.info("[Reload] 正在启动适配器...")
|
|
1169
|
+
await adapter.startup()
|
|
1170
|
+
|
|
1171
|
+
logger.info("[Reload] 重新加载完成")
|
|
1172
|
+
return True
|
|
736
1173
|
|
|
737
|
-
def
|
|
1174
|
+
async def run() -> None:
|
|
1175
|
+
"""
|
|
1176
|
+
无头模式运行ErisPulse
|
|
1177
|
+
|
|
1178
|
+
此方法提供了一种无需入口启动的方式,适用于与其它框架集成的场景
|
|
1179
|
+
"""
|
|
1180
|
+
try:
|
|
1181
|
+
isInit = await init()
|
|
1182
|
+
|
|
1183
|
+
if not isInit:
|
|
1184
|
+
logger.error("ErisPulse 初始化失败,请检查日志")
|
|
1185
|
+
return
|
|
1186
|
+
|
|
1187
|
+
await adapter.startup()
|
|
1188
|
+
|
|
1189
|
+
# 保持程序运行
|
|
1190
|
+
await asyncio.Event().wait()
|
|
1191
|
+
except Exception as e:
|
|
1192
|
+
logger.error(e)
|
|
1193
|
+
finally:
|
|
1194
|
+
await module.unload()
|
|
1195
|
+
await adapter.shutdown()
|
|
1196
|
+
|
|
1197
|
+
async def load_module(module_name: str) -> bool:
|
|
738
1198
|
"""
|
|
739
1199
|
手动加载指定模块
|
|
740
1200
|
|
|
@@ -744,15 +1204,29 @@ def load_module(module_name: str) -> bool:
|
|
|
744
1204
|
{!--< tips >!--}
|
|
745
1205
|
1. 可用于手动触发懒加载模块的初始化
|
|
746
1206
|
2. 如果模块不存在或已加载会返回False
|
|
1207
|
+
3. 对于需要异步初始化的模块,这是唯一的加载方式
|
|
747
1208
|
{!--< /tips >!--}
|
|
748
1209
|
"""
|
|
749
1210
|
try:
|
|
750
|
-
|
|
751
|
-
if isinstance(
|
|
752
|
-
#
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
1211
|
+
module_instance = getattr(sdk, module_name, None)
|
|
1212
|
+
if isinstance(module_instance, LazyModule):
|
|
1213
|
+
# 检查模块是否需要异步初始化
|
|
1214
|
+
if hasattr(module_instance, '_needs_async_init') and object.__getattribute__(module_instance, '_needs_async_init'):
|
|
1215
|
+
# 对于需要异步初始化的模块,执行完整异步初始化
|
|
1216
|
+
await module_instance._initialize()
|
|
1217
|
+
object.__setattr__(module_instance, '_needs_async_init', False) # 清除标志
|
|
1218
|
+
return True
|
|
1219
|
+
# 检查模块是否已经同步初始化但未完成异步部分
|
|
1220
|
+
elif (object.__getattribute__(module_instance, '_initialized') and
|
|
1221
|
+
object.__getattribute__(module_instance, '_is_base_module')):
|
|
1222
|
+
# 如果是BaseModule子类且已同步初始化,只需完成异步部分
|
|
1223
|
+
await module_instance._complete_async_init()
|
|
1224
|
+
return True
|
|
1225
|
+
else:
|
|
1226
|
+
# 触发懒加载模块的完整初始化
|
|
1227
|
+
await module_instance._initialize()
|
|
1228
|
+
return True
|
|
1229
|
+
elif module_instance is not None:
|
|
756
1230
|
logger.warning(f"模块 {module_name} 已经加载")
|
|
757
1231
|
return False
|
|
758
1232
|
else:
|
|
@@ -761,7 +1235,11 @@ def load_module(module_name: str) -> bool:
|
|
|
761
1235
|
except Exception as e:
|
|
762
1236
|
logger.error(f"加载模块 {module_name} 失败: {e}")
|
|
763
1237
|
return False
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
sdk
|
|
767
|
-
sdk
|
|
1238
|
+
|
|
1239
|
+
logger.debug("ErisPulse 正在挂载必要的入口方法")
|
|
1240
|
+
setattr(sdk, "init", init)
|
|
1241
|
+
setattr(sdk, "init_task", init_task)
|
|
1242
|
+
setattr(sdk, "load_module", load_module)
|
|
1243
|
+
setattr(sdk, "run", run)
|
|
1244
|
+
setattr(sdk, "restart", restart)
|
|
1245
|
+
setattr(sdk, "uninit", uninit)
|