ErisPulse 2.1.13rc1__py3-none-any.whl → 2.1.13rc3__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/__main__.py +195 -35
- {erispulse-2.1.13rc1.dist-info → erispulse-2.1.13rc3.dist-info}/METADATA +1 -1
- {erispulse-2.1.13rc1.dist-info → erispulse-2.1.13rc3.dist-info}/RECORD +6 -6
- {erispulse-2.1.13rc1.dist-info → erispulse-2.1.13rc3.dist-info}/WHEEL +0 -0
- {erispulse-2.1.13rc1.dist-info → erispulse-2.1.13rc3.dist-info}/entry_points.txt +0 -0
- {erispulse-2.1.13rc1.dist-info → erispulse-2.1.13rc3.dist-info}/licenses/LICENSE +0 -0
ErisPulse/__main__.py
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
1
|
"""
|
|
3
2
|
ErisPulse SDK 命令行工具
|
|
4
3
|
|
|
5
|
-
|
|
4
|
+
提供ErisPulse生态系统的包管理、模块控制和开发工具功能。
|
|
5
|
+
|
|
6
|
+
{!--< tips >!--}
|
|
7
|
+
1. 需要Python 3.8+环境
|
|
8
|
+
2. Windows平台需要colorama支持ANSI颜色
|
|
9
|
+
{!--< /tips >!--}
|
|
6
10
|
"""
|
|
7
11
|
|
|
8
12
|
import argparse
|
|
@@ -33,16 +37,20 @@ from rich.layout import Layout
|
|
|
33
37
|
from rich.live import Live
|
|
34
38
|
from rich.markdown import Markdown
|
|
35
39
|
from rich.highlighter import RegexHighlighter
|
|
36
|
-
from rich.logging import RichHandler
|
|
37
40
|
|
|
38
41
|
# 确保在Windows上启用颜色
|
|
39
42
|
if sys.platform == "win32":
|
|
40
43
|
from colorama import init
|
|
41
44
|
init()
|
|
42
45
|
|
|
43
|
-
# 自定义高亮器
|
|
44
46
|
class CommandHighlighter(RegexHighlighter):
|
|
45
|
-
"""
|
|
47
|
+
"""
|
|
48
|
+
高亮CLI命令和参数
|
|
49
|
+
|
|
50
|
+
{!--< tips >!--}
|
|
51
|
+
使用正则表达式匹配命令行参数和选项
|
|
52
|
+
{!--< /tips >!--}
|
|
53
|
+
"""
|
|
46
54
|
highlights = [
|
|
47
55
|
r"(?P<switch>\-\-?\w+)",
|
|
48
56
|
r"(?P<option>\[\w+\])",
|
|
@@ -79,7 +87,12 @@ class PackageManager:
|
|
|
79
87
|
"""
|
|
80
88
|
ErisPulse包管理器
|
|
81
89
|
|
|
82
|
-
|
|
90
|
+
提供包安装、卸载、升级和查询功能
|
|
91
|
+
|
|
92
|
+
{!--< tips >!--}
|
|
93
|
+
1. 支持本地和远程包管理
|
|
94
|
+
2. 包含1小时缓存机制
|
|
95
|
+
{!--< /tips >!--}
|
|
83
96
|
"""
|
|
84
97
|
REMOTE_SOURCES = [
|
|
85
98
|
"https://erisdev.com/packages.json",
|
|
@@ -89,11 +102,20 @@ class PackageManager:
|
|
|
89
102
|
CACHE_EXPIRY = 3600 # 1小时缓存
|
|
90
103
|
|
|
91
104
|
def __init__(self):
|
|
105
|
+
"""初始化包管理器"""
|
|
92
106
|
self._cache = {}
|
|
93
107
|
self._cache_time = {}
|
|
94
108
|
|
|
95
109
|
async def _fetch_remote_packages(self, url: str) -> Optional[dict]:
|
|
96
|
-
"""
|
|
110
|
+
"""
|
|
111
|
+
从指定URL获取远程包数据
|
|
112
|
+
|
|
113
|
+
:param url: 远程包数据URL
|
|
114
|
+
:return: 解析后的JSON数据,失败返回None
|
|
115
|
+
|
|
116
|
+
:raises ClientError: 网络请求失败时抛出
|
|
117
|
+
:raises JSONDecodeError: JSON解析失败时抛出
|
|
118
|
+
"""
|
|
97
119
|
import aiohttp
|
|
98
120
|
from aiohttp import ClientError, ClientTimeout
|
|
99
121
|
|
|
@@ -114,6 +136,13 @@ class PackageManager:
|
|
|
114
136
|
|
|
115
137
|
:param force_refresh: 是否强制刷新缓存
|
|
116
138
|
:return: 包含模块和适配器的字典
|
|
139
|
+
|
|
140
|
+
:return:
|
|
141
|
+
dict: {
|
|
142
|
+
"modules": {模块名: 模块信息},
|
|
143
|
+
"adapters": {适配器名: 适配器信息},
|
|
144
|
+
"cli_extensions": {扩展名: 扩展信息}
|
|
145
|
+
}
|
|
117
146
|
"""
|
|
118
147
|
# 检查缓存
|
|
119
148
|
cache_key = "remote_packages"
|
|
@@ -143,6 +172,13 @@ class PackageManager:
|
|
|
143
172
|
获取已安装的包信息
|
|
144
173
|
|
|
145
174
|
:return: 已安装包字典,包含模块、适配器和CLI扩展
|
|
175
|
+
|
|
176
|
+
:return:
|
|
177
|
+
dict: {
|
|
178
|
+
"modules": {模块名: 模块信息},
|
|
179
|
+
"adapters": {适配器名: 适配器信息},
|
|
180
|
+
"cli_extensions": {扩展名: 扩展信息}
|
|
181
|
+
}
|
|
146
182
|
"""
|
|
147
183
|
packages = {
|
|
148
184
|
"modules": {},
|
|
@@ -193,7 +229,14 @@ class PackageManager:
|
|
|
193
229
|
return packages
|
|
194
230
|
|
|
195
231
|
def _is_module_enabled(self, module_name: str) -> bool:
|
|
196
|
-
"""
|
|
232
|
+
"""
|
|
233
|
+
检查模块是否启用
|
|
234
|
+
|
|
235
|
+
:param module_name: 模块名称
|
|
236
|
+
:return: 模块是否启用
|
|
237
|
+
|
|
238
|
+
:raises ImportError: 核心模块不可用时抛出
|
|
239
|
+
"""
|
|
197
240
|
try:
|
|
198
241
|
from ErisPulse.Core import mods
|
|
199
242
|
return mods.get_module_status(module_name)
|
|
@@ -203,7 +246,13 @@ class PackageManager:
|
|
|
203
246
|
return False
|
|
204
247
|
|
|
205
248
|
def _run_pip_command(self, args: List[str], description: str) -> bool:
|
|
206
|
-
"""
|
|
249
|
+
"""
|
|
250
|
+
执行pip命令
|
|
251
|
+
|
|
252
|
+
:param args: pip命令参数列表
|
|
253
|
+
:param description: 进度条描述
|
|
254
|
+
:return: 命令是否成功执行
|
|
255
|
+
"""
|
|
207
256
|
with Progress(
|
|
208
257
|
TextColumn(f"[progress.description]{description}"),
|
|
209
258
|
BarColumn(complete_style="progress.download"),
|
|
@@ -277,6 +326,8 @@ class PackageManager:
|
|
|
277
326
|
升级所有已安装的ErisPulse包
|
|
278
327
|
|
|
279
328
|
:return: 升级是否成功
|
|
329
|
+
|
|
330
|
+
:raises KeyboardInterrupt: 用户取消操作时抛出
|
|
280
331
|
"""
|
|
281
332
|
installed = self.get_installed_packages()
|
|
282
333
|
all_packages = set()
|
|
@@ -315,11 +366,23 @@ class PackageManager:
|
|
|
315
366
|
|
|
316
367
|
class ReloadHandler(FileSystemEventHandler):
|
|
317
368
|
"""
|
|
318
|
-
|
|
369
|
+
文件系统事件处理器
|
|
319
370
|
|
|
320
|
-
|
|
371
|
+
实现热重载功能,监控文件变化并重启进程
|
|
372
|
+
|
|
373
|
+
{!--< tips >!--}
|
|
374
|
+
1. 支持.py文件修改重载
|
|
375
|
+
2. 支持配置文件修改重载
|
|
376
|
+
{!--< /tips >!--}
|
|
321
377
|
"""
|
|
378
|
+
|
|
322
379
|
def __init__(self, script_path: str, reload_mode: bool = False):
|
|
380
|
+
"""
|
|
381
|
+
初始化处理器
|
|
382
|
+
|
|
383
|
+
:param script_path: 要监控的脚本路径
|
|
384
|
+
:param reload_mode: 是否启用重载模式
|
|
385
|
+
"""
|
|
323
386
|
super().__init__()
|
|
324
387
|
self.script_path = os.path.abspath(script_path)
|
|
325
388
|
self.process = None
|
|
@@ -329,7 +392,7 @@ class ReloadHandler(FileSystemEventHandler):
|
|
|
329
392
|
self.watched_files = set()
|
|
330
393
|
|
|
331
394
|
def start_process(self):
|
|
332
|
-
"""
|
|
395
|
+
"""启动监控进程"""
|
|
333
396
|
if self.process:
|
|
334
397
|
self._terminate_process()
|
|
335
398
|
|
|
@@ -347,7 +410,11 @@ class ReloadHandler(FileSystemEventHandler):
|
|
|
347
410
|
raise
|
|
348
411
|
|
|
349
412
|
def _terminate_process(self):
|
|
350
|
-
"""
|
|
413
|
+
"""
|
|
414
|
+
终止当前进程
|
|
415
|
+
|
|
416
|
+
:raises subprocess.TimeoutExpired: 进程终止超时时抛出
|
|
417
|
+
"""
|
|
351
418
|
try:
|
|
352
419
|
self.process.terminate()
|
|
353
420
|
# 等待最多2秒让进程正常退出
|
|
@@ -360,7 +427,11 @@ class ReloadHandler(FileSystemEventHandler):
|
|
|
360
427
|
console.print(f"[error]终止进程时出错: {e}[/]")
|
|
361
428
|
|
|
362
429
|
def on_modified(self, event):
|
|
363
|
-
"""
|
|
430
|
+
"""
|
|
431
|
+
文件修改事件处理
|
|
432
|
+
|
|
433
|
+
:param event: 文件系统事件
|
|
434
|
+
"""
|
|
364
435
|
now = time.time()
|
|
365
436
|
if now - self.last_reload < 1.0: # 防抖
|
|
366
437
|
return
|
|
@@ -371,22 +442,41 @@ class ReloadHandler(FileSystemEventHandler):
|
|
|
371
442
|
self._handle_reload(event, "配置变动")
|
|
372
443
|
|
|
373
444
|
def _handle_reload(self, event, reason: str):
|
|
374
|
-
"""
|
|
445
|
+
"""
|
|
446
|
+
处理重载逻辑
|
|
447
|
+
|
|
448
|
+
:param event: 文件系统事件
|
|
449
|
+
:param reason: 重载原因描述
|
|
450
|
+
"""
|
|
375
451
|
console.print(f"\n[reload]{reason}: [path]{event.src_path}[/][/]")
|
|
376
452
|
self._terminate_process()
|
|
377
453
|
self.start_process()
|
|
378
454
|
|
|
379
455
|
class CLI:
|
|
380
|
-
"""
|
|
456
|
+
"""
|
|
457
|
+
ErisPulse命令行接口
|
|
458
|
+
|
|
459
|
+
提供完整的命令行交互功能
|
|
460
|
+
|
|
461
|
+
{!--< tips >!--}
|
|
462
|
+
1. 支持动态加载第三方命令
|
|
463
|
+
2. 支持模块化子命令系统
|
|
464
|
+
{!--< /tips >!--}
|
|
465
|
+
"""
|
|
381
466
|
|
|
382
467
|
def __init__(self):
|
|
468
|
+
"""初始化CLI"""
|
|
383
469
|
self.parser = self._create_parser()
|
|
384
470
|
self.package_manager = PackageManager()
|
|
385
471
|
self.observer = None
|
|
386
472
|
self.handler = None
|
|
387
473
|
|
|
388
474
|
def _create_parser(self) -> argparse.ArgumentParser:
|
|
389
|
-
"""
|
|
475
|
+
"""
|
|
476
|
+
创建命令行参数解析器
|
|
477
|
+
|
|
478
|
+
:return: 配置好的ArgumentParser实例
|
|
479
|
+
"""
|
|
390
480
|
parser = argparse.ArgumentParser(
|
|
391
481
|
prog="epsdk",
|
|
392
482
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
@@ -562,8 +652,30 @@ class CLI:
|
|
|
562
652
|
|
|
563
653
|
return parser
|
|
564
654
|
|
|
655
|
+
def _get_external_commands(self) -> List[str]:
|
|
656
|
+
"""
|
|
657
|
+
获取所有已注册的第三方命令名称
|
|
658
|
+
|
|
659
|
+
:return: 第三方命令名称列表
|
|
660
|
+
"""
|
|
661
|
+
try:
|
|
662
|
+
entry_points = importlib.metadata.entry_points()
|
|
663
|
+
if hasattr(entry_points, 'select'):
|
|
664
|
+
cli_entries = entry_points.select(group='erispulse.cli')
|
|
665
|
+
else:
|
|
666
|
+
cli_entries = entry_points.get('erispulse.cli', [])
|
|
667
|
+
return [entry.name for entry in cli_entries]
|
|
668
|
+
except Exception:
|
|
669
|
+
return []
|
|
670
|
+
|
|
565
671
|
def _load_external_commands(self, subparsers):
|
|
566
|
-
"""
|
|
672
|
+
"""
|
|
673
|
+
加载第三方CLI命令
|
|
674
|
+
|
|
675
|
+
:param subparsers: 子命令解析器
|
|
676
|
+
|
|
677
|
+
:raises ImportError: 加载命令失败时抛出
|
|
678
|
+
"""
|
|
567
679
|
try:
|
|
568
680
|
entry_points = importlib.metadata.entry_points()
|
|
569
681
|
if hasattr(entry_points, 'select'):
|
|
@@ -593,7 +705,12 @@ class CLI:
|
|
|
593
705
|
))
|
|
594
706
|
|
|
595
707
|
def _print_installed_packages(self, pkg_type: str, outdated_only: bool = False):
|
|
596
|
-
"""
|
|
708
|
+
"""
|
|
709
|
+
打印已安装包信息
|
|
710
|
+
|
|
711
|
+
:param pkg_type: 包类型 (modules/adapters/cli/all)
|
|
712
|
+
:param outdated_only: 是否只显示可升级的包
|
|
713
|
+
"""
|
|
597
714
|
installed = self.package_manager.get_installed_packages()
|
|
598
715
|
|
|
599
716
|
if pkg_type == "modules" and installed["modules"]:
|
|
@@ -672,7 +789,11 @@ class CLI:
|
|
|
672
789
|
console.print(table)
|
|
673
790
|
|
|
674
791
|
def _print_remote_packages(self, pkg_type: str):
|
|
675
|
-
"""
|
|
792
|
+
"""
|
|
793
|
+
打印远程包信息
|
|
794
|
+
|
|
795
|
+
:param pkg_type: 包类型 (modules/adapters/cli/all)
|
|
796
|
+
"""
|
|
676
797
|
remote_packages = asyncio.run(self.package_manager.get_remote_packages())
|
|
677
798
|
|
|
678
799
|
if pkg_type == "modules" and remote_packages["modules"]:
|
|
@@ -739,7 +860,13 @@ class CLI:
|
|
|
739
860
|
console.print(table)
|
|
740
861
|
|
|
741
862
|
def _is_package_outdated(self, package_name: str, current_version: str) -> bool:
|
|
742
|
-
"""
|
|
863
|
+
"""
|
|
864
|
+
检查包是否过时
|
|
865
|
+
|
|
866
|
+
:param package_name: 包名
|
|
867
|
+
:param current_version: 当前版本
|
|
868
|
+
:return: 是否有新版本可用
|
|
869
|
+
"""
|
|
743
870
|
remote_packages = asyncio.run(self.package_manager.get_remote_packages())
|
|
744
871
|
|
|
745
872
|
# 检查模块
|
|
@@ -760,7 +887,12 @@ class CLI:
|
|
|
760
887
|
return False
|
|
761
888
|
|
|
762
889
|
def _resolve_package_name(self, short_name: str) -> Optional[str]:
|
|
763
|
-
"""
|
|
890
|
+
"""
|
|
891
|
+
解析简称到完整包名
|
|
892
|
+
|
|
893
|
+
:param short_name: 模块/适配器简称
|
|
894
|
+
:return: 完整包名,未找到返回None
|
|
895
|
+
"""
|
|
764
896
|
remote_packages = asyncio.run(self.package_manager.get_remote_packages())
|
|
765
897
|
|
|
766
898
|
# 检查模块
|
|
@@ -774,7 +906,12 @@ class CLI:
|
|
|
774
906
|
return None
|
|
775
907
|
|
|
776
908
|
def _setup_watchdog(self, script_path: str, reload_mode: bool):
|
|
777
|
-
"""
|
|
909
|
+
"""
|
|
910
|
+
设置文件监控
|
|
911
|
+
|
|
912
|
+
:param script_path: 要监控的脚本路径
|
|
913
|
+
:param reload_mode: 是否启用重载模式
|
|
914
|
+
"""
|
|
778
915
|
watch_dirs = [
|
|
779
916
|
os.path.dirname(os.path.abspath(script_path)),
|
|
780
917
|
]
|
|
@@ -814,17 +951,13 @@ class CLI:
|
|
|
814
951
|
self.observer.join()
|
|
815
952
|
|
|
816
953
|
def run(self):
|
|
817
|
-
"""
|
|
818
|
-
|
|
954
|
+
"""
|
|
955
|
+
运行CLI
|
|
819
956
|
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
level=logging.DEBUG,
|
|
825
|
-
format="%(message)s",
|
|
826
|
-
handlers=[RichHandler(console=console)]
|
|
827
|
-
)
|
|
957
|
+
:raises KeyboardInterrupt: 用户中断时抛出
|
|
958
|
+
:raises Exception: 命令执行失败时抛出
|
|
959
|
+
"""
|
|
960
|
+
args = self.parser.parse_args()
|
|
828
961
|
|
|
829
962
|
if args.version:
|
|
830
963
|
self._print_version()
|
|
@@ -910,9 +1043,29 @@ class CLI:
|
|
|
910
1043
|
|
|
911
1044
|
elif args.command == "init":
|
|
912
1045
|
from ErisPulse import sdk
|
|
913
|
-
sdk.init(
|
|
1046
|
+
sdk.init()
|
|
914
1047
|
console.print("[success]ErisPulse项目初始化完成[/]")
|
|
915
1048
|
|
|
1049
|
+
# 处理第三方命令
|
|
1050
|
+
elif args.command in self._get_external_commands():
|
|
1051
|
+
# 获取第三方命令的处理函数并执行
|
|
1052
|
+
entry_points = importlib.metadata.entry_points()
|
|
1053
|
+
if hasattr(entry_points, 'select'):
|
|
1054
|
+
cli_entries = entry_points.select(group='erispulse.cli')
|
|
1055
|
+
else:
|
|
1056
|
+
cli_entries = entry_points.get('erispulse.cli', [])
|
|
1057
|
+
|
|
1058
|
+
for entry in cli_entries:
|
|
1059
|
+
if entry.name == args.command:
|
|
1060
|
+
cli_func = entry.load()
|
|
1061
|
+
if callable(cli_func):
|
|
1062
|
+
# 创建一个新的解析器来解析第三方命令的参数
|
|
1063
|
+
subparser = self.parser._subparsers._group_actions[0].choices[args.command]
|
|
1064
|
+
parsed_args = subparser.parse_args(sys.argv[2:])
|
|
1065
|
+
# 调用第三方命令处理函数
|
|
1066
|
+
parsed_args.func(parsed_args)
|
|
1067
|
+
break
|
|
1068
|
+
|
|
916
1069
|
except KeyboardInterrupt:
|
|
917
1070
|
console.print("\n[warning]操作被用户中断[/]")
|
|
918
1071
|
self._cleanup()
|
|
@@ -925,7 +1078,14 @@ class CLI:
|
|
|
925
1078
|
sys.exit(1)
|
|
926
1079
|
|
|
927
1080
|
def main():
|
|
928
|
-
"""
|
|
1081
|
+
"""
|
|
1082
|
+
CLI入口点
|
|
1083
|
+
|
|
1084
|
+
{!--< tips >!--}
|
|
1085
|
+
1. 创建CLI实例并运行
|
|
1086
|
+
2. 处理全局异常
|
|
1087
|
+
{!--< /tips >!--}
|
|
1088
|
+
"""
|
|
929
1089
|
cli = CLI()
|
|
930
1090
|
cli.run()
|
|
931
1091
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
ErisPulse/__init__.py,sha256=T-N56UQyBmpvlqwH2wGi5ptPzaJpbgF5tKkJt0DlkaM,26099
|
|
2
|
-
ErisPulse/__main__.py,sha256=
|
|
2
|
+
ErisPulse/__main__.py,sha256=kGpk-BeztjhrdNwWL2mZxaVy05y4XicCS6SZGtQERho,37409
|
|
3
3
|
ErisPulse/Core/__init__.py,sha256=tBYPahQ7-w7U6M69xy8DW0_ECa9ja-Q0y_SQqVswYBo,409
|
|
4
4
|
ErisPulse/Core/adapter.py,sha256=ZK81dibJ471FowL0MRXkS113iBcMgj_VzpTw0PzhAEo,18102
|
|
5
5
|
ErisPulse/Core/config.py,sha256=ZmwGdtHSOE7K5uOGzLYcyl3ZF3sAmeWAntqcdfDzhpM,5027
|
|
@@ -9,8 +9,8 @@ ErisPulse/Core/mods.py,sha256=2yIq8t9Ca9CBPRiZU0yr8Lc0XGmmkB7LlH-5FWqXjw4,7023
|
|
|
9
9
|
ErisPulse/Core/raiserr.py,sha256=vlyaaiOIYkyqm9dAqSW9E54JBzX-9roHDp5_r6I0yUU,5591
|
|
10
10
|
ErisPulse/Core/server.py,sha256=FkDTeLuHD5IBnWVxvYU8pHb6yCt8GzyvC1bpOiJ7G7I,9217
|
|
11
11
|
ErisPulse/Core/util.py,sha256=7rdMmn6sBFqYd4znxBCcJjuv2eyTExdeKyZopgds868,3796
|
|
12
|
-
erispulse-2.1.
|
|
13
|
-
erispulse-2.1.
|
|
14
|
-
erispulse-2.1.
|
|
15
|
-
erispulse-2.1.
|
|
16
|
-
erispulse-2.1.
|
|
12
|
+
erispulse-2.1.13rc3.dist-info/METADATA,sha256=ppMW2h_uDFhvpfP9u30vbaHgQA9fr_oPdDzeWaLQRf4,6262
|
|
13
|
+
erispulse-2.1.13rc3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
14
|
+
erispulse-2.1.13rc3.dist-info/entry_points.txt,sha256=Jss71M6nEha0TA-DyVZugPYdcL14s9QpiOeIlgWxzOc,182
|
|
15
|
+
erispulse-2.1.13rc3.dist-info/licenses/LICENSE,sha256=4jyqikiB0G0n06CEEMMTzTXjE4IShghSlB74skMSPQs,1464
|
|
16
|
+
erispulse-2.1.13rc3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|