ErisPulse 1.1.14.dev1__py3-none-any.whl → 1.1.16__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/__init__.py CHANGED
@@ -36,10 +36,13 @@ sdk.logger.info("SDK已初始化")
36
36
 
37
37
  """
38
38
 
39
- import types
40
- sdk = types.SimpleNamespace()
41
39
  import os
42
40
  import sys
41
+
42
+ # 依赖类型
43
+ import types
44
+
45
+ # BaseModules: SDK核心模块
43
46
  from . import util
44
47
  from .raiserr import raiserr
45
48
  from .logger import logger
@@ -50,177 +53,199 @@ from .adapter import adapter, BaseAdapter, SendDSL
50
53
  # 这里不能删,确保windows下的shell能正确显示颜色
51
54
  os.system('')
52
55
 
53
- setattr(sdk, "env", env)
54
- setattr(sdk, "mods", mods)
55
- setattr(sdk, "util", util)
56
- setattr(sdk, "raiserr", raiserr)
57
- setattr(sdk, "logger", logger)
58
- setattr(sdk, "adapter", adapter)
59
- setattr(sdk, "SendDSL", SendDSL)
60
- setattr(sdk, "BaseAdapter", BaseAdapter)
61
-
62
- # 注册 ErrorHook 并预注册常用错误类型
63
- raiserr.register("CaughtExternalError" , doc="捕获的非SDK抛出的异常")
64
- raiserr.register("InitError" , doc="SDK初始化错误")
65
- raiserr.register("MissingDependencyError" , doc="缺少依赖错误")
66
- raiserr.register("InvalidDependencyError" , doc="依赖无效错误")
67
- raiserr.register("CycleDependencyError" , doc="依赖循环错误")
68
- raiserr.register("ModuleLoadError" , doc="模块加载错误")
69
-
70
- def init() -> None:
56
+ sdk = types.SimpleNamespace()
57
+
58
+ BaseModules = {
59
+ "util" : util,
60
+ "logger" : logger,
61
+ "env" : env,
62
+ "mods" : mods,
63
+ "adapter" : adapter,
64
+ "SendDSL" : SendDSL, # 链式发送基类 - 兼容原 sdk.SendDSL | 待弃用, 需要在 Adapter继承类中手动创建嵌套类并集成 super().SendDSL()
65
+ "AdapterFather" : BaseAdapter,
66
+ "BaseAdapter" : BaseAdapter
67
+ }
68
+
69
+ BaseErrors = {
70
+ "ExternalError" : "外部捕获异常",
71
+ "CaughtExternalError" : "捕获的非SDK抛出的异常",
72
+ "InitError" : "SDK初始化错误",
73
+ "MissingDependencyError" : "缺少依赖错误",
74
+ "InvalidDependencyError" : "依赖无效错误",
75
+ "CycleDependencyError" : "依赖循环错误",
76
+ "ModuleLoadError" : "模块加载错误"
77
+ }
78
+
79
+ for module, moduleObj in BaseModules.items():
80
+ try:
81
+ setattr(sdk, module, moduleObj)
82
+ except Exception as e:
83
+ raise e
84
+
85
+ for error, doc in BaseErrors.items():
86
+ try:
87
+ raiserr.register(error, doc=doc)
88
+ except Exception as e:
89
+ raise e
90
+
91
+ def _prepare_environment() -> bool:
92
+ # 检查环境
93
+ logger.info("[Init] 准备初始化环境...")
71
94
  try:
72
- logger.info("[Init] SDK 正在初始化...")
73
95
  if env.create_env_file_if_not_exists():
74
96
  logger.info("[Init] 项目首次初始化,建议先配置环境变量")
75
97
  if input("是否立即退出?(y/n): ").strip().lower() == "y":
76
- sys.exit(0)
98
+ return False
77
99
  env.load_env_file()
78
-
79
- sdkModulePath = os.path.join(os.path.dirname(__file__), "modules")
80
-
81
- if not os.path.exists(sdkModulePath):
82
- os.makedirs(sdkModulePath)
83
-
84
- sys.path.append(sdkModulePath)
85
-
86
- TempModules = [
87
- x for x in os.listdir(sdkModulePath)
88
- if os.path.isdir(os.path.join(sdkModulePath, x))
89
- ]
90
-
91
- sdkInstalledModuleNames: list[str] = []
92
- disabledModules: list[str] = []
93
-
94
- # ==== 扫描模块并收集基本信息 ====
95
- module_objs = {} # {module_name: moduleObj}
96
- for module_name in TempModules:
97
- try:
98
- moduleObj = __import__(module_name)
99
- if not hasattr(moduleObj, "moduleInfo") or not isinstance(moduleObj.moduleInfo, dict):
100
- logger.warning(f"模块 {module_name} 缺少有效的 'moduleInfo' 字典.")
101
- continue
102
- if "name" not in moduleObj.moduleInfo.get("meta", {}):
103
- logger.warning(f"模块 {module_name} 的 'moduleInfo' 字典 缺少必要 'name' 键.")
104
- continue
105
- if not hasattr(moduleObj, "Main"):
106
- logger.warning(f"模块 {module_name} 缺少 'Main' 类.")
107
- continue
108
-
109
- meta_name = moduleObj.moduleInfo["meta"]["name"]
110
- module_info = mods.get_module(meta_name)
111
- if module_info is None:
112
- module_info = {
113
- "status": True,
114
- "info": moduleObj.moduleInfo
115
- }
116
- mods.set_module(meta_name, module_info)
117
- logger.info(f"模块 {meta_name} 信息已初始化并存储到数据库")
118
-
119
- if not module_info.get('status', True):
120
- disabledModules.append(module_name)
121
- logger.warning(f"模块 {meta_name} 已禁用,跳过加载")
122
- continue
123
-
124
- required_deps = moduleObj.moduleInfo.get("dependencies", {}).get("requires", [])
125
- missing_required_deps = [dep for dep in required_deps if dep not in TempModules]
126
- if missing_required_deps:
127
- logger.error(f"模块 {module_name} 缺少必需依赖: {missing_required_deps}")
128
- raiserr.MissingDependencyError(f"模块 {module_name} 缺少必需依赖: {missing_required_deps}")
129
-
130
- optional_deps = moduleObj.moduleInfo.get("dependencies", {}).get("optional", [])
131
- available_optional_deps = []
132
- for dep in optional_deps:
133
- if isinstance(dep, list):
134
- available_deps = [d for d in dep if d in TempModules]
135
- if available_deps:
136
- available_optional_deps.extend(available_deps)
137
- elif dep in TempModules:
138
- available_optional_deps.append(dep)
139
-
140
- if optional_deps and not available_optional_deps:
141
- logger.warning(f"模块 {module_name} 缺少所有可选依赖: {optional_deps}")
142
-
143
- module_objs[module_name] = moduleObj
144
- sdkInstalledModuleNames.append(module_name)
145
-
146
- except Exception as e:
147
- logger.warning(f"模块 {module_name} 加载失败: {e}")
100
+ return True
101
+ except Exception as e:
102
+ logger.error(f"环境准备失败: {e}")
103
+ return False
104
+ def _scan_modules(module_path: str) -> tuple[dict, list, list]:
105
+ # 扫描并验证模块
106
+ module_objs = {}
107
+ enabled_modules = []
108
+ disabled_modules = []
109
+
110
+ if not os.path.exists(module_path):
111
+ os.makedirs(module_path)
112
+ sys.path.append(module_path)
113
+
114
+ for module_name in os.listdir(module_path):
115
+ if not os.path.isdir(os.path.join(module_path, module_name)):
116
+ continue
117
+
118
+ try:
119
+ moduleObj = __import__(module_name)
120
+ if not _validate_module(moduleObj, module_name):
148
121
  continue
149
-
150
- # ==== 构建依赖图并进行拓扑排序 ====
151
- sdkModuleDependencies = {}
152
- for module_name in sdkInstalledModuleNames:
153
- moduleObj = module_objs[module_name]
154
- meta_name = moduleObj.moduleInfo["meta"]["name"]
155
-
156
- req_deps = moduleObj.moduleInfo.get("dependencies", {}).get("requires", [])
157
- opt_deps = moduleObj.moduleInfo.get("dependencies", {}).get("optional", [])
158
-
159
- available_optional_deps = [dep for dep in opt_deps if dep in sdkInstalledModuleNames]
160
- deps = req_deps + available_optional_deps
161
-
162
- for dep in deps:
163
- if dep in disabledModules:
164
- logger.warning(f"模块 {meta_name} 的依赖模块 {dep} 已禁用,跳过加载")
165
- continue
166
-
167
- if not all(dep in sdkInstalledModuleNames for dep in deps):
168
- raiserr.InvalidDependencyError(f"模块 {meta_name} 的依赖无效: {deps}")
169
- sdkModuleDependencies[module_name] = deps
170
-
171
- sdkInstalledModuleNames: list[str] = sdk.util.topological_sort(
172
- sdkInstalledModuleNames, sdkModuleDependencies, raiserr.CycleDependencyError
173
- )
174
- # 存储模块依赖关系到env
175
- env.set('module_dependencies', {
176
- 'modules': sdkInstalledModuleNames,
177
- 'dependencies': sdkModuleDependencies
178
- })
179
-
180
- # ==== 注册适配器 ====
181
- logger.debug("[Init] 开始注册适配器...")
182
- for module_name in sdkInstalledModuleNames:
183
- moduleObj = module_objs[module_name]
122
+
184
123
  meta_name = moduleObj.moduleInfo["meta"]["name"]
185
-
186
- try:
187
- if hasattr(moduleObj, "adapterInfo") and isinstance(moduleObj.adapterInfo, dict):
188
- for platform_name, adapter_class in moduleObj.adapterInfo.items():
189
- sdk.adapter.register(platform_name, adapter_class)
190
- logger.info(f"模块 {meta_name} 注册了适配器: {platform_name}")
191
- except Exception as e:
192
- logger.error(f"模块 {meta_name} 注册适配器失败: {e}")
193
-
194
- # ==== 存储模块信息到数据库 ====
195
- all_modules_info = {}
196
- for module_name in sdkInstalledModuleNames:
197
- moduleObj = module_objs[module_name]
198
- moduleInfo: dict = moduleObj.moduleInfo
199
-
200
- meta_name = moduleInfo.get("meta", {}).get("name", None)
201
- module_info = mods.get_module(meta_name)
202
- mods.set_module(meta_name, {
124
+ module_info = mods.get_module(meta_name) or {
203
125
  "status": True,
204
- "info": moduleInfo
205
- })
206
- logger.debug("所有模块信息已加载并存储到数据库")
207
-
208
- # ==== 实例化 Main 类并挂载到 sdk ====
209
- logger.debug("[Init] 开始实例化模块 Main 类...")
210
- for module_name in sdkInstalledModuleNames:
211
- moduleObj = module_objs[module_name]
212
- meta_name = moduleObj.moduleInfo["meta"]["name"]
213
-
214
- module_status = mods.get_module_status(meta_name)
215
- if not module_status:
126
+ "info": moduleObj.moduleInfo
127
+ }
128
+ mods.set_module(meta_name, module_info)
129
+
130
+ if not module_info.get('status', True):
131
+ disabled_modules.append(module_name)
132
+ logger.warning(f"模块 {meta_name} 已禁用,跳过加载")
216
133
  continue
217
-
218
- moduleMain = moduleObj.Main(sdk)
219
- setattr(moduleMain, "moduleInfo", moduleObj.moduleInfo)
220
- setattr(sdk, meta_name, moduleMain)
221
- logger.debug(f"模块 {meta_name} 正在初始化")
134
+
135
+ _check_dependencies(moduleObj, module_name, os.listdir(module_path))
136
+ module_objs[module_name] = moduleObj
137
+ enabled_modules.append(module_name)
138
+
139
+ except Exception as e:
140
+ logger.warning(f"模块 {module_name} 加载失败: {e}")
141
+
142
+ return module_objs, enabled_modules, disabled_modules
143
+
144
+ def _validate_module(moduleObj, module_name: str) -> bool:
145
+ # 验证模块基本结构
146
+ if not hasattr(moduleObj, "moduleInfo") or not isinstance(moduleObj.moduleInfo, dict):
147
+ logger.warning(f"模块 {module_name} 缺少有效的 'moduleInfo' 字典")
148
+ return False
149
+ if "name" not in moduleObj.moduleInfo.get("meta", {}):
150
+ logger.warning(f"模块 {module_name} 缺少必要 'name' 键")
151
+ return False
152
+ if not hasattr(moduleObj, "Main"):
153
+ logger.warning(f"模块 {module_name} 缺少 'Main' 类")
154
+ return False
155
+ return True
156
+
157
+ def _check_dependencies(moduleObj, module_name: str, available_modules: list):
158
+ # 检查模块依赖关系
159
+ required_deps = moduleObj.moduleInfo.get("dependencies", {}).get("requires", [])
160
+ if missing := [dep for dep in required_deps if dep not in available_modules]:
161
+ logger.error(f"模块 {module_name} 缺少必需依赖: {missing}")
162
+ raiserr.MissingDependencyError(f"模块 {module_name} 缺少必需依赖: {missing}")
163
+
164
+ optional_deps = moduleObj.moduleInfo.get("dependencies", {}).get("optional", [])
165
+ available_optional = [
166
+ dep for dep in optional_deps
167
+ if (isinstance(dep, list) and any(d in available_modules for d in dep))
168
+ or (not isinstance(dep, list) and dep in available_modules)
169
+ ]
170
+ if optional_deps and not available_optional:
171
+ logger.warning(f"模块 {module_name} 缺少所有可选依赖: {optional_deps}")
172
+
173
+ def _resolve_dependencies(modules: list, module_objs: dict) -> list:
174
+ # 解析模块依赖关系并进行拓扑排序
175
+ dependencies = {}
176
+ for module_name in modules:
177
+ moduleObj = module_objs[module_name]
178
+ req_deps = moduleObj.moduleInfo.get("dependencies", {}).get("requires", [])
179
+ opt_deps = moduleObj.moduleInfo.get("dependencies", {}).get("optional", [])
180
+ available_opt = [dep for dep in opt_deps if dep in modules]
181
+ dependencies[module_name] = req_deps + available_opt
182
+
183
+ sorted_modules = sdk.util.topological_sort(modules, dependencies, raiserr.CycleDependencyError)
184
+ env.set('module_dependencies', {
185
+ 'modules': sorted_modules,
186
+ 'dependencies': dependencies
187
+ })
188
+ return sorted_modules
189
+
190
+ def _register_adapters(modules: list, module_objs: dict) -> bool:
191
+ # 注册适配器
192
+ success = True
193
+ logger.debug("[Init] 开始注册适配器...")
194
+ for module_name in modules:
195
+ moduleObj = module_objs[module_name]
196
+ meta_name = moduleObj.moduleInfo["meta"]["name"]
197
+
198
+ try:
199
+ if hasattr(moduleObj, "adapterInfo") and isinstance(moduleObj.adapterInfo, dict):
200
+ for platform, adapter_class in moduleObj.adapterInfo.items():
201
+ sdk.adapter.register(platform, adapter_class)
202
+ logger.info(f"模块 {meta_name} 注册适配器: {platform}")
203
+ except Exception as e:
204
+ logger.error(f"模块 {meta_name} 适配器注册失败: {e}")
205
+ success = False
206
+ return success
207
+
208
+ def _initialize_modules(modules: list, module_objs: dict) -> bool:
209
+ # 初始化模块
210
+ success = True
211
+ logger.debug("[Init] 开始实例化模块...")
212
+ for module_name in modules:
213
+ moduleObj = module_objs[module_name]
214
+ meta_name = moduleObj.moduleInfo["meta"]["name"]
215
+
216
+ try:
217
+ if mods.get_module_status(meta_name):
218
+ moduleMain = moduleObj.Main(sdk)
219
+ setattr(moduleMain, "moduleInfo", moduleObj.moduleInfo)
220
+ setattr(sdk, meta_name, moduleMain)
221
+ logger.debug(f"模块 {meta_name} 初始化完成")
222
+ except Exception as e:
223
+ logger.error(f"模块 {meta_name} 初始化失败: {e}")
224
+ success = False
225
+ return success
226
+
227
+ def init() -> bool:
228
+ logger.info("[Init] SDK 正在初始化...")
229
+ try:
230
+ if not _prepare_environment():
231
+ return False
232
+
233
+ module_path = os.path.join(os.path.dirname(__file__), "modules")
234
+ module_objs, enabled_modules, _ = _scan_modules(module_path)
235
+
236
+ if not enabled_modules:
237
+ logger.warning("没有找到可用的模块")
238
+ return True
239
+
240
+ sorted_modules = _resolve_dependencies(enabled_modules, module_objs)
241
+ if not _register_adapters(sorted_modules, module_objs):
242
+ return False
243
+
244
+ return _initialize_modules(sorted_modules, module_objs)
245
+
222
246
  except Exception as e:
247
+ logger.critical(f"SDK初始化严重错误: {e}")
223
248
  raiserr.InitError(f"sdk初始化失败: {e}", exit=True)
249
+ return False
224
250
 
225
-
226
- sdk.init = init
251
+ sdk.init = init
ErisPulse/__main__.py CHANGED
@@ -44,6 +44,7 @@ epsdk origin add https://example.com/map.json
44
44
  """
45
45
 
46
46
  import argparse
47
+ import importlib
47
48
  import os
48
49
  import sys
49
50
  import time
@@ -549,7 +550,74 @@ def install_pip_dependencies(dependencies):
549
550
  shellprint.panel(f"安装pip依赖失败: {e.stderr}", "错误", "error")
550
551
  return False
551
552
 
553
+ def install_local_module(module_path, force=False):
554
+ """安装本地目录中的模块"""
555
+ module_path = os.path.abspath(module_path)
556
+ if not os.path.exists(module_path):
557
+ shellprint.panel(f"路径不存在: {module_path}", "错误", "error")
558
+ return False
559
+
560
+ # 尝试从目录名获取模块名
561
+ module_name = os.path.basename(module_path.rstrip('/\\'))
562
+
563
+ # 检查是否是有效的模块目录
564
+ init_py = os.path.join(module_path, '__init__.py')
565
+ if not os.path.exists(init_py):
566
+ shellprint.panel(f"目录 {module_path} 不是一个有效的Python模块", "错误", "error")
567
+ return False
568
+
569
+ # 尝试导入模块获取moduleInfo
570
+ try:
571
+ spec = importlib.util.spec_from_file_location(module_name, init_py)
572
+ module = importlib.util.module_from_spec(spec)
573
+ spec.loader.exec_module(module)
574
+ if not hasattr(module, 'moduleInfo'):
575
+ shellprint.panel(f"模块 {module_name} 缺少 moduleInfo 定义", "错误", "error")
576
+ return False
577
+ except Exception as e:
578
+ shellprint.panel(f"导入模块 {module_name} 失败: {e}", "错误", "error")
579
+ return False
580
+
581
+ module_info = mods.get_module(module_name)
582
+ if module_info and not force:
583
+ meta = module_info.get('info', {}).get('meta', {})
584
+ shellprint.panel(
585
+ f"{Shell_Printer.BOLD}{module_name}{Shell_Printer.RESET}\n版本: {meta.get('version', '未知')}\n描述: {meta.get('description', '无描述')}",
586
+ "模块已存在",
587
+ "info"
588
+ )
589
+ if not shellprint.confirm("是否要强制重新安装?", default=False):
590
+ return False
591
+
592
+ # 复制模块到modules目录
593
+ script_dir = os.path.dirname(os.path.abspath(__file__))
594
+ target_dir = os.path.join(script_dir, 'modules', module_name)
595
+
596
+ try:
597
+ if os.path.exists(target_dir):
598
+ shutil.rmtree(target_dir)
599
+ shutil.copytree(module_path, target_dir)
600
+ except Exception as e:
601
+ shellprint.panel(f"复制模块文件失败: {e}", "错误", "error")
602
+ return False
603
+
604
+ # 注册模块信息
605
+ mods.set_module(module_name, {
606
+ 'status': True,
607
+ 'info': {
608
+ 'meta': module.moduleInfo.get('meta', {}),
609
+ 'dependencies': module.moduleInfo.get('dependencies', {})
610
+ }
611
+ })
612
+
613
+ shellprint.panel(f"本地模块 {Shell_Printer.BOLD}{module_name}{Shell_Printer.RESET} 安装成功", "成功", "success")
614
+ return True
615
+
552
616
  def install_module(module_name, force=False):
617
+ # 检查是否是本地路径
618
+ if module_name.startswith('.') or os.path.isabs(module_name):
619
+ return install_local_module(module_name, force)
620
+
553
621
  shellprint.panel(f"准备安装模块: {Shell_Printer.BOLD}{module_name}{Shell_Printer.RESET}", "安装摘要", "info")
554
622
  last_update_time = env.get('last_origin_update_time', None)
555
623
  if last_update_time:
@@ -925,7 +993,6 @@ def list_modules(module_name=None):
925
993
 
926
994
  def main():
927
995
  parser = argparse.ArgumentParser(
928
-
929
996
  prog="epsdk",
930
997
  formatter_class=argparse.RawTextHelpFormatter
931
998
  )
@@ -1147,7 +1214,12 @@ def main():
1147
1214
  else:
1148
1215
  shellprint.panel(f"运行脚本: {Shell_Printer.BOLD}{script_path}{Shell_Printer.RESET}", "执行", "info")
1149
1216
  import runpy
1150
- runpy.run_path(script_path, run_name="__main__")
1217
+
1218
+ # 添加KeyboardInterrupt异常捕捉
1219
+ try:
1220
+ runpy.run_path(script_path, run_name="__main__")
1221
+ except KeyboardInterrupt:
1222
+ shellprint.panel("脚本执行已中断", "中断", "info")
1151
1223
 
1152
1224
  elif args.command == 'origin':
1153
1225
  if args.origin_command == 'add':