ErisPulse 2.1.0__py3-none-any.whl → 2.1.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.
ErisPulse/Core/adapter.py CHANGED
@@ -96,7 +96,6 @@ class BaseAdapter:
96
96
 
97
97
  :param text: 文本内容
98
98
  :return: 异步任务
99
-
100
99
  :example:
101
100
  >>> await adapter.Send.To("123").Text("Hello")
102
101
  """
@@ -113,33 +112,23 @@ class BaseAdapter:
113
112
  """
114
113
  初始化适配器
115
114
  """
116
- self._handlers = defaultdict(list) # 原生事件处理器
117
- self._onebot_handlers = defaultdict(list) # OneBot12事件处理器
115
+ self._handlers = defaultdict(list)
118
116
  self._middlewares = []
119
117
  self.Send = self.__class__.Send(self)
120
118
 
121
- def on(self, event_type: str = "*", *, onebot12: bool = False) -> Callable[[Callable], Callable]:
119
+ def on(self, event_type: str = "*") -> Callable[[Callable], Callable]:
122
120
  """
123
121
  适配器事件监听装饰器
124
122
 
125
123
  :param event_type: 事件类型
126
- :param onebot12: 是否监听OneBot12协议事件
127
124
  :return: 装饰器函数
128
-
129
- :example:
130
- >>> @adapter.on("message")
131
- >>> async def handle_message(data):
132
- >>> print(f"收到消息: {data}")
133
125
  """
134
126
  def decorator(func: Callable) -> Callable:
135
127
  @functools.wraps(func)
136
128
  async def wrapper(*args, **kwargs):
137
129
  return await func(*args, **kwargs)
138
-
139
- if onebot12:
140
- self._onebot_handlers[event_type].append(wrapper)
141
- else:
142
- self._handlers[event_type].append(wrapper)
130
+ self._handlers[event_type].append(wrapper)
131
+
143
132
  return wrapper
144
133
  return decorator
145
134
 
@@ -166,7 +155,6 @@ class BaseAdapter:
166
155
  :param endpoint: API端点
167
156
  :param params: API参数
168
157
  :return: API调用结果
169
-
170
158
  :raises NotImplementedError: 必须由子类实现
171
159
  """
172
160
  raise NotImplementedError("适配器必须实现call_api方法")
@@ -186,36 +174,6 @@ class BaseAdapter:
186
174
  :raises NotImplementedError: 必须由子类实现
187
175
  """
188
176
  raise NotImplementedError("适配器必须实现shutdown方法")
189
-
190
- def add_handler(self, *args: Any) -> None:
191
- """
192
- 添加事件处理器
193
-
194
- :param args: 参数列表
195
- - 1个参数: 处理器函数(监听所有事件)
196
- - 2个参数: 事件类型和处理器函数
197
-
198
- :raises TypeError: 当参数数量无效时抛出
199
-
200
- :example:
201
- >>> # 监听所有事件
202
- >>> adapter.add_handler(handle_all_events)
203
- >>> # 监听特定事件
204
- >>> adapter.add_handler("message", handle_message)
205
- """
206
- if len(args) == 1:
207
- event_type = "*"
208
- handler = args[0]
209
- elif len(args) == 2:
210
- event_type, handler = args
211
- else:
212
- raise TypeError("add_handler() 接受 1 个(监听所有事件)或 2 个参数(指定事件类型)")
213
-
214
- @functools.wraps(handler)
215
- async def wrapper(*handler_args, **handler_kwargs):
216
- return await handler(*handler_args, **handler_kwargs)
217
-
218
- self._handlers[event_type].append(wrapper)
219
177
 
220
178
  async def emit(self, event_type: str, data: Any) -> None:
221
179
  """
@@ -240,35 +198,6 @@ class BaseAdapter:
240
198
  for handler in self._handlers.get("*", []):
241
199
  await handler(data)
242
200
 
243
- async def emit_onebot12(self, event_type: str, onebot_data: Dict) -> None:
244
- """
245
- 提交OneBot12协议事件
246
-
247
- :param event_type: OneBot12事件类型
248
- :param onebot_data: 符合OneBot12标准的事件数据
249
-
250
- :example:
251
- >>> await adapter.emit_onebot12("message", {
252
- >>> "id": "123",
253
- >>> "time": 1620000000,
254
- >>> "type": "message",
255
- >>> "detail_type": "private",
256
- >>> "message": [{"type": "text", "data": {"text": "Hello"}}]
257
- >>> })
258
- """
259
- # 先执行中间件
260
- for middleware in self._middlewares:
261
- onebot_data = await middleware(onebot_data)
262
-
263
- # 触发OneBot12事件处理器
264
- if event_type in self._onebot_handlers:
265
- for handler in self._onebot_handlers[event_type]:
266
- await handler(onebot_data)
267
-
268
- # 触发通配符 "*" 的处理器
269
- for handler in self._onebot_handlers.get("*", []):
270
- await handler(onebot_data)
271
-
272
201
  async def send(self, target_type: str, target_id: str, message: Any, **kwargs: Any) -> Any:
273
202
  """
274
203
  发送消息的便捷方法
ErisPulse/Core/logger.py CHANGED
@@ -1,9 +1,32 @@
1
+ """
2
+ ErisPulse 日志系统
3
+
4
+ 提供模块化日志记录功能,支持多级日志、模块过滤和内存存储。
5
+
6
+ {!--< tips >!--}
7
+ 1. 支持按模块设置不同日志级别
8
+ 2. 日志可存储在内存中供后续分析
9
+ 3. 自动识别调用模块名称
10
+ {!--< /tips >!--}
11
+ """
12
+
1
13
  import logging
2
14
  import inspect
3
15
  import datetime
4
16
  from typing import List, Dict, Any, Optional, Union, Type, Set, Tuple, FrozenSet
5
17
 
6
18
  class Logger:
19
+ """
20
+ 日志管理器
21
+
22
+ 提供模块化日志记录和存储功能
23
+
24
+ {!--< tips >!--}
25
+ 1. 使用set_module_level设置模块日志级别
26
+ 2. 使用get_logs获取历史日志
27
+ 3. 支持标准日志级别(DEBUG, INFO等)
28
+ {!--< /tips >!--}
29
+ """
7
30
  def __init__(self):
8
31
  self._logs = {}
9
32
  self._module_levels = {}
@@ -16,6 +39,12 @@ class Logger:
16
39
  self._logger.addHandler(console_handler)
17
40
 
18
41
  def set_level(self, level: str) -> bool:
42
+ """
43
+ 设置全局日志级别
44
+
45
+ :param level: 日志级别(DEBUG/INFO/WARNING/ERROR/CRITICAL)
46
+ :return: bool 设置是否成功
47
+ """
19
48
  try:
20
49
  level = level.upper()
21
50
  if hasattr(logging, level):
@@ -27,6 +56,13 @@ class Logger:
27
56
  return False
28
57
 
29
58
  def set_module_level(self, module_name: str, level: str) -> bool:
59
+ """
60
+ 设置指定模块日志级别
61
+
62
+ :param module_name: 模块名称
63
+ :param level: 日志级别(DEBUG/INFO/WARNING/ERROR/CRITICAL)
64
+ :return: bool 设置是否成功
65
+ """
30
66
  from .env import env
31
67
  if not env.get_module_status(module_name):
32
68
  self._logger.warning(f"模块 {module_name} 未启用,无法设置日志等级。")
@@ -41,6 +77,12 @@ class Logger:
41
77
  return False
42
78
 
43
79
  def set_output_file(self, path) -> bool:
80
+ """
81
+ 设置日志输出
82
+
83
+ :param path: 日志文件路径 Str/List
84
+ :return: bool 设置是否成功
85
+ """
44
86
  if self._file_handler:
45
87
  self._logger.removeHandler(self._file_handler)
46
88
  self._file_handler.close()
@@ -58,7 +100,14 @@ class Logger:
58
100
  except Exception as e:
59
101
  self._logger.error(f"无法设置日志文件 {p}: {e}")
60
102
  return False
103
+
61
104
  def save_logs(self, path) -> bool:
105
+ """
106
+ 保存所有在内存中记录的日志
107
+
108
+ :param path: 日志文件路径 Str/List
109
+ :return: bool 设置是否成功
110
+ """
62
111
  if self._logs == None:
63
112
  self._logger.warning("没有log记录可供保存。")
64
113
  return False
@@ -79,6 +128,12 @@ class Logger:
79
128
  return False
80
129
 
81
130
  def get_logs(self, module_name: str = None) -> dict:
131
+ """
132
+ 获取日志内容
133
+
134
+ :param module_name (可选): 模块名称
135
+ :return: dict 日志内容
136
+ """
82
137
  if module_name:
83
138
  return {module_name: self._logs.get(module_name, [])}
84
139
  return {k: v.copy() for k, v in self._logs.items()}
ErisPulse/__init__.py CHANGED
@@ -13,11 +13,9 @@ ErisPulse SDK 主模块
13
13
  import os
14
14
  import sys
15
15
  import importlib
16
- import asyncio
17
- import toml
18
16
  import inspect
19
17
  import importlib.metadata
20
- from typing import Dict, List, Tuple, Optional, Set, Type, Any, Callable
18
+ from typing import Dict, List, Tuple, Type, Any
21
19
  from pathlib import Path
22
20
 
23
21
  # BaseModules: SDK核心模块
@@ -73,14 +71,14 @@ class LazyModule:
73
71
  {!--< /tips >!--}
74
72
  """
75
73
 
76
- def __init__(self, module_name: str, module_class: Type, sdk_ref: Any, module_info: Dict[str, Any]):
74
+ def __init__(self, module_name: str, module_class: Type, sdk_ref: Any, module_info: Dict[str, Any]) -> None:
77
75
  """
78
76
  初始化懒加载包装器
79
77
 
80
- :param module_name: 模块名称
81
- :param module_class: 模块类
82
- :param sdk_ref: SDK引用
83
- :param module_info: 模块信息字典
78
+ :param module_name: str 模块名称
79
+ :param module_class: Type 模块类
80
+ :param sdk_ref: Any SDK引用
81
+ :param module_info: Dict[str, Any] 模块信息字典
84
82
  """
85
83
  self._module_name = module_name
86
84
  self._module_class = module_class
@@ -90,7 +88,11 @@ class LazyModule:
90
88
  self._initialized = False
91
89
 
92
90
  def _initialize(self):
93
- """实际初始化模块"""
91
+ """
92
+ 实际初始化模块
93
+
94
+ :raises LazyLoadError: 当模块初始化失败时抛出
95
+ """
94
96
  try:
95
97
  # 获取类的__init__参数信息
96
98
  init_signature = inspect.signature(self._module_class.__init__)
@@ -110,16 +112,77 @@ class LazyModule:
110
112
  raise raiserr.LazyLoadError(f"无法初始化模块 {self._module_name}: {e}")
111
113
 
112
114
  def __getattr__(self, name: str) -> Any:
113
- """属性访问时触发初始化"""
115
+ """
116
+ 属性访问时触发初始化
117
+
118
+ :param name: str 要访问的属性名
119
+ :return: Any 模块属性值
120
+ """
114
121
  if not self._initialized:
115
122
  self._initialize()
116
123
  return getattr(self._instance, name)
117
124
 
118
125
  def __call__(self, *args, **kwargs) -> Any:
119
- """调用时触发初始化"""
126
+ """
127
+ 调用时触发初始化
128
+
129
+ :param args: 位置参数
130
+ :param kwargs: 关键字参数
131
+ :return: Any 模块调用结果
132
+ """
120
133
  if not self._initialized:
121
134
  self._initialize()
122
135
  return self._instance(*args, **kwargs)
136
+
137
+ def __bool__(self) -> bool:
138
+ """
139
+ 判断模块布尔值时触发初始化
140
+
141
+ :return: bool 模块布尔值
142
+ """
143
+ if not self._initialized:
144
+ self._initialize()
145
+ return bool(self._instance)
146
+
147
+ def __str__(self) -> str:
148
+ """
149
+ 转换为字符串时触发初始化
150
+
151
+ :return: str 模块字符串表示
152
+ """
153
+ if not self._initialized:
154
+ self._initialize()
155
+ return str(self._instance)
156
+ return str(self._instance)
157
+
158
+ # 确保模块在被赋值给变量后仍然能正确工作
159
+ def __getattribute__(self, name: str) -> Any:
160
+ try:
161
+ # 首先尝试获取常规属性
162
+ return super().__getattribute__(name)
163
+ except AttributeError:
164
+ # 如果常规属性不存在,触发初始化
165
+ if name != '_initialized' and not self._initialized:
166
+ self._initialize()
167
+ return getattr(self._instance, name)
168
+ raise
169
+
170
+ def __copy__(self):
171
+ """
172
+ 浅拷贝时返回自身,保持懒加载特性
173
+
174
+ :return: self
175
+ """
176
+ return self
177
+
178
+ def __deepcopy__(self, memo):
179
+ """
180
+ 深拷贝时返回自身,保持懒加载特性
181
+
182
+ :param memo: memo
183
+ :return: self
184
+ """
185
+ return self
123
186
 
124
187
 
125
188
  class AdapterLoader:
@@ -375,8 +438,8 @@ class ModuleLoader:
375
438
  """
376
439
  检查模块是否应该懒加载
377
440
 
378
- :param module_class: 模块类
379
- :return: bool: 如果返回 False,则立即加载;否则懒加载
441
+ :param module_class: Type 模块类
442
+ :return: bool 如果返回 False,则立即加载;否则懒加载
380
443
  """
381
444
  # 检查模块是否定义了 should_eager_load() 方法
382
445
  if hasattr(module_class, "should_eager_load"):
@@ -413,7 +476,8 @@ class ModuleInitializer:
413
476
  4. 注册适配器
414
477
  5. 初始化各模块
415
478
 
416
- :return: bool: 初始化是否成功
479
+ :return: bool 初始化是否成功
480
+ :raises InitError: 当初始化失败时抛出
417
481
  """
418
482
  logger.info("[Init] SDK 正在初始化...")
419
483
 
@@ -433,16 +497,12 @@ class ModuleInitializer:
433
497
  logger.warning("[Init] 没有找到可用的模块和适配器")
434
498
  return True
435
499
 
436
- # 3. 预记录所有模块信息到SDK属性中
437
- logger.debug("[Init] 正在预记录模块信息...")
438
- ModuleInitializer._pre_register_modules(enabled_modules, module_objs)
439
-
440
- # 4. 注册适配器
500
+ # 3. 注册适配器
441
501
  logger.debug("[Init] 正在注册适配器...")
442
502
  if not ModuleInitializer._register_adapters(enabled_adapters, adapter_objs):
443
503
  return False
444
504
 
445
- # 5. 初始化模块
505
+ # 4. 初始化模块
446
506
  logger.debug("[Init] 正在初始化模块...")
447
507
  success = ModuleInitializer._initialize_modules(enabled_modules, module_objs)
448
508
  logger.info(f"[Init] SDK初始化{'成功' if success else '失败'}")
@@ -454,20 +514,58 @@ class ModuleInitializer:
454
514
  return False
455
515
 
456
516
  @staticmethod
457
- def _pre_register_modules(modules: List[str], module_objs: Dict[str, Any]) -> None:
517
+ def _initialize_modules(modules: List[str], module_objs: Dict[str, Any]) -> None:
458
518
  """
459
- 预记录所有模块信息到SDK属性中
519
+ {!--< internal-use >!--}
520
+ 初始化模块
521
+
522
+ :param modules: List[str] 模块名称列表
523
+ :param module_objs: Dict[str, Any] 模块对象字典
460
524
 
461
- 确保所有模块在初始化前都已在SDK中注册
525
+ :return: bool 模块初始化是否成功
462
526
  """
463
527
  for module_name in modules:
464
528
  module_obj = module_objs[module_name]
465
529
  meta_name = module_obj.moduleInfo["meta"]["name"]
466
530
 
467
- # 即使模块是懒加载的,也先在SDK中创建占位符
468
- if not hasattr(sdk, meta_name):
531
+ if hasattr(sdk, meta_name):
532
+ continue
533
+
534
+ try:
535
+ entry_points = importlib.metadata.entry_points()
536
+ if hasattr(entry_points, 'select'):
537
+ module_entries = entry_points.select(group='erispulse.module')
538
+ module_entry_map = {entry.name: entry for entry in module_entries}
539
+ else:
540
+ module_entries = entry_points.get('erispulse.module', [])
541
+ module_entry_map = {entry.name: entry for entry in module_entries}
542
+
543
+ entry_point = module_entry_map.get(meta_name)
544
+ if entry_point:
545
+ module_class = entry_point.load()
546
+ lazy_load = ModuleLoader._should_lazy_load(module_class)
547
+
548
+ if lazy_load:
549
+ lazy_module = LazyModule(meta_name, module_class, sdk, module_obj.moduleInfo)
550
+ setattr(sdk, meta_name, lazy_module)
551
+ else:
552
+ init_signature = inspect.signature(module_class.__init__)
553
+ if 'sdk' in init_signature.parameters:
554
+ instance = module_class(sdk)
555
+ else:
556
+ instance = module_class()
557
+
558
+ setattr(instance, "moduleInfo", module_obj.moduleInfo)
559
+ setattr(sdk, meta_name, instance)
560
+
561
+ logger.debug(f"预注册模块: {meta_name}")
562
+
563
+ return True
564
+
565
+ except Exception as e:
566
+ logger.error(f"预注册模块 {meta_name} 失败: {e}")
469
567
  setattr(sdk, meta_name, None)
470
- logger.debug(f"预注册模块: {meta_name}")
568
+ return False
471
569
 
472
570
  @staticmethod
473
571
  def _register_adapters(adapters: List[str], adapter_objs: Dict[str, Any]) -> bool:
@@ -475,10 +573,10 @@ class ModuleInitializer:
475
573
  {!--< internal-use >!--}
476
574
  注册适配器
477
575
 
478
- :param adapters: 适配器名称列表
479
- :param adapter_objs: 适配器对象字典
576
+ :param adapters: List[str] 适配器名称列表
577
+ :param adapter_objs: Dict[str, Any] 适配器对象字典
480
578
 
481
- :return: bool: 适配器注册是否成功
579
+ :return: bool 适配器注册是否成功
482
580
  """
483
581
  success = True
484
582
  # 存储平台名到适配器类的映射
@@ -519,85 +617,6 @@ class ModuleInitializer:
519
617
  success = False
520
618
  return success
521
619
 
522
- @staticmethod
523
- def _initialize_modules(modules: List[str], module_objs: Dict[str, Any]) -> bool:
524
- """
525
- {!--< internal-use >!--}
526
- 初始化模块
527
-
528
- :param modules: 模块名称列表
529
- :param module_objs: 模块对象字典
530
-
531
- :return: bool: 模块初始化是否成功
532
- """
533
- success = True
534
-
535
- try:
536
- entry_points = importlib.metadata.entry_points()
537
- if hasattr(entry_points, 'select'):
538
- module_entries = entry_points.select(group='erispulse.module')
539
- module_entry_map = {entry.name: entry for entry in module_entries}
540
- else:
541
- module_entries = entry_points.get('erispulse.module', [])
542
- module_entry_map = {entry.name: entry for entry in module_entries}
543
- except Exception as e:
544
- logger.error(f"获取 entry_points 失败: {e}")
545
- return False
546
-
547
- # 第一次遍历:创建所有模块的占位符
548
- for module_name in modules:
549
- module_obj = module_objs[module_name]
550
- meta_name = module_obj.moduleInfo["meta"]["name"]
551
-
552
- if not mods.get_module_status(meta_name):
553
- continue
554
-
555
- entry_point = module_entry_map.get(meta_name)
556
- if not entry_point:
557
- logger.error(f"找不到模块 {meta_name} 的 entry-point")
558
- success = False
559
- continue
560
-
561
- # 创建模块占位符
562
- if not hasattr(sdk, meta_name):
563
- setattr(sdk, meta_name, None)
564
-
565
- # 第二次遍历:实际初始化模块
566
- for module_name in modules:
567
- module_obj = module_objs[module_name]
568
- meta_name = module_obj.moduleInfo["meta"]["name"]
569
-
570
- try:
571
- if not mods.get_module_status(meta_name):
572
- continue
573
-
574
- entry_point = module_entry_map.get(meta_name)
575
- if not entry_point:
576
- continue
577
-
578
- module_class = entry_point.load()
579
- lazy_load = ModuleLoader._should_lazy_load(module_class)
580
-
581
- if lazy_load:
582
- lazy_module = LazyModule(meta_name, module_class, sdk, module_obj.moduleInfo)
583
- setattr(sdk, meta_name, lazy_module)
584
- else:
585
- init_signature = inspect.signature(module_class.__init__)
586
- if 'sdk' in init_signature.parameters:
587
- instance = module_class(sdk)
588
- else:
589
- instance = module_class()
590
-
591
- setattr(instance, "moduleInfo", module_obj.moduleInfo)
592
- setattr(sdk, meta_name, instance)
593
- logger.debug(f"模块 {meta_name} 已初始化")
594
-
595
- except Exception as e:
596
- logger.error(f"初始化模块 {meta_name} 失败: {e}")
597
- success = False
598
-
599
- return success
600
-
601
620
  def init_progress() -> bool:
602
621
  """
603
622
  初始化项目环境文件
@@ -605,7 +624,7 @@ def init_progress() -> bool:
605
624
  1. 检查并创建main.py入口文件
606
625
  2. 确保基础目录结构存在
607
626
 
608
- :return: bool: 是否创建了新的main.py文件
627
+ :return: bool 是否创建了新的main.py文件
609
628
 
610
629
  {!--< tips >!--}
611
630
  1. 如果main.py已存在则不会覆盖
@@ -658,7 +677,7 @@ def _prepare_environment() -> bool:
658
677
  1. 初始化项目环境文件
659
678
  2. 加载环境变量配置
660
679
 
661
- :return: bool: 环境准备是否成功
680
+ :return: bool 环境准备是否成功
662
681
  """
663
682
  logger.info("[Init] 准备初始化环境...")
664
683
  try:
@@ -680,7 +699,7 @@ def init() -> bool:
680
699
  1. 准备运行环境
681
700
  2. 初始化所有模块和适配器
682
701
 
683
- :return: bool: SDK初始化是否成功
702
+ :return: bool SDK初始化是否成功
684
703
 
685
704
  {!--< tips >!--}
686
705
  1. 这是SDK的主要入口函数
@@ -700,8 +719,8 @@ def load_module(module_name: str) -> bool:
700
719
  """
701
720
  手动加载指定模块
702
721
 
703
- :param module_name: 要加载的模块名称
704
- :return: bool: 加载是否成功
722
+ :param module_name: str 要加载的模块名称
723
+ :return: bool 加载是否成功
705
724
 
706
725
  {!--< tips >!--}
707
726
  1. 可用于手动触发懒加载模块的初始化
ErisPulse/__main__.py CHANGED
@@ -5,7 +5,6 @@
5
5
 
6
6
  ## 主要命令
7
7
  ### 包管理:
8
- search: 搜索PyPI上的ErisPulse模块
9
8
  install: 安装模块/适配器包
10
9
  uninstall: 卸载模块/适配器包
11
10
  list: 列出已安装的模块/适配器
@@ -42,8 +41,18 @@ from watchdog.events import FileSystemEventHandler
42
41
  from .Core.shellprint import shellprint, Shell_Printer
43
42
 
44
43
  class PyPIManager:
45
- """管理PyPI上的ErisPulse模块和适配器"""
44
+ """
45
+ PyPI包管理器
46
46
 
47
+ 负责与PyPI交互,包括搜索、安装、卸载和升级ErisPulse模块/适配器
48
+
49
+ {!--< tips >!--}
50
+ 1. 支持多个远程源作为备份
51
+ 2. 自动区分模块和适配器
52
+ 3. 提供详细的错误处理
53
+ {!--< /tips >!--}
54
+ """
55
+
47
56
  REMOTE_SOURCES = [
48
57
  "https://erisdev.com/packages.json",
49
58
  "https://raw.githubusercontent.com/ErisPulse/ErisPulse-ModuleRepo/main/packages.json"
@@ -51,6 +60,20 @@ class PyPIManager:
51
60
 
52
61
  @staticmethod
53
62
  async def get_remote_packages() -> dict:
63
+ """
64
+ 获取远程包列表
65
+
66
+ 从配置的远程源获取所有可用的ErisPulse模块和适配器
67
+
68
+ :return:
69
+ Dict[str, Dict]: 包含模块和适配器的字典
70
+ - modules: 模块字典 {模块名: 模块信息}
71
+ - adapters: 适配器字典 {适配器名: 适配器信息}
72
+
73
+ :raises ClientError: 当网络请求失败时抛出
74
+ :raises asyncio.TimeoutError: 当请求超时时抛出
75
+ """
76
+
54
77
  import aiohttp
55
78
  from aiohttp import ClientError, ClientTimeout
56
79
 
@@ -86,30 +109,16 @@ class PyPIManager:
86
109
  shellprint.panel(f"获取远程模块列表失败: {last_error}", "错误", "error")
87
110
  return {"modules": {}, "adapters": {}}
88
111
 
89
- @staticmethod
90
- def search_packages(query: str) -> List[Dict[str, str]]:
91
- try:
92
- result = subprocess.run(
93
- [sys.executable, "-m", "pip", "search", query],
94
- capture_output=True,
95
- text=True
96
- )
97
-
98
- packages = []
99
- for line in result.stdout.split('\n'):
100
- if "ErisPulse-" in line:
101
- parts = line.split(' ', 1)
102
- if len(parts) >= 1:
103
- name = parts[0].strip()
104
- desc = parts[1].strip() if len(parts) > 1 else ""
105
- packages.append({"name": name, "description": desc})
106
- return packages
107
- except Exception as e:
108
- shellprint.panel(f"搜索PyPI包失败: {e}", "错误", "error")
109
- return []
110
-
111
112
  @staticmethod
112
113
  def get_installed_packages() -> Dict[str, Dict[str, str]]:
114
+ """
115
+ 获取已安装的包信息
116
+
117
+ :return:
118
+ Dict[str, Dict[str, Dict[str, str]]]: 已安装包字典
119
+ - modules: 已安装模块 {模块名: 模块信息}
120
+ - adapters: 已安装适配器 {适配器名: 适配器信息}
121
+ """
113
122
  packages = {
114
123
  "modules": {},
115
124
  "adapters": {}
@@ -140,6 +149,13 @@ class PyPIManager:
140
149
 
141
150
  @staticmethod
142
151
  def install_package(package_name: str, upgrade: bool = False) -> bool:
152
+ """
153
+ 安装指定包
154
+
155
+ :param package_name: str 要安装的包名
156
+ :param upgrade: bool 是否升级已安装的包 (默认: False)
157
+ :return: bool 安装是否成功
158
+ """
143
159
  try:
144
160
  cmd = [sys.executable, "-m", "pip", "install"]
145
161
  if upgrade:
@@ -158,6 +174,12 @@ class PyPIManager:
158
174
 
159
175
  @staticmethod
160
176
  def uninstall_package(package_name: str) -> bool:
177
+ """
178
+ 卸载指定包
179
+
180
+ :param package_name: str 要卸载的包名
181
+ :return: bool 卸载是否成功
182
+ """
161
183
  try:
162
184
  shellprint.status(f"正在卸载 {package_name}...")
163
185
  result = subprocess.run(
@@ -174,6 +196,16 @@ class PyPIManager:
174
196
 
175
197
  @staticmethod
176
198
  def upgrade_all() -> bool:
199
+ """
200
+ 升级所有已安装的ErisPulse包
201
+
202
+ :return: bool 升级是否成功
203
+
204
+ {!--< tips >!--}
205
+ 1. 会先列出所有可升级的包
206
+ 2. 需要用户确认才会执行升级
207
+ {!--< /tips >!--}
208
+ """
177
209
  try:
178
210
  installed = PyPIManager.get_installed_packages()
179
211
  all_packages = set()
@@ -205,6 +237,17 @@ class PyPIManager:
205
237
  return False
206
238
 
207
239
  class ReloadHandler(FileSystemEventHandler):
240
+ """
241
+ 热重载处理器
242
+
243
+ 监控文件变化并自动重启脚本
244
+
245
+ {!--< tips >!--}
246
+ 1. 基于watchdog实现文件监控
247
+ 2. 有1秒的防抖延迟
248
+ 3. 会终止旧进程并启动新进程
249
+ {!--< /tips >!--}
250
+ """
208
251
  def __init__(self, script_path, *args, **kwargs):
209
252
  super().__init__(*args, **kwargs)
210
253
  self.script_path = script_path
@@ -213,6 +256,11 @@ class ReloadHandler(FileSystemEventHandler):
213
256
  self.start_process()
214
257
 
215
258
  def start_process(self):
259
+ """
260
+ 启动/重启被监控的进程
261
+
262
+ {!--< internal-use >!--}
263
+ """
216
264
  if self.process:
217
265
  self.process.terminate()
218
266
  self.process.wait()
@@ -222,6 +270,11 @@ class ReloadHandler(FileSystemEventHandler):
222
270
  self.last_reload = time.time()
223
271
 
224
272
  def on_modified(self, event):
273
+ """
274
+ 文件修改事件处理
275
+
276
+ :param event: FileSystemEvent 文件系统事件对象
277
+ """
225
278
  now = time.time()
226
279
  if now - self.last_reload < 1.0:
227
280
  return
@@ -231,6 +284,16 @@ class ReloadHandler(FileSystemEventHandler):
231
284
  self.start_process()
232
285
 
233
286
  def start_reloader(script_path):
287
+ """
288
+ 启动热重载监控
289
+
290
+ :param script_path: str 要监控的脚本路径
291
+
292
+ {!--< tips >!--}
293
+ 1. 监控脚本所在目录和modules目录
294
+ 2. 按Ctrl+C可停止监控
295
+ {!--< /tips >!--}
296
+ """
234
297
  project_root = os.path.dirname(os.path.abspath(__file__))
235
298
  watch_dirs = [
236
299
  os.path.dirname(os.path.abspath(script_path)),
@@ -257,6 +320,14 @@ def start_reloader(script_path):
257
320
  observer.join()
258
321
 
259
322
  def run_script(script_path: str, reload: bool = False):
323
+ """
324
+ 运行指定脚本
325
+
326
+ :param script_path: str 要运行的脚本路径
327
+ :param reload: bool 是否启用热重载 (默认: False)
328
+
329
+ :raises FileNotFoundError: 当脚本不存在时抛出
330
+ """
260
331
  if not os.path.exists(script_path):
261
332
  shellprint.panel(f"找不到指定文件: {script_path}", "错误", "error")
262
333
  return
@@ -270,13 +341,31 @@ def run_script(script_path: str, reload: bool = False):
270
341
  runpy.run_path(script_path, run_name="__main__")
271
342
  except KeyboardInterrupt:
272
343
  shellprint.panel("脚本执行已中断", "中断", "info")
344
+
273
345
  def get_erispulse_version():
346
+ """
347
+ 获取当前安装的ErisPulse版本
348
+
349
+ :return: str ErisPulse版本号或"unknown version"
350
+ """
274
351
  try:
275
352
  return version("ErisPulse")
276
353
  except PackageNotFoundError:
277
354
  return "unknown version"
278
355
 
279
356
  def main():
357
+ """
358
+ CLI主入口
359
+
360
+ 解析命令行参数并执行相应命令
361
+
362
+ {!--< tips >!--}
363
+ 1. 使用argparse处理命令行参数
364
+ 2. 支持彩色输出和表格显示
365
+ 3. 提供详细的错误处理
366
+ {!--< /tips >!--}
367
+ """
368
+
280
369
  parser = argparse.ArgumentParser(
281
370
  prog="epsdk",
282
371
  formatter_class=argparse.RawTextHelpFormatter,
@@ -293,11 +382,7 @@ def main():
293
382
  metavar=f"{Shell_Printer.GREEN}<命令>{Shell_Printer.RESET}",
294
383
  help='具体命令的帮助信息'
295
384
  )
296
-
297
- # 搜索命令
298
- search_parser = subparsers.add_parser('search', help='搜索PyPI上的ErisPulse模块')
299
- search_parser.add_argument('query', type=str, help='搜索关键词')
300
-
385
+
301
386
  # 安装命令
302
387
  install_parser = subparsers.add_parser('install', help='安装模块/适配器包')
303
388
  install_parser.add_argument('package', type=str, help='要安装的包名')
@@ -336,20 +421,7 @@ def main():
336
421
  return
337
422
 
338
423
  try:
339
- if args.command == "search":
340
- packages = PyPIManager.search_packages(args.query)
341
- if packages:
342
- rows = [
343
- [
344
- f"{Shell_Printer.BLUE}{pkg['name']}{Shell_Printer.RESET}",
345
- pkg['description']
346
- ] for pkg in packages
347
- ]
348
- shellprint.table(["包名", "描述"], rows, "搜索结果", "info")
349
- else:
350
- shellprint.panel(f"未找到匹配 '{args.query}' 的ErisPulse包", "提示", "info")
351
-
352
- elif args.command == "install":
424
+ if args.command == "install":
353
425
  import asyncio
354
426
  # 首先检查是否是远程模块/适配器的简称
355
427
  remote_packages = asyncio.run(PyPIManager.get_remote_packages())
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ErisPulse
3
- Version: 2.1.0
3
+ Version: 2.1.1
4
4
  Summary: ErisPulse 是一个模块化、可扩展的异步 Python SDK 框架,主要用于构建高效、可维护的机器人应用程序。
5
5
  Author-email: "艾莉丝·格雷拉特(WSu2059)" <wsu2059@qq.com>, runoneall <runoobsteve@gmail.com>
6
6
  License: MIT License
@@ -1,16 +1,16 @@
1
- ErisPulse/__init__.py,sha256=4jcAocMDQt4xdE9B3di8lGCtrU47Y4DY2ipW_9diYbU,26210
2
- ErisPulse/__main__.py,sha256=DeMBevz0KyLywnd5HccgZDwVfv-EKQOpo1fsVypKwiE,18525
1
+ ErisPulse/__init__.py,sha256=JLcJpPdgwBzPVEurGM6hLGxok4wajh9PF8wp6VAeKGo,26329
2
+ ErisPulse/__main__.py,sha256=yxlB-rCQKy7D5XMWqP5id1sOQbzLuPx048NNpLaCDf8,19851
3
3
  ErisPulse/Core/__init__.py,sha256=CIxWFdB6-0D8YJz7IdW052A4YllDsklEONCRj7mOpkQ,362
4
- ErisPulse/Core/adapter.py,sha256=gzryZjrOy0uowE5oU4MaVTtGPW7HP4StfvP5ECC4rUk,20510
4
+ ErisPulse/Core/adapter.py,sha256=2tHaN2wvPeOHN4o3BroHqeA0T-u097-HFlY8qxHvyLs,17943
5
5
  ErisPulse/Core/env.py,sha256=9WYNadD9h2jP_2wxOVBJEhH1uDzbctW7eB4Ba9RSjA4,20409
6
- ErisPulse/Core/logger.py,sha256=035II2YvRmcAvbbCEsmMxjvAJhdLvQlUqaDXAufWk_E,5782
6
+ ErisPulse/Core/logger.py,sha256=40vDe_D3L6ople-RZX8eGXntrZpFGHHzSl3pYxK-FLI,7196
7
7
  ErisPulse/Core/mods.py,sha256=5SPutuzbMrA-VZwiXeNxYWfrdbpLRdYfQ0RvEkFuQgg,7308
8
8
  ErisPulse/Core/raiserr.py,sha256=QLQ3r7p4iFP86XBLq9mtf1wv1xSlgny35i8t5-l4DXo,4620
9
9
  ErisPulse/Core/server.py,sha256=H8dUUj8mxBLEd3ick7btbWEE_m58Y6277Zo5FY7Ild4,9217
10
10
  ErisPulse/Core/shellprint.py,sha256=-BFoyFho_D3XEhxIoKt6x5gO4C62LKwmJWKDUGiPjNY,5908
11
11
  ErisPulse/Core/util.py,sha256=kyydBAJHHG9I7rMRzKWtLAQMZoJyBqHiBAweqcraFkU,4001
12
- erispulse-2.1.0.dist-info/METADATA,sha256=Ip9gteaaYMG0Qkzxq_DbFnmvCYNC8ULMPxCZ6jYimeA,6161
13
- erispulse-2.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
14
- erispulse-2.1.0.dist-info/entry_points.txt,sha256=Jss71M6nEha0TA-DyVZugPYdcL14s9QpiOeIlgWxzOc,182
15
- erispulse-2.1.0.dist-info/licenses/LICENSE,sha256=lBYj7Nk4urLvByj4HvQFxu8j9hThhFF6OGfyxAZBP9Q,1451
16
- erispulse-2.1.0.dist-info/RECORD,,
12
+ erispulse-2.1.1.dist-info/METADATA,sha256=QYngGAOCd2sYXMr-Ezfeift5FyZPqBEWKBI8Kf76S_0,6161
13
+ erispulse-2.1.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
14
+ erispulse-2.1.1.dist-info/entry_points.txt,sha256=Jss71M6nEha0TA-DyVZugPYdcL14s9QpiOeIlgWxzOc,182
15
+ erispulse-2.1.1.dist-info/licenses/LICENSE,sha256=lBYj7Nk4urLvByj4HvQFxu8j9hThhFF6OGfyxAZBP9Q,1451
16
+ erispulse-2.1.1.dist-info/RECORD,,