ErisPulse 2.3.0.dev5__py3-none-any.whl → 2.3.1__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.
@@ -24,7 +24,10 @@ DEFAULT_ERISPULSE_CONFIG = {
24
24
  "max_snapshot": 20
25
25
  },
26
26
  "modules": {},
27
- "adapters": {}
27
+ "adapters": {},
28
+ "framework": {
29
+ "enable_lazy_loading": True
30
+ }
28
31
  }
29
32
 
30
33
  def _ensure_erispulse_config_structure(config_dict: Dict[str, Any]) -> Dict[str, Any]:
@@ -115,4 +118,13 @@ def get_storage_config() -> Dict[str, Any]:
115
118
  :return: 存储配置字典
116
119
  """
117
120
  erispulse_config = get_erispulse_config()
118
- return erispulse_config["storage"]
121
+ return erispulse_config["storage"]
122
+
123
+ def get_framework_config() -> Dict[str, Any]:
124
+ """
125
+ 获取框架配置
126
+
127
+ :return: 框架配置字典
128
+ """
129
+ erispulse_config = get_erispulse_config()
130
+ return erispulse_config["framework"]
ErisPulse/Core/ux.py CHANGED
@@ -227,7 +227,7 @@ class UXManager:
227
227
  self.console.print(f"[green]创建项目目录: {project_name}[/green]")
228
228
 
229
229
  # 创建基本目录结构
230
- dirs = ["modules", "config", "logs"]
230
+ dirs = ["config", "logs"]
231
231
  for dir_name in dirs:
232
232
  dir_path = project_path / dir_name
233
233
  dir_path.mkdir(exist_ok=True)
@@ -288,39 +288,11 @@ class UXManager:
288
288
 
289
289
  self.console.print("[green]创建主程序文件: main.py[/green]")
290
290
 
291
- # 创建模块目录和示例模块
292
- if adapter_list:
293
- example_file = project_path / "modules" / "example.py"
294
- if not example_file.exists():
295
- with open(example_file, "w", encoding="utf-8") as f:
296
- f.write('"""')
297
- f.write("\n示例模块\n\n")
298
- f.write("这是一个示例模块,展示了如何创建基本的消息处理器\n")
299
- f.write('"""\n\n')
300
- f.write("from ErisPulse.Core.Event import command, message\n\n")
301
- f.write("class Main:\n")
302
- f.write(" def __init__(self, sdk=None):\n")
303
- f.write(" self.sdk = sdk or globals().get('sdk', __import__('ErisPulse').sdk)\n")
304
- f.write(" self.logger = self.sdk.logger.get_child(\"Example\")\n")
305
- f.write(" self.logger.info(\"示例模块已加载\")\n\n")
306
- f.write(" # 注册命令处理器\n")
307
- f.write(" @command(\"hello\", help=\"发送问候消息\")\n")
308
- f.write(" async def hello_command(event):\n")
309
- f.write(" platform = event[\"platform\"]\n")
310
- f.write(" user_id = event[\"user_id\"]\n")
311
- f.write(" \n")
312
- f.write(" if hasattr(self.sdk.adapter, platform):\n")
313
- f.write(" adapter_instance = getattr(self.sdk.adapter, platform)\n")
314
- f.write(" await adapter_instance.Send.To(\"user\", user_id).Text(\"你好!这是一个示例消息。\")\n")
315
-
316
- self.console.print("[green]创建示例模块: modules/example.py[/green]")
317
-
318
291
  self.console.print("\n[bold green]项目 {} 初始化成功![/bold green]".format(project_name))
319
292
  self.console.print("\n[cyan]接下来您可以:[/cyan]")
320
293
  self.console.print(f"1. 编辑 {project_name}/config.toml 配置适配器")
321
- self.console.print(f"2. {project_name}/modules/ 目录下创建自定义模块")
322
- self.console.print(f"3. 运行 [cyan]cd {project_name} \n ep run[/cyan] 启动项目")
323
-
294
+ self.console.print(f"2. 运行 [cyan]cd {project_name} \n ep run[/cyan] 启动项目")
295
+ self.console.print("\n访问 https://github.com/ErisPulse/ErisPulse/tree/main/docs 获取更多信息和文档")
324
296
  return True
325
297
 
326
298
  except Exception as e:
@@ -410,8 +382,7 @@ class UXManager:
410
382
  # 显示下一步操作
411
383
  self.console.print("\n[cyan]接下来您可以:[/cyan]")
412
384
  self.console.print("1. 编辑 {}/config.toml 进一步配置".format(project_name))
413
- self.console.print("2. {}/modules/ 目录下创建自定义模块".format(project_name))
414
- self.console.print("3. 运行 [cyan]cd {} \n ep run[/cyan] 启动项目".format(project_name))
385
+ self.console.print("2. 运行 [cyan]cd {} \n ep run[/cyan] 启动项目".format(project_name))
415
386
 
416
387
  return True
417
388
 
ErisPulse/__init__.py CHANGED
@@ -177,6 +177,88 @@ class LazyModule:
177
177
  logger.error(f"懒加载模块 {object.__getattribute__(self, '_module_name')} 初始化失败: {e}")
178
178
  raise e
179
179
 
180
+ def _initialize_sync(self):
181
+ """
182
+ 同步初始化模块,用于在异步上下文中进行同步调用
183
+
184
+ :raises LazyLoadError: 当模块初始化失败时抛出
185
+ """
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
222
+
223
+ async def _complete_async_init(self):
224
+ """
225
+ 完成异步初始化部分,用于同步初始化后的异步处理
226
+
227
+ 这个方法用于处理 module.load 和事件提交等异步操作
228
+ """
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}")
261
+
180
262
  def _ensure_initialized(self) -> None:
181
263
  """
182
264
  确保模块已初始化
@@ -184,15 +266,32 @@ class LazyModule:
184
266
  :raises LazyLoadError: 当模块未初始化时抛出
185
267
  """
186
268
  if not object.__getattribute__(self, '_initialized'):
187
- # 在异步环境中同步调用异步初始化方法
269
+ # 检查当前是否在异步上下文中
188
270
  try:
189
271
  loop = asyncio.get_running_loop()
190
- # 在已有事件循环中创建任务
191
- task = loop.create_task(self._initialize())
192
- # 阻塞等待完成
193
- loop.run_until_complete(task)
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}")
194
293
  except RuntimeError:
195
- # 没有运行中的事件循环
294
+ # 没有运行中的事件循环,可以安全地创建新的事件循环
196
295
  asyncio.run(self._initialize())
197
296
 
198
297
  def __getattr__(self, name: str) -> Any:
@@ -204,6 +303,13 @@ class LazyModule:
204
303
  """
205
304
  logger.debug(f"正在访问懒加载模块 {object.__getattribute__(self, '_module_name')} 的属性 {name}...")
206
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
+
207
313
  self._ensure_initialized()
208
314
  return getattr(object.__getattribute__(self, '_instance'), name)
209
315
 
@@ -572,6 +678,19 @@ class ModuleLoader:
572
678
 
573
679
  logger.debug(f"检查模块 {module_class.__name__} 是否应该懒加载")
574
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
+
575
694
  # 检查模块是否定义了 should_eager_load() 方法
576
695
  if hasattr(module_class, "should_eager_load"):
577
696
  try:
@@ -966,9 +1085,19 @@ async def init() -> bool:
966
1085
  """
967
1086
  if not await _prepare_environment():
968
1087
  return False
969
-
1088
+
970
1089
  return await ModuleInitializer.init()
971
1090
 
1091
+ def init_sync() -> bool:
1092
+ """
1093
+ SDK初始化入口(同步版本)
1094
+
1095
+ 用于命令行直接调用,自动在事件循环中运行异步初始化
1096
+
1097
+ :return: bool SDK初始化是否成功
1098
+ """
1099
+ return asyncio.run(init())
1100
+
972
1101
  def init_task() -> asyncio.Task:
973
1102
  """
974
1103
  SDK初始化入口,返回Task对象
@@ -986,6 +1115,7 @@ def init_task() -> asyncio.Task:
986
1115
  loop = asyncio.new_event_loop()
987
1116
  asyncio.set_event_loop(loop)
988
1117
  return loop.create_task(_async_init())
1118
+
989
1119
  async def uninit() -> bool:
990
1120
  """
991
1121
  SDK反初始化
@@ -1085,14 +1215,28 @@ async def load_module(module_name: str) -> bool:
1085
1215
  {!--< tips >!--}
1086
1216
  1. 可用于手动触发懒加载模块的初始化
1087
1217
  2. 如果模块不存在或已加载会返回False
1218
+ 3. 对于需要异步初始化的模块,这是唯一的加载方式
1088
1219
  {!--< /tips >!--}
1089
1220
  """
1090
1221
  try:
1091
1222
  module_instance = getattr(sdk, module_name, None)
1092
1223
  if isinstance(module_instance, LazyModule):
1093
- # 触发懒加载模块的初始化
1094
- await module_instance._initialize()
1095
- return True
1224
+ # 检查模块是否需要异步初始化
1225
+ if hasattr(module_instance, '_needs_async_init') and object.__getattribute__(module_instance, '_needs_async_init'):
1226
+ # 对于需要异步初始化的模块,执行完整异步初始化
1227
+ await module_instance._initialize()
1228
+ object.__setattr__(module_instance, '_needs_async_init', False) # 清除标志
1229
+ return True
1230
+ # 检查模块是否已经同步初始化但未完成异步部分
1231
+ elif (object.__getattribute__(module_instance, '_initialized') and
1232
+ object.__getattribute__(module_instance, '_is_base_module')):
1233
+ # 如果是BaseModule子类且已同步初始化,只需完成异步部分
1234
+ await module_instance._complete_async_init()
1235
+ return True
1236
+ else:
1237
+ # 触发懒加载模块的完整初始化
1238
+ await module_instance._initialize()
1239
+ return True
1096
1240
  elif module_instance is not None:
1097
1241
  logger.warning(f"模块 {module_name} 已经加载")
1098
1242
  return False
@@ -7,9 +7,11 @@ ErisPulse SDK 工具模块
7
7
  from .package_manager import PackageManager
8
8
  from .reload_handler import ReloadHandler
9
9
  from .cli import CLI
10
+ from .console import console
10
11
 
11
12
  __all__ = [
12
13
  "PackageManager",
13
14
  "ReloadHandler",
14
15
  "CLI",
16
+ "console",
15
17
  ]
ErisPulse/utils/cli.py CHANGED
@@ -8,58 +8,12 @@ from typing import List, Dict, Optional, Any
8
8
  from watchdog.observers import Observer
9
9
 
10
10
  # Rich console setup
11
- from rich.console import Console
12
11
  from rich.panel import Panel
13
12
  from rich.table import Table
14
13
  from rich.prompt import Confirm, Prompt
15
14
  from rich.box import SIMPLE
16
- from rich.theme import Theme
17
- from rich.highlighter import RegexHighlighter
18
15
 
19
- # 确保在Windows上启用颜色
20
- if sys.platform == "win32":
21
- from colorama import init
22
- init()
23
-
24
- class CommandHighlighter(RegexHighlighter):
25
- """
26
- 高亮CLI命令和参数
27
-
28
- {!--< tips >!--}
29
- 使用正则表达式匹配命令行参数和选项
30
- {!--< /tips >!--}
31
- """
32
- highlights = [
33
- r"(?P<switch>\-\-?\w+)",
34
- r"(?P<option>\[\w+\])",
35
- r"(?P<command>\b\w+\b)",
36
- ]
37
-
38
- # 主题配置
39
- theme = Theme({
40
- "info": "dim cyan",
41
- "success": "bold green",
42
- "warning": "bold yellow",
43
- "error": "bold red",
44
- "title": "bold magenta",
45
- "default": "default",
46
- "progress": "green",
47
- "progress.remaining": "white",
48
- "cmd": "bold blue",
49
- "param": "italic cyan",
50
- "switch": "bold yellow",
51
- "module": "bold green",
52
- "adapter": "bold yellow",
53
- "cli": "bold magenta",
54
- })
55
-
56
- # 全局控制台实例
57
- console = Console(
58
- theme=theme,
59
- color_system="auto",
60
- force_terminal=True,
61
- highlighter=CommandHighlighter()
62
- )
16
+ from .console import console
63
17
 
64
18
  class CLI:
65
19
  """
@@ -988,7 +942,8 @@ class CLI:
988
942
  time.sleep(0.5)
989
943
  except KeyboardInterrupt:
990
944
  console.print("\n[info]正在安全关闭...[/]")
991
- self._cleanup_adapters()
945
+ _cleanup_adapters()
946
+ _cleanup_modules()
992
947
  self._cleanup()
993
948
  console.print("[success]已安全退出[/]")
994
949
 
@@ -1062,41 +1017,76 @@ class CLI:
1062
1017
  console.print(traceback.format_exc())
1063
1018
  self._cleanup()
1064
1019
  sys.exit(1)
1020
+
1021
+ def _cleanup_adapters():
1022
+ """
1023
+ 清理适配器资源
1024
+ """
1065
1025
 
1066
- def _cleanup_adapters(self):
1067
- """
1068
- 清理适配器资源
1069
- """
1070
- from ErisPulse import adapter, logger
1071
- try:
1072
- import asyncio
1073
- import threading
1026
+ from ErisPulse import adapter
1027
+ try:
1028
+ import asyncio
1029
+ import threading
1030
+
1031
+ # 检查是否有正在运行的适配器
1032
+ if adapter.list_adapters():
1074
1033
 
1075
- # 检查是否有正在运行的适配器
1076
- if (hasattr(adapter, '_started_instances') and
1077
- adapter._started_instances):
1078
-
1079
- logger.info("正在停止所有适配器...")
1080
-
1081
- if threading.current_thread() is threading.main_thread():
1082
- try:
1083
- loop = asyncio.get_running_loop()
1084
- if loop.is_running():
1085
- # 在新线程中运行
1086
- stop_thread = threading.Thread(
1087
- target=lambda: asyncio.run(adapter.shutdown())
1088
- )
1089
- stop_thread.start()
1090
- stop_thread.join(timeout=5)
1091
- else:
1092
- asyncio.run(adapter.shutdown())
1093
- except RuntimeError:
1034
+ console.print("[info]正在停止所有适配器...[/]")
1035
+
1036
+ if threading.current_thread() is threading.main_thread():
1037
+ try:
1038
+ loop = asyncio.get_running_loop()
1039
+ if loop.is_running():
1040
+ # 在新线程中运行
1041
+ stop_thread = threading.Thread(
1042
+ target=lambda: asyncio.run(adapter.shutdown())
1043
+ )
1044
+ stop_thread.start()
1045
+ stop_thread.join(timeout=5)
1046
+ else:
1094
1047
  asyncio.run(adapter.shutdown())
1048
+ except RuntimeError:
1049
+ asyncio.run(adapter.shutdown())
1050
+ else:
1051
+ new_loop = asyncio.new_event_loop()
1052
+ asyncio.set_event_loop(new_loop)
1053
+ new_loop.run_until_complete(adapter.shutdown())
1054
+
1055
+ console.print("[success]适配器已全部停止[/]")
1056
+ else:
1057
+ console.print("[dim]没有需要停止的适配器[/]")
1058
+ except Exception as e:
1059
+ console.print(f"[error]清理适配器资源时出错: {e}[/]")
1060
+
1061
+ def _cleanup_modules():
1062
+ """
1063
+ 清理模块资源
1064
+ """
1065
+ from ErisPulse import module
1066
+ try:
1067
+ import asyncio
1068
+ import threading
1069
+
1070
+ console.print("[info]正在卸载所有模块...[/]")
1071
+
1072
+ if threading.current_thread() is threading.main_thread():
1073
+ try:
1074
+ loop = asyncio.get_running_loop()
1075
+ if loop.is_running():
1076
+ stop_thread = threading.Thread(
1077
+ target=lambda: asyncio.run(module.unload())
1078
+ )
1079
+ stop_thread.start()
1080
+ stop_thread.join(timeout=5)
1095
1081
  else:
1096
- new_loop = asyncio.new_event_loop()
1097
- asyncio.set_event_loop(new_loop)
1098
- new_loop.run_until_complete(adapter.shutdown())
1099
-
1100
- logger.info("适配器已全部停止")
1101
- except Exception as e:
1102
- logger.error(f"清理适配器资源时出错: {e}")
1082
+ asyncio.run(module.unload())
1083
+ except RuntimeError:
1084
+ asyncio.run(module.unload())
1085
+ else:
1086
+ new_loop = asyncio.new_event_loop()
1087
+ asyncio.set_event_loop(new_loop)
1088
+ new_loop.run_until_complete(module.unload())
1089
+
1090
+ console.print("[success]模块已全部卸载[/]")
1091
+ except Exception as e:
1092
+ console.print(f"[error]清理模块资源时出错: {e}[/]")
@@ -0,0 +1,53 @@
1
+ import sys
2
+ from rich.console import Console
3
+ from rich.theme import Theme
4
+ from rich.highlighter import RegexHighlighter
5
+
6
+ # 确保在Windows上启用颜色
7
+ if sys.platform == "win32":
8
+ from colorama import init
9
+ init()
10
+
11
+ class CommandHighlighter(RegexHighlighter):
12
+ """
13
+ 高亮CLI命令和参数
14
+
15
+ {!--< tips >!--}
16
+ 使用正则表达式匹配命令行参数和选项
17
+ {!--< /tips >!--}
18
+ """
19
+ highlights = [
20
+ r"(?P<switch>\-\-?\w+)",
21
+ r"(?P<option>\[\w+\])",
22
+ r"(?P<command>\b\w+\b)",
23
+ ]
24
+
25
+ # 主题配置
26
+ theme = Theme({
27
+ "info": "dim cyan",
28
+ "success": "bold green",
29
+ "warning": "bold yellow",
30
+ "error": "bold red",
31
+ "title": "bold magenta",
32
+ "default": "default",
33
+ "progress": "green",
34
+ "progress.remaining": "white",
35
+ "cmd": "bold blue",
36
+ "param": "italic cyan",
37
+ "switch": "bold yellow",
38
+ "module": "bold green",
39
+ "adapter": "bold yellow",
40
+ "cli": "bold magenta",
41
+ })
42
+
43
+ # 全局控制台实例
44
+ console = Console(
45
+ theme=theme,
46
+ color_system="auto",
47
+ force_terminal=True,
48
+ highlighter=CommandHighlighter()
49
+ )
50
+
51
+ __all__ = [
52
+ "console",
53
+ ]
@@ -13,13 +13,11 @@ import sys
13
13
  import time
14
14
  from typing import List, Dict, Tuple, Optional, Any
15
15
 
16
- from rich.console import Console
17
16
  from rich.panel import Panel
18
17
  from rich.progress import Progress, BarColumn, TextColumn
19
18
  from rich.prompt import Confirm
20
19
 
21
- # 全局控制台实例,从CLI模块导入
22
- console = Console()
20
+ from .console import console
23
21
 
24
22
  class PackageManager:
25
23
  """
@@ -4,18 +4,13 @@ ErisPulse SDK 热重载处理器
4
4
  实现热重载功能,监控文件变化并重启进程
5
5
  """
6
6
 
7
- import asyncio
8
7
  import os
9
8
  import subprocess
10
9
  import sys
11
- import threading
12
10
  import time
13
11
  from watchdog.events import FileSystemEventHandler
14
12
 
15
- from rich.console import Console
16
-
17
- # 全局控制台实例,从CLI模块导入
18
- console = Console()
13
+ from .console import console
19
14
 
20
15
 
21
16
  class ReloadHandler(FileSystemEventHandler):
@@ -101,35 +96,16 @@ class ReloadHandler(FileSystemEventHandler):
101
96
  :param event: 文件系统事件
102
97
  :param reason: 重载原因
103
98
  """
104
- from ErisPulse.Core import adapter, logger
105
- # 在重载前确保所有适配器正确停止
99
+ from ErisPulse.Core import logger
100
+
106
101
  try:
107
- # 检查适配器是否正在运行
108
- if hasattr(adapter, '_started_instances') and adapter._started_instances:
109
- logger.info("正在停止适配器...")
110
- # 创建新的事件循环来运行异步停止操作
111
-
112
- # 如果在主线程中
113
- if threading.current_thread() is threading.main_thread():
114
- try:
115
- # 在新线程中运行适配器停止
116
- stop_thread = threading.Thread(target=lambda: asyncio.run(adapter.shutdown()))
117
- stop_thread.start()
118
- stop_thread.join(timeout=10) # 最多等待10秒
119
- except RuntimeError:
120
- # 没有运行中的事件循环
121
- asyncio.run(adapter.shutdown())
122
- else:
123
- # 在非主线程中,创建新的事件循环
124
- new_loop = asyncio.new_event_loop()
125
- asyncio.set_event_loop(new_loop)
126
- new_loop.run_until_complete(adapter.shutdown())
127
-
128
- logger.info("适配器已停止")
102
+ from .cli import _cleanup_adapters, _cleanup_modules
103
+ logger.info(f"检测到文件变更 ({reason}),正在关闭适配器和模块...")
104
+ _cleanup_adapters()
105
+ _cleanup_modules()
129
106
  except Exception as e:
130
- logger.warning(f"停止适配器时出错: {e}")
107
+ logger.warning(f"关闭适配器和模块时出错: {e}")
131
108
 
132
- # 原有的重载逻辑
133
- logger.info(f"检测到文件变更 ({reason}),正在重启...")
109
+ logger.info("正在重启...")
134
110
  self._terminate_process()
135
- self.start_process()
111
+ self.start_process()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ErisPulse
3
- Version: 2.3.0.dev5
3
+ Version: 2.3.1
4
4
  Summary: ErisPulse 是一个模块化、可扩展的异步 Python SDK 框架,主要用于构建高效、可维护的机器人应用程序。
5
5
  Author-email: "艾莉丝·格雷拉特(WSu2059)" <wsu2059@qq.com>
6
6
  License: MIT License
@@ -1,7 +1,7 @@
1
- ErisPulse/__init__.py,sha256=6foVg_ZnQhO9Cg8vwmyHhJSxmnSwLCrzITFE5CP8qLc,42583
1
+ ErisPulse/__init__.py,sha256=u5b96KfFq57kB4I51t_YAU_aLVTftG4rLkAqFmmYwVA,50327
2
2
  ErisPulse/__main__.py,sha256=x1VV2mbn1B9RVRhG5uumTCrvZCLzJjGWN0wFll-G0H4,471
3
3
  ErisPulse/Core/__init__.py,sha256=9RNwUq9Hbe3r6nA8QBvq2pvMJN4QiBfo71N0u_ywiwI,1398
4
- ErisPulse/Core/_self_config.py,sha256=7PdOfJj1_s4fViayUSzqiUWDTb7Tie_1KjdRcIveK8w,3281
4
+ ErisPulse/Core/_self_config.py,sha256=ReoVy2hYZxG7hPRHXUWRjLClC4nWZ2RG8VWdD-PAM7g,3549
5
5
  ErisPulse/Core/adapter.py,sha256=9wpaE9B6LixlGTJ0p341wYe4AE3SVuczToMOWd7UkL4,19707
6
6
  ErisPulse/Core/config.py,sha256=cV0R2eUWNECIogYLFbhNu1pYl8HStPG-DNbCe3lkY4E,5873
7
7
  ErisPulse/Core/exceptions.py,sha256=tTOOs57SD8aSp4HXomuXtVYgHJCJtfP3AS4JIIq1LPk,3920
@@ -10,7 +10,7 @@ ErisPulse/Core/logger.py,sha256=nktXT-6cxF50NYsUErMsf8J79brzXg2faaJ4Agt2Gro,1259
10
10
  ErisPulse/Core/module.py,sha256=13rI03GwEzVd66hIhZnZNybiA9wj7ITzQILi1-nCjhQ,12944
11
11
  ErisPulse/Core/router.py,sha256=rtvUjbRHVeTTgWBBG-yxK91oEjs5Tw3ReryqCI-rMYc,12411
12
12
  ErisPulse/Core/storage.py,sha256=WbREN-GTpzPls8Vx3t8F2U_lzmCKEsI4OcecWWmvaSk,25238
13
- ErisPulse/Core/ux.py,sha256=DQHzSXJGGI2CHoVQg1Od5qYDDdxXObEJOaqAoGZEegQ,31631
13
+ ErisPulse/Core/ux.py,sha256=jWC_v8e0Khe1LAg5ksKCVyEgmO2MJGIfmtOAPTorD90,29589
14
14
  ErisPulse/Core/Bases/__init__.py,sha256=hHKsI2zQfBdahnEuHlMgzOX2_ygRDOVN8-VqTIrcxP4,230
15
15
  ErisPulse/Core/Bases/adapter.py,sha256=aCupQdc8M5Ds7m5dZMCmtoyC-0Zqh5K_6F3uKle8WXE,6490
16
16
  ErisPulse/Core/Bases/module.py,sha256=TtzZQ4x4u09S6yDibsIHa9srlGLFPXCHdn2WxZ3nmdo,1154
@@ -22,12 +22,13 @@ ErisPulse/Core/Event/message.py,sha256=wxg_GJsI1ZvPrV9611xELLxnlk2bcxMJH7EBEkoWw
22
22
  ErisPulse/Core/Event/meta.py,sha256=0cs0Cg5r58kll3P4lNtnVWAKLQiL6MoXPkbkk6_IEko,3660
23
23
  ErisPulse/Core/Event/notice.py,sha256=tU28tc3Ig-FMB2EJUDO2Z9ewfJjzEPh2O2J4lU7GYDk,4557
24
24
  ErisPulse/Core/Event/request.py,sha256=rYjFjRJccNRZ6bkY89ig8Q2YntnoytUfg-_PGntJxXg,2956
25
- ErisPulse/utils/__init__.py,sha256=GTLeWbAkQSWPJ3NjFDV2DYZaTZ6bx56VumrtqkI8upA,255
26
- ErisPulse/utils/cli.py,sha256=fwxyGAcIh57rQkZ-YF6TQKou0v2Wrtjg1XUFp-IOcHI,40924
27
- ErisPulse/utils/package_manager.py,sha256=8auzSigymzff6JBMKVy-6XntPPFGeO7qTUSKoY-vYFE,32767
28
- ErisPulse/utils/reload_handler.py,sha256=ulVJEK7NsdsTXUkqp40iLf9D5rC8WjFut48UIRj9JyQ,4552
29
- erispulse-2.3.0.dev5.dist-info/METADATA,sha256=mAAjbybK9-vZPmSMt80JKRBS7YNfDhVhS_J29KEU1pw,7478
30
- erispulse-2.3.0.dev5.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
31
- erispulse-2.3.0.dev5.dist-info/entry_points.txt,sha256=Jss71M6nEha0TA-DyVZugPYdcL14s9QpiOeIlgWxzOc,182
32
- erispulse-2.3.0.dev5.dist-info/licenses/LICENSE,sha256=tJjKWuY4OPWNgriiixWLvmFb8Pf8p_-4NMq_zZN3gWg,1858
33
- erispulse-2.3.0.dev5.dist-info/RECORD,,
25
+ ErisPulse/utils/__init__.py,sha256=_4cDUbJyNebH-VXDUTnfdZKv8Y1MPYgsl-fOM0ZFNuw,299
26
+ ErisPulse/utils/cli.py,sha256=-K24UOi3EO65R2tCnVjikVFETzxUtuSApmPZH7iH5gs,40894
27
+ ErisPulse/utils/console.py,sha256=IIo8kVTy0ikEp1H4V6BsokaQp_ISfBFuxlhQcRnk2vs,1145
28
+ ErisPulse/utils/package_manager.py,sha256=uv9Q24Qxa2bbotxLrSvhF-lX6vEmK-4KPCIwPe6ZyGc,32698
29
+ ErisPulse/utils/reload_handler.py,sha256=ToBE9EiXY8ZNNL8jntdsc2Dpy-Wgh73Jd3aBpedKAtg,3369
30
+ erispulse-2.3.1.dist-info/METADATA,sha256=WvmkTAbyCTSgkpMGQc31U_Lb-wZCfhL3IwJXcQTcJM0,7473
31
+ erispulse-2.3.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
32
+ erispulse-2.3.1.dist-info/entry_points.txt,sha256=NiOwT6-XQ7KIH1r6J8odjRO-uaKHfr_Vz_UIG96EWXg,187
33
+ erispulse-2.3.1.dist-info/licenses/LICENSE,sha256=tJjKWuY4OPWNgriiixWLvmFb8Pf8p_-4NMq_zZN3gWg,1858
34
+ erispulse-2.3.1.dist-info/RECORD,,
@@ -1,6 +1,6 @@
1
1
  [console_scripts]
2
2
  ep = ErisPulse.__main__:main
3
3
  ep-cli = ErisPulse.__main__:main
4
- ep-init = ErisPulse.__init__:init
4
+ ep-init = ErisPulse.__init__:init_sync
5
5
  epsdk = ErisPulse.__main__:main
6
6
  epsdk-cli = ErisPulse.__main__:main