ErisPulse 1.2.4__py3-none-any.whl → 1.2.7__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
@@ -38,6 +38,7 @@ sdk.logger.info("SDK已初始化")
38
38
 
39
39
  import os
40
40
  import sys
41
+ from typing import Tuple, Dict, List, Any, Optional, Set, Union, Type, FrozenSet
41
42
 
42
43
  # 依赖类型
43
44
  import types
@@ -48,7 +49,7 @@ from .raiserr import raiserr
48
49
  from .logger import logger
49
50
  from .db import env
50
51
  from .mods import mods
51
- from .adapter import adapter, BaseAdapter, SendDSL
52
+ from .adapter import adapter, AdapterFather, SendDSL
52
53
 
53
54
  # 这里不能删,确保windows下的shell能正确显示颜色
54
55
  os.system('')
@@ -62,9 +63,9 @@ BaseModules = {
62
63
  "env" : env,
63
64
  "mods" : mods,
64
65
  "adapter" : adapter,
65
- "SendDSL" : SendDSL, # 链式发送基类 - 兼容原 sdk.SendDSL | 待弃用, 需要在 Adapter继承类中手动创建嵌套类并集成 super().SendDSL()
66
- "AdapterFather" : BaseAdapter,
67
- "BaseAdapter" : BaseAdapter
66
+ "SendDSL" : SendDSL, # 链式发送基类 - 兼容原 sdk.SendDSL | 待弃用, 需要在 Adapter继承类中手动创建嵌套类并集成 super().SendDSL()
67
+ "AdapterFather" : AdapterFather,
68
+ "BaseAdapter" : AdapterFather
68
69
  }
69
70
 
70
71
  BaseErrors = {
@@ -88,7 +89,7 @@ for error, doc in BaseErrors.items():
88
89
  raiserr.register(error, doc=doc)
89
90
  except Exception as e:
90
91
  raise e
91
- def init_progress():
92
+ def init_progress() -> Tuple[bool, bool]:
92
93
  from pathlib import Path
93
94
  env_file = Path("env.py")
94
95
  main_file = Path("main.py")
@@ -150,7 +151,6 @@ if __name__ == "__main__":
150
151
  return False
151
152
 
152
153
  def _prepare_environment() -> bool:
153
- # 检查环境
154
154
  logger.info("[Init] 准备初始化环境...")
155
155
  try:
156
156
  env_init, main_init = init_progress()
@@ -167,7 +167,8 @@ def _prepare_environment() -> bool:
167
167
  except Exception as e:
168
168
  logger.error(f"环境准备失败: {e}")
169
169
  return False
170
- def _scan_modules(module_path: str) -> tuple[dict, list, list]:
170
+ def _scan_modules(module_path: str) -> Tuple[Dict, List, List]:
171
+
171
172
  # 扫描并验证模块
172
173
  module_objs = {}
173
174
  enabled_modules = []
@@ -220,7 +221,7 @@ def _validate_module(moduleObj, module_name: str) -> bool:
220
221
  return False
221
222
  return True
222
223
 
223
- def _check_dependencies(moduleObj, module_name: str, available_modules: list):
224
+ def _check_dependencies(moduleObj, module_name: str, available_modules: list) -> None:
224
225
  # 检查模块依赖关系
225
226
  required_deps = moduleObj.moduleInfo.get("dependencies", {}).get("requires", [])
226
227
  if missing := [dep for dep in required_deps if dep not in available_modules]:
@@ -314,4 +315,4 @@ def init() -> bool:
314
315
  raiserr.InitError(f"sdk初始化失败: {e}", exit=True)
315
316
  return False
316
317
 
317
- sdk.init = init
318
+ sdk.init = init
ErisPulse/__main__.py CHANGED
@@ -203,7 +203,7 @@ class Shell_Printer:
203
203
  print(f"{cls.YELLOW}请输入 'y' 或 'n'{cls.RESET}")
204
204
 
205
205
  @classmethod
206
- def ask(cls, msg, choices=None, default=None) -> str | None:
206
+ def ask(cls, msg, choices=None, default="") -> str:
207
207
  prompt = f"{cls.BOLD}{msg}{cls.RESET}"
208
208
  if choices:
209
209
  prompt += f" ({cls.CYAN}{'/'.join(choices)}{cls.RESET})"
@@ -909,11 +909,56 @@ def upgrade_all_modules(force=False):
909
909
 
910
910
  for i, update in enumerate(updates_available, 1):
911
911
  print(f"\n{Shell_Printer.BOLD}[{i}/{len(updates_available)}]{Shell_Printer.RESET} 更新模块 {Shell_Printer.BOLD}{update['name']}{Shell_Printer.RESET}")
912
+
913
+ # 检查新版本的依赖
914
+ module_key = f"{update['name']}@{update['provider']}"
915
+ new_module_info = modules_data[module_key]
916
+ new_dependencies = new_module_info.get('dependencies', {}).get('requires', [])
917
+
918
+ # 检查缺失的依赖
919
+ missing_deps = []
920
+ for dep in new_dependencies:
921
+ if dep not in all_modules or not all_modules[dep].get('status', True):
922
+ missing_deps.append(dep)
923
+
924
+ if missing_deps:
925
+ shellprint.panel(
926
+ f"模块 {update['name']} 需要以下依赖:\n{Shell_Printer.YELLOW}{', '.join(missing_deps)}{Shell_Printer.RESET}",
927
+ "缺失依赖",
928
+ "warning"
929
+ )
930
+ if not shellprint.confirm("是否安装这些依赖?", default=True):
931
+ print(f"{Shell_Printer.BLUE}跳过模块 {update['name']} 的更新{Shell_Printer.RESET}")
932
+ continue
933
+
934
+ for dep in missing_deps:
935
+ print(f"\n{Shell_Printer.BOLD}安装依赖: {dep}{Shell_Printer.RESET}")
936
+ install_module(dep)
937
+
912
938
  module_url = update['url'] + update['path']
913
939
  script_dir = os.path.dirname(os.path.abspath(__file__))
914
940
  module_dir = os.path.join(script_dir, 'modules', update['name'])
915
941
  zip_path = os.path.join(script_dir, f"{update['name']}.zip")
916
942
 
943
+ # 检查新版本的pip依赖
944
+ new_pip_deps = new_module_info.get('dependencies', {}).get('pip', [])
945
+ current_pip_deps = all_modules[update['name']].get('info', {}).get('dependencies', {}).get('pip', [])
946
+ added_pip_deps = [dep for dep in new_pip_deps if dep not in current_pip_deps]
947
+
948
+ if added_pip_deps:
949
+ shellprint.panel(
950
+ f"模块 {update['name']} 需要以下新的pip依赖:\n{Shell_Printer.YELLOW}{', '.join(added_pip_deps)}{Shell_Printer.RESET}",
951
+ "新增pip依赖",
952
+ "warning"
953
+ )
954
+ if not shellprint.confirm("是否安装这些pip依赖?", default=True):
955
+ print(f"{Shell_Printer.BLUE}跳过模块 {update['name']} 的更新{Shell_Printer.RESET}")
956
+ continue
957
+
958
+ if not install_pip_dependencies(added_pip_deps):
959
+ print(f"{Shell_Printer.RED}无法安装模块 {update['name']} 的pip依赖,更新终止{Shell_Printer.RESET}")
960
+ continue
961
+
917
962
  if not extract_and_setup_module(
918
963
  module_name=update['name'],
919
964
  module_url=module_url,
@@ -922,7 +967,12 @@ def upgrade_all_modules(force=False):
922
967
  ):
923
968
  continue
924
969
 
970
+ # 更新模块信息,包括新的依赖
925
971
  all_modules[update['name']]['info']['version'] = update['remote_version']
972
+ all_modules[update['name']]['info']['dependencies'] = {
973
+ 'requires': new_dependencies,
974
+ 'pip': new_pip_deps
975
+ }
926
976
  mods.set_all_modules(all_modules)
927
977
  print(f"{Shell_Printer.GREEN}模块 {update['name']} 已更新至版本 {update['remote_version']}{Shell_Printer.RESET}")
928
978
 
@@ -1264,4 +1314,4 @@ def main():
1264
1314
  parser.print_help()
1265
1315
 
1266
1316
  if __name__ == "__main__":
1267
- main()
1317
+ main()
ErisPulse/adapter.py CHANGED
@@ -8,7 +8,7 @@
8
8
  ### 适配器基类 (BaseAdapter)
9
9
  适配器基类提供了与外部平台交互的标准接口。
10
10
 
11
- #### call_api(endpoint: str, **params) -> Any
11
+ #### call_api(endpoint: str, **params: Any) -> Any
12
12
  调用平台API的抽象方法。
13
13
  - 参数:
14
14
  - endpoint: API端点
@@ -21,7 +21,7 @@
21
21
  - 示例:
22
22
  ```python
23
23
  class MyPlatformAdapter(BaseAdapter):
24
- async def call_api(self, endpoint: str, **params):
24
+ async def call_api(self, endpoint: str, **params: Any) -> Any:
25
25
  if endpoint == "/send":
26
26
  return await self._send_message(params)
27
27
  elif endpoint == "/upload":
@@ -40,7 +40,7 @@ class MyPlatformAdapter(BaseAdapter):
40
40
  - 示例:
41
41
  ```python
42
42
  class MyPlatformAdapter(BaseAdapter):
43
- async def start(self):
43
+ async def start(self) -> None:
44
44
  self.client = await self._create_client()
45
45
  self.ws = await self.client.create_websocket()
46
46
  self._start_heartbeat()
@@ -57,34 +57,34 @@ class MyPlatformAdapter(BaseAdapter):
57
57
  - 示例:
58
58
  ```python
59
59
  class MyPlatformAdapter(BaseAdapter):
60
- async def shutdown(self):
60
+ async def shutdown(self) -> None:
61
61
  if self.ws:
62
62
  await self.ws.close()
63
63
  if self.client:
64
64
  await self.client.close()
65
65
  ```
66
66
 
67
- #### on(event_type: str = "*") -> Callable
67
+ #### on(event_type: str = "*") -> Callable[[Callable[..., Any]], Callable[..., Any]]
68
68
  事件监听装饰器。
69
69
  - 参数:
70
70
  - event_type: 事件类型,默认"*"表示所有事件
71
71
  - 返回:
72
- - Callable: 装饰器函数
72
+ - Callable[[Callable[..., Any]], Callable[..., Any]]: 装饰器函数
73
73
  - 示例:
74
74
  ```python
75
75
  adapter = MyPlatformAdapter()
76
76
 
77
77
  @adapter.on("message")
78
- async def handle_message(data):
78
+ async def handle_message(data: Any) -> None:
79
79
  print(f"收到消息: {data}")
80
80
 
81
81
  @adapter.on("error")
82
- async def handle_error(error):
82
+ async def handle_error(error: Exception) -> None:
83
83
  print(f"发生错误: {error}")
84
84
 
85
85
  # 处理所有事件
86
86
  @adapter.on()
87
- async def handle_all(event):
87
+ async def handle_all(event: Any) -> None:
88
88
  print(f"事件: {event}")
89
89
  ```
90
90
 
@@ -98,7 +98,7 @@ async def handle_all(event):
98
98
  - 示例:
99
99
  ```python
100
100
  class MyPlatformAdapter(BaseAdapter):
101
- async def _handle_websocket_message(self, message):
101
+ async def _handle_websocket_message(self, message: Any) -> None:
102
102
  # 处理消息并触发相应事件
103
103
  if message.type == "chat":
104
104
  await self.emit("message", {
@@ -108,23 +108,23 @@ class MyPlatformAdapter(BaseAdapter):
108
108
  })
109
109
  ```
110
110
 
111
- #### middleware(func: Callable) -> Callable
111
+ #### middleware(func: Callable[..., Any]) -> Callable[..., Any]
112
112
  添加中间件处理器。
113
113
  - 参数:
114
114
  - func: 中间件函数
115
115
  - 返回:
116
- - Callable: 中间件函数
116
+ - Callable[..., Any]: 中间件函数
117
117
  - 示例:
118
118
  ```python
119
119
  adapter = MyPlatformAdapter()
120
120
 
121
121
  @adapter.middleware
122
- async def log_middleware(data):
122
+ async def log_middleware(data: Any) -> Any:
123
123
  print(f"处理数据: {data}")
124
124
  return data
125
125
 
126
126
  @adapter.middleware
127
- async def filter_middleware(data):
127
+ async def filter_middleware(data: Any) -> Optional[Any]:
128
128
  if "spam" in data.get("content", ""):
129
129
  return None
130
130
  return data
@@ -133,7 +133,7 @@ async def filter_middleware(data):
133
133
  ### 消息发送DSL (SendDSL)
134
134
  提供链式调用风格的消息发送接口。
135
135
 
136
- #### To(target_type: str = None, target_id: str = None) -> 'SendDSL'
136
+ #### To(target_type: Optional[str] = None, target_id: Optional[str] = None) -> 'SendDSL'
137
137
  设置消息目标。
138
138
  - 参数:
139
139
  - target_type: 目标类型(可选)
@@ -152,12 +152,12 @@ sdk.adapter.Platform.Send.To("group", "456").Text("Hello Group")
152
152
  sdk.adapter.Platform.Send.To("123").Text("Hello")
153
153
  ```
154
154
 
155
- #### Text(text: str) -> Task
155
+ #### Text(text: str) -> asyncio.Task
156
156
  发送文本消息。
157
157
  - 参数:
158
158
  - text: 文本内容
159
159
  - 返回:
160
- - Task: 异步任务
160
+ - asyncio.Task: 异步任务
161
161
  - 示例:
162
162
  ```python
163
163
  # 发送简单文本
@@ -192,7 +192,7 @@ for name, adapter in adapters.items():
192
192
  sdk.adapter.register(name, adapter)
193
193
  ```
194
194
 
195
- #### startup(platforms: List[str] = None) -> None
195
+ #### startup(platforms: Optional[List[str]] = None) -> None
196
196
  启动指定的适配器。
197
197
  - 参数:
198
198
  - platforms: 要启动的平台列表,None表示所有平台
@@ -226,7 +226,10 @@ atexit.register(lambda: asyncio.run(sdk.adapter.shutdown()))
226
226
 
227
227
  import functools
228
228
  import asyncio
229
- from typing import Callable, Any, Dict, List, Type, Optional, Set
229
+ from typing import (
230
+ Callable, Any, Dict, List, Type, Optional, Set,
231
+ Union, Awaitable, TypeVar, Generic, Tuple, Coroutine, FrozenSet
232
+ )
230
233
  from collections import defaultdict
231
234
 
232
235
 
@@ -457,6 +460,6 @@ class AdapterManager:
457
460
  def platforms(self) -> list:
458
461
  return list(self._adapters.keys())
459
462
 
460
-
463
+ AdapterFather = BaseAdapter
461
464
  adapter = AdapterManager()
462
465
  SendDSL = SendDSLBase
ErisPulse/db.py CHANGED
@@ -436,6 +436,7 @@ import threading
436
436
  from pathlib import Path
437
437
  from datetime import datetime
438
438
  from functools import lru_cache
439
+ from typing import List, Dict, Optional, Any, Set, Tuple, Union, Type, FrozenSet
439
440
  from .raiserr import raiserr
440
441
 
441
442
  class EnvManager:
@@ -479,7 +480,7 @@ class EnvManager:
479
480
  self._last_snapshot_time = time.time() # 初始化为当前时间
480
481
  self._snapshot_interval = 3600 # 默认每小时自动快照
481
482
 
482
- def get(self, key, default=None):
483
+ def get(self, key, default=None) -> Any:
483
484
  try:
484
485
  with sqlite3.connect(self.db_path) as conn:
485
486
  cursor = conn.cursor()
@@ -505,55 +506,65 @@ class EnvManager:
505
506
  cursor.execute("SELECT key FROM config")
506
507
  return [row[0] for row in cursor.fetchall()]
507
508
 
508
- def set(self, key, value):
509
- serialized_value = json.dumps(value) if isinstance(value, (dict, list)) else str(value)
510
- with self.transaction():
511
- conn = sqlite3.connect(self.db_path)
512
- cursor = conn.cursor()
513
- cursor.execute("INSERT OR REPLACE INTO config (key, value) VALUES (?, ?)", (key, serialized_value))
514
- conn.commit()
515
- conn.close()
516
-
517
- self._check_auto_snapshot()
518
- return True
509
+ def set(self, key, value) -> bool:
510
+ try:
511
+ serialized_value = json.dumps(value) if isinstance(value, (dict, list)) else str(value)
512
+ with self.transaction():
513
+ conn = sqlite3.connect(self.db_path)
514
+ cursor = conn.cursor()
515
+ cursor.execute("INSERT OR REPLACE INTO config (key, value) VALUES (?, ?)", (key, serialized_value))
516
+ conn.commit()
517
+ conn.close()
518
+
519
+ self._check_auto_snapshot()
520
+ return True
521
+ except Exception as e:
522
+ return False
519
523
 
520
524
  def set_multi(self, items):
521
- with self.transaction():
522
- conn = sqlite3.connect(self.db_path)
523
- cursor = conn.cursor()
524
- for key, value in items.items():
525
- serialized_value = json.dumps(value) if isinstance(value, (dict, list)) else str(value)
526
- cursor.execute("INSERT OR REPLACE INTO config (key, value) VALUES (?, ?)",
527
- (key, serialized_value))
528
- conn.commit()
529
- conn.close()
530
-
531
- self._check_auto_snapshot()
532
- return True
533
-
534
- def delete(self, key):
535
- with self.transaction():
536
- conn = sqlite3.connect(self.db_path)
537
- cursor = conn.cursor()
538
- cursor.execute("DELETE FROM config WHERE key = ?", (key,))
539
- conn.commit()
540
- conn.close()
541
-
542
- self._check_auto_snapshot()
543
- return True
544
-
545
- def delete_multi(self, keys):
546
- with self.transaction():
547
- conn = sqlite3.connect(self.db_path)
548
- cursor = conn.cursor()
549
- cursor.executemany("DELETE FROM config WHERE key = ?", [(k,) for k in keys])
550
- conn.commit()
551
- conn.close()
552
-
553
- self._check_auto_snapshot()
554
- return True
525
+ try:
526
+ with self.transaction():
527
+ conn = sqlite3.connect(self.db_path)
528
+ cursor = conn.cursor()
529
+ for key, value in items.items():
530
+ serialized_value = json.dumps(value) if isinstance(value, (dict, list)) else str(value)
531
+ cursor.execute("INSERT OR REPLACE INTO config (key, value) VALUES (?, ?)",
532
+ (key, serialized_value))
533
+ conn.commit()
534
+ conn.close()
535
+
536
+ self._check_auto_snapshot()
537
+ return True
538
+ except Exception as e:
539
+ return False
555
540
 
556
- def get_multi(self, keys):
541
+ def delete(self, key) -> bool:
542
+ try:
543
+ with self.transaction():
544
+ conn = sqlite3.connect(self.db_path)
545
+ cursor = conn.cursor()
546
+ cursor.execute("DELETE FROM config WHERE key = ?", (key,))
547
+ conn.commit()
548
+ conn.close()
549
+
550
+ self._check_auto_snapshot()
551
+ return True
552
+ except Exception as e:
553
+ return False
554
+ def delete_multi(self, keys) -> bool:
555
+ try:
556
+ with self.transaction():
557
+ conn = sqlite3.connect(self.db_path)
558
+ cursor = conn.cursor()
559
+ cursor.executemany("DELETE FROM config WHERE key = ?", [(k,) for k in keys])
560
+ conn.commit()
561
+ conn.close()
562
+
563
+ self._check_auto_snapshot()
564
+ return True
565
+ except Exception as e:
566
+ return False
567
+ def get_multi(self, keys) -> dict:
557
568
  conn = sqlite3.connect(self.db_path)
558
569
  cursor = conn.cursor()
559
570
  placeholders = ','.join(['?'] * len(keys))
@@ -630,22 +641,29 @@ class EnvManager:
630
641
  def set_snapshot_interval(self, seconds):
631
642
  self._snapshot_interval = seconds
632
643
 
633
- def clear(self):
634
- conn = sqlite3.connect(self.db_path)
635
- cursor = conn.cursor()
636
- cursor.execute("DELETE FROM config")
637
- conn.commit()
638
- conn.close()
639
-
640
- def load_env_file(self):
641
- env_file = Path("env.py")
642
- if env_file.exists():
643
- spec = importlib.util.spec_from_file_location("env_module", env_file)
644
- env_module = importlib.util.module_from_spec(spec)
645
- spec.loader.exec_module(env_module)
646
- for key, value in vars(env_module).items():
647
- if not key.startswith("__") and isinstance(value, (dict, list, str, int, float, bool)):
648
- self.set(key, value)
644
+ def clear(self) -> bool:
645
+ try:
646
+ conn = sqlite3.connect(self.db_path)
647
+ cursor = conn.cursor()
648
+ cursor.execute("DELETE FROM config")
649
+ conn.commit()
650
+ conn.close()
651
+ return True
652
+ except Exception as e:
653
+ return False
654
+ def load_env_file(self) -> bool:
655
+ try:
656
+ env_file = Path("env.py")
657
+ if env_file.exists():
658
+ spec = importlib.util.spec_from_file_location("env_module", env_file)
659
+ env_module = importlib.util.module_from_spec(spec)
660
+ spec.loader.exec_module(env_module)
661
+ for key, value in vars(env_module).items():
662
+ if not key.startswith("__") and isinstance(value, (dict, list, str, int, float, bool)):
663
+ self.set(key, value)
664
+ return True
665
+ except Exception as e:
666
+ return False
649
667
  def __getattr__(self, key):
650
668
  try:
651
669
  return self.get(key)
@@ -660,7 +678,7 @@ class EnvManager:
660
678
  from .logger import logger
661
679
  logger.error(f"设置配置项 {key} 失败: {e}")
662
680
 
663
- def snapshot(self, name=None):
681
+ def snapshot(self, name=None) -> str:
664
682
  if not name:
665
683
  name = datetime.now().strftime("%Y%m%d_%H%M%S")
666
684
  snapshot_path = os.path.join(self.SNAPSHOT_DIR, f"{name}.db")
@@ -687,7 +705,7 @@ class EnvManager:
687
705
  logger.error(f"创建快照失败: {e}")
688
706
  raise
689
707
 
690
- def restore(self, snapshot_name):
708
+ def restore(self, snapshot_name) -> bool:
691
709
  snapshot_path = os.path.join(self.SNAPSHOT_DIR, f"{snapshot_name}.db") \
692
710
  if not snapshot_name.endswith('.db') else snapshot_name
693
711
 
@@ -716,7 +734,7 @@ class EnvManager:
716
734
  logger.error(f"恢复快照失败: {e}")
717
735
  return False
718
736
 
719
- def list_snapshots(self):
737
+ def list_snapshots(self) -> list:
720
738
  snapshots = []
721
739
  for f in os.listdir(self.SNAPSHOT_DIR):
722
740
  if f.endswith('.db'):
@@ -729,7 +747,7 @@ class EnvManager:
729
747
  ))
730
748
  return sorted(snapshots, key=lambda x: x[1], reverse=True)
731
749
 
732
- def delete_snapshot(self, snapshot_name):
750
+ def delete_snapshot(self, snapshot_name) -> bool:
733
751
  snapshot_path = os.path.join(self.SNAPSHOT_DIR, f"{snapshot_name}.db") \
734
752
  if not snapshot_name.endswith('.db') else snapshot_name
735
753
 
ErisPulse/logger.py CHANGED
@@ -10,7 +10,7 @@
10
10
  以debug为例:
11
11
  > 此外,还有其他级别的日志记录函数,如info, warning, error, critical等,用法相同。
12
12
 
13
- debug(msg: str, *args, **kwargs) -> None
13
+ debug(msg: str, *args: Any, **kwargs: Any) -> None
14
14
 
15
15
  记录调试级别的日志信息。
16
16
  - 参数:
@@ -70,7 +70,7 @@ for module, level in config.get("logging", {}).items():
70
70
  ```
71
71
 
72
72
  ### 日志存储和输出
73
- #### set_output_file(path: str | list) -> None
73
+ #### set_output_file(path: Union[str, List[str]]) -> None
74
74
  设置日志输出文件。
75
75
  - 参数:
76
76
  - path: 日志文件路径,可以是单个字符串或路径列表
@@ -92,7 +92,7 @@ log_file = f"logs/app_{datetime.now().strftime('%Y%m%d')}.log"
92
92
  sdk.logger.set_output_file(log_file)
93
93
  ```
94
94
 
95
- #### save_logs(path: str | list) -> None
95
+ #### save_logs(path: Union[str, List[str]]) -> None
96
96
  保存内存中的日志到文件。
97
97
  - 参数:
98
98
  - path: 保存路径,可以是单个字符串或路径列表
@@ -118,6 +118,7 @@ atexit.register(lambda: sdk.logger.save_logs("final_logs.txt"))
118
118
  import logging
119
119
  import inspect
120
120
  import datetime
121
+ from typing import List, Dict, Any, Optional, Union, Type, Set, Tuple, FrozenSet
121
122
 
122
123
  class Logger:
123
124
  def __init__(self):
@@ -131,10 +132,16 @@ class Logger:
131
132
  console_handler.setFormatter(logging.Formatter("%(message)s"))
132
133
  self._logger.addHandler(console_handler)
133
134
 
134
- def set_level(self, level: str):
135
- level = level.upper()
136
- if hasattr(logging, level):
137
- self._logger.setLevel(getattr(logging, level))
135
+ def set_level(self, level: str) -> bool:
136
+ try:
137
+ level = level.upper()
138
+ if hasattr(logging, level):
139
+ self._logger.setLevel(getattr(logging, level))
140
+ return True
141
+ return False
142
+ except Exception as e:
143
+ self._logger.error(f"无效的日志等级: {level}")
144
+ return False
138
145
 
139
146
  def set_module_level(self, module_name: str, level: str) -> bool:
140
147
  from .db import env
@@ -150,7 +157,7 @@ class Logger:
150
157
  self._logger.error(f"无效的日志等级: {level}")
151
158
  return False
152
159
 
153
- def set_output_file(self, path: str | list):
160
+ def set_output_file(self, path) -> bool:
154
161
  if self._file_handler:
155
162
  self._logger.removeHandler(self._file_handler)
156
163
  self._file_handler.close()
@@ -164,17 +171,17 @@ class Logger:
164
171
  file_handler.setFormatter(logging.Formatter("%(message)s"))
165
172
  self._logger.addHandler(file_handler)
166
173
  self._logger.info(f"日志输出已设置到文件: {p}")
174
+ return True
167
175
  except Exception as e:
168
176
  self._logger.error(f"无法设置日志文件 {p}: {e}")
169
- raise e
170
-
171
- def save_logs(self, path: str | list):
177
+ return False
178
+ def save_logs(self, path) -> bool:
172
179
  if self._logs == None:
173
180
  self._logger.warning("没有log记录可供保存。")
174
- return
181
+ return False
175
182
  if isinstance(path, str):
176
183
  path = [path]
177
-
184
+
178
185
  for p in path:
179
186
  try:
180
187
  with open(p, "w", encoding="utf-8") as file:
@@ -183,10 +190,16 @@ class Logger:
183
190
  for log in logs:
184
191
  file.write(f" {log}\n")
185
192
  self._logger.info(f"日志已被保存到:{p}。")
193
+ return True
186
194
  except Exception as e:
187
195
  self._logger.error(f"无法保存日志到 {p}: {e}。")
188
- raise e
196
+ return False
189
197
 
198
+ def get_logs(self, module_name: str = None) -> dict:
199
+ if module_name:
200
+ return {module_name: self._logs.get(module_name, [])}
201
+ return {k: v.copy() for k, v in self._logs.items()}
202
+
190
203
  def _save_in_memory(self, ModuleName, msg):
191
204
  if ModuleName not in self._logs:
192
205
  self._logs[ModuleName] = []
ErisPulse/mods.py CHANGED
@@ -81,7 +81,7 @@ module_info["info"]["meta"]["version"] = "1.1.0"
81
81
  sdk.mods.set_module("MyModule", module_info)
82
82
  ```
83
83
 
84
- #### get_module(module_name: str) -> dict | None
84
+ #### get_module(module_name: str) -> dict
85
85
  获取模块信息。
86
86
  - 参数:
87
87
  - module_name: 模块名称
@@ -253,7 +253,7 @@ sdk.env.set(custom_status_key, is_active)
253
253
  """
254
254
 
255
255
  import json
256
- from typing import Dict, Optional
256
+ from typing import Dict, Optional, Any, List, Set, Tuple, Union, Type, FrozenSet
257
257
 
258
258
  class ModuleManager:
259
259
  DEFAULT_MODULE_PREFIX = "erispulse.module.data:"
ErisPulse/raiserr.py CHANGED
@@ -25,12 +25,12 @@ class CustomBase(Exception):
25
25
  sdk.raiserr.register("AdvancedError", "高级错误", CustomBase)
26
26
  ```
27
27
 
28
- #### info(name: str = None) -> dict | None
28
+ #### info(name: str = None) -> Dict[str, Any] | None
29
29
  获取错误类型信息。
30
30
  - 参数:
31
31
  - name: 错误类型名称,如果为None则返回所有错误类型信息
32
32
  - 返回:
33
- - dict: 包含错误类型信息的字典,包括类型名、文档和类引用
33
+ - Dict[str, Any]: 包含错误类型信息的字典,包括类型名、文档和类引用
34
34
  - None: 如果指定的错误类型不存在
35
35
  - 示例:
36
36
  ```python
@@ -71,12 +71,13 @@ except Exception as e:
71
71
  import sys
72
72
  import traceback
73
73
  import asyncio
74
+ from typing import Dict, Any, Optional, Type, List, Set, Tuple, Union
74
75
 
75
76
  class Error:
76
77
  def __init__(self):
77
78
  self._types = {}
78
79
 
79
- def register(self, name, doc="", base=Exception):
80
+ def register(self, name, doc="", base=Exception) -> Type:
80
81
  if name not in self._types:
81
82
  err_cls = type(name, (base,), {"__doc__": doc})
82
83
  self._types[name] = err_cls
@@ -98,7 +99,7 @@ class Error:
98
99
  raise exc
99
100
  return raiser
100
101
 
101
- def info(self, name: str = None):
102
+ def info(self, name: str = None) -> Dict[str, Any] | None:
102
103
  result = {}
103
104
  for err_name, err_cls in self._types.items():
104
105
  result[err_name] = {
ErisPulse/util.py CHANGED
@@ -5,8 +5,8 @@
5
5
 
6
6
  ## API 文档
7
7
  ### 拓扑排序:
8
- - topological_sort(elements, dependencies, error): 拓扑排序依赖关系
9
- - show_topology(): 可视化模块依赖关系
8
+ - topological_sort(elements: List[str], dependencies: Dict[str, List[str]], error: Type[Exception]) -> List[str]: 拓扑排序依赖关系
9
+ - show_topology() -> str: 可视化模块依赖关系
10
10
 
11
11
  ### 装饰器:
12
12
  - @cache: 缓存函数结果
@@ -14,7 +14,7 @@
14
14
  - @retry(max_attempts=3, delay=1): 失败自动重试
15
15
 
16
16
  ### 异步执行:
17
- - ExecAsync(async_func, *args, **kwargs): 异步执行函数
17
+ - ExecAsync(async_func: Callable, *args: Any, **kwargs: Any) -> Any: 异步执行函数
18
18
 
19
19
  ### 示例用法:
20
20
 
@@ -48,10 +48,11 @@ import functools
48
48
  import traceback
49
49
  from concurrent.futures import ThreadPoolExecutor
50
50
  from collections import defaultdict, deque
51
+ from typing import List, Dict, Type, Callable, Any, Optional, Set
51
52
 
52
53
  executor = ThreadPoolExecutor()
53
54
 
54
- def topological_sort(elements, dependencies, error):
55
+ def topological_sort(elements, dependencies, error) -> List[str]:
55
56
  graph = defaultdict(list)
56
57
  in_degree = {element: 0 for element in elements}
57
58
  for element, deps in dependencies.items():
@@ -72,7 +73,7 @@ def topological_sort(elements, dependencies, error):
72
73
  sdk.logger.error(f"依赖导入错误: {elements} vs {sorted_list} | 发生了循环依赖")
73
74
  return sorted_list
74
75
 
75
- def show_topology():
76
+ def show_topology() -> str:
76
77
  from . import sdk
77
78
  dep_data = sdk.env.get('module_dependencies')
78
79
  if not dep_data:
@@ -98,7 +99,7 @@ def show_topology():
98
99
 
99
100
  return "\n".join(result)
100
101
 
101
- def ExecAsync(async_func, *args, **kwargs):
102
+ def ExecAsync(async_func, *args, **kwargs) -> Any:
102
103
  loop = asyncio.get_event_loop()
103
104
  return loop.run_in_executor(executor, lambda: asyncio.run(async_func(*args, **kwargs)))
104
105
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ErisPulse
3
- Version: 1.2.4
3
+ Version: 1.2.7
4
4
  Summary: ErisPulse 是一个模块化、可扩展的异步 Python SDK 框架,主要用于构建高效、可维护的机器人应用程序。
5
5
  Author-email: "艾莉丝·格雷拉特(WSu2059)" <wsu2059@qq.com>, runoneall <runoobsteve@gmail.com>
6
6
  License: MIT License
@@ -38,13 +38,15 @@ Classifier: License :: OSI Approved :: MIT License
38
38
  Classifier: Operating System :: OS Independent
39
39
  Classifier: Programming Language :: Python :: 3
40
40
  Classifier: Programming Language :: Python :: 3 :: Only
41
+ Classifier: Programming Language :: Python :: 3.8
42
+ Classifier: Programming Language :: Python :: 3.9
41
43
  Classifier: Programming Language :: Python :: 3.10
42
44
  Classifier: Programming Language :: Python :: 3.11
43
45
  Classifier: Programming Language :: Python :: 3.12
44
46
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
45
- Requires-Python: >=3.10
47
+ Requires-Python: >=3.8
46
48
  Requires-Dist: aiohttp
47
- Requires-Dist: importlib>=1.0.4
49
+ Requires-Dist: importlib
48
50
  Requires-Dist: pip
49
51
  Requires-Dist: watchdog
50
52
  Description-Content-Type: text/markdown
@@ -54,7 +56,6 @@ Description-Content-Type: text/markdown
54
56
  ![ErisPulse Logo](.github/assets/erispulse_logo.png)
55
57
 
56
58
  [![FramerOrg](https://img.shields.io/badge/合作伙伴-FramerOrg-blue?style=flat-square)](https://github.com/FramerOrg)
57
- [![License](https://img.shields.io/github/license/ErisPulse/ErisPulse?style=flat-square)](https://github.com/ErisPulse/ErisPulse/blob/main/LICENSE)
58
59
  [![Python Versions](https://img.shields.io/pypi/pyversions/ErisPulse?style=flat-square)](https://pypi.org/project/ErisPulse/)
59
60
 
60
61
  > 文档站:
@@ -203,4 +204,4 @@ epsdk run your_script.py --reload
203
204
 
204
205
  ---
205
206
 
206
- [加入社区讨论 →](https://github.com/ErisPulse/ErisPulse/discussions)
207
+ [加入社区讨论 →](https://github.com/ErisPulse/ErisPulse/discussions)
@@ -0,0 +1,13 @@
1
+ ErisPulse/__init__.py,sha256=2hEVWxKaDfFGAe3ekpUFx5tIub2riwDtSscsfpA0T2w,11108
2
+ ErisPulse/__main__.py,sha256=MQ_npNFErw5m8My092apQ4gyZAL-7VPLL9Wc7HTq4f4,56451
3
+ ErisPulse/adapter.py,sha256=sho8HMYVSa3syovU2mDxV2Wsw99yD5_sFz6UER89Tes,14367
4
+ ErisPulse/db.py,sha256=mSLLxjqOxSwvMbBSYCpH9TvCvdfccWrKJx6GtkhAl8U,23881
5
+ ErisPulse/logger.py,sha256=ftXp4bfk0S5cnkK4wmF5WqhvuzpUL4MXsuJa-ZTBoMs,8760
6
+ ErisPulse/mods.py,sha256=2OgueJPetQ5N1uDr5DiFvDZ4zF1HSuZ4OsL8IFDqro8,9976
7
+ ErisPulse/raiserr.py,sha256=6txXLfHmC9hb-HI1mbSMxaz1H0T4dfXGSrENRZ06AVg,4081
8
+ ErisPulse/util.py,sha256=eXtmW39bCjbV8lxOmOro4b4gyBhKo-db_EeffJ9BDf0,4525
9
+ erispulse-1.2.7.dist-info/METADATA,sha256=JgWp8A0StlIl102F5sDIz7W5ulBZgD0kUHze2ixdQU0,6721
10
+ erispulse-1.2.7.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
11
+ erispulse-1.2.7.dist-info/entry_points.txt,sha256=y8ppdsQhk-azC7_ikQgRr4rITSZ4VC4crVKtzHh4TBY,146
12
+ erispulse-1.2.7.dist-info/licenses/LICENSE,sha256=qAe8UGD2uYa8mUPqffBkdIS_4Q5d66FlhYuo3eC_Dq8,1396
13
+ erispulse-1.2.7.dist-info/RECORD,,
@@ -1,13 +0,0 @@
1
- ErisPulse/__init__.py,sha256=FSsMOuiXqMKDRuwX-V8doXorPpfZybHFV0KoSTwOQm8,11007
2
- ErisPulse/__main__.py,sha256=lFhd9Dn93G6z4ZjZJMEZDIBndy9J3msjdbzijDFrQfY,54056
3
- ErisPulse/adapter.py,sha256=rrBdPSHvOzzN0VJCD8lThygM9I-_iQIeZ5iMgqCJ34w,13977
4
- ErisPulse/db.py,sha256=LSIw6MpNtZ-P3deARLj8Umo06EBrwyuzhF4Nj1Lkbyc,23043
5
- ErisPulse/logger.py,sha256=UfQBF9fLx4WKe_se_lB5jNvaeTDtpv5PKT9x49QMmyw,8152
6
- ErisPulse/mods.py,sha256=1vEFiuL61Ouu7cocyysev5k2lGqcJ_hJGZqXNNbhJqg,9936
7
- ErisPulse/raiserr.py,sha256=QeKffL8Gm4Vl1DDMFQiKluiKCx0mxgN2Jj98WP4tUHo,3958
8
- ErisPulse/util.py,sha256=tmmZA4Ef5ElB01KZg2fTZLrkZOJbORjnkAd8sXj7xqw,4335
9
- erispulse-1.2.4.dist-info/METADATA,sha256=S3C1tvm2P5Uws5RbF4rvzPJoIBR_KlzSgLoWKkgaIV8,6776
10
- erispulse-1.2.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
11
- erispulse-1.2.4.dist-info/entry_points.txt,sha256=y8ppdsQhk-azC7_ikQgRr4rITSZ4VC4crVKtzHh4TBY,146
12
- erispulse-1.2.4.dist-info/licenses/LICENSE,sha256=qAe8UGD2uYa8mUPqffBkdIS_4Q5d66FlhYuo3eC_Dq8,1396
13
- erispulse-1.2.4.dist-info/RECORD,,