ErisPulse 2.3.9.dev3__tar.gz → 2.4.0.dev3__tar.gz
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-2.3.9.dev3 → erispulse-2.4.0.dev3}/PKG-INFO +10 -1
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/README.md +2 -1
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/pyproject.toml +10 -1
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/CLI/cli.py +7 -1
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/CLI/commands/install.py +200 -24
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/CLI/commands/install.pyi +2 -12
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/CLI/utils/package_manager.py +35 -4
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/CLI/utils/package_manager.pyi +11 -1
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/Core/Bases/adapter.py +166 -118
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/Core/Bases/adapter.pyi +22 -10
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/Core/Bases/manager.py +38 -40
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/Core/Bases/manager.pyi +5 -5
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/Core/Bases/module.py +22 -20
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/Core/Bases/module.pyi +4 -3
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/Core/Event/__init__.py +15 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/Core/Event/__init__.pyi +2 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/Core/Event/base.py +48 -27
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/Core/Event/base.pyi +5 -1
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/Core/Event/command.py +190 -153
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/Core/Event/command.pyi +9 -8
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/Core/Event/message.py +43 -29
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/Core/Event/message.pyi +2 -1
- erispulse-2.4.0.dev3/src/ErisPulse/Core/Event/message_builder.py +270 -0
- erispulse-2.4.0.dev3/src/ErisPulse/Core/Event/message_builder.pyi +163 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/Core/Event/meta.py +39 -28
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/Core/Event/meta.pyi +2 -1
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/Core/Event/notice.py +47 -34
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/Core/Event/notice.pyi +2 -1
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/Core/Event/request.py +32 -23
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/Core/Event/request.pyi +2 -1
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/Core/Event/session_type.py +92 -81
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/Core/Event/session_type.pyi +36 -21
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/Core/Event/wrapper.py +341 -108
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/Core/Event/wrapper.pyi +142 -18
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/Core/__init__.py +2 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/Core/__init__.pyi +1 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/Core/adapter.py +370 -118
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/Core/adapter.pyi +80 -12
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/Core/config.py +31 -25
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/Core/config.pyi +6 -2
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/Core/lifecycle.py +65 -47
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/Core/lifecycle.pyi +4 -3
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/Core/logger.py +42 -102
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/Core/logger.pyi +22 -41
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/Core/module.py +128 -125
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/Core/module.pyi +16 -16
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/Core/router.py +128 -108
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/Core/router.pyi +18 -11
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/Core/storage.py +174 -146
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/Core/storage.pyi +22 -8
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/finders/bases/finder.py +51 -50
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/finders/bases/finder.pyi +2 -1
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/loaders/adapter.py +87 -79
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/loaders/adapter.pyi +14 -14
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/loaders/bases/loader.py +48 -45
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/loaders/bases/loader.pyi +1 -1
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/loaders/module.py +413 -293
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/loaders/module.pyi +19 -19
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/loaders/strategy.py +29 -29
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/loaders/strategy.pyi +5 -3
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/runtime/frame_config.py +4 -4
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/runtime/frame_config.pyi +2 -2
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/sdk.py +103 -37
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/sdk.pyi +2 -2
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/.gitignore +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/LICENSE +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/CLI/__init__.py +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/CLI/__init__.pyi +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/CLI/base.py +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/CLI/base.pyi +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/CLI/cli.pyi +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/CLI/commands/__init__.py +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/CLI/commands/__init__.pyi +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/CLI/commands/init.py +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/CLI/commands/init.pyi +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/CLI/commands/list.py +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/CLI/commands/list.pyi +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/CLI/commands/list_remote.py +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/CLI/commands/list_remote.pyi +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/CLI/commands/run.py +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/CLI/commands/run.pyi +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/CLI/commands/self_update.py +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/CLI/commands/self_update.pyi +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/CLI/commands/uninstall.py +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/CLI/commands/uninstall.pyi +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/CLI/commands/upgrade.py +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/CLI/commands/upgrade.pyi +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/CLI/console.py +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/CLI/console.pyi +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/CLI/registry.py +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/CLI/registry.pyi +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/CLI/utils/__init__.py +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/CLI/utils/__init__.pyi +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/Core/Bases/__init__.py +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/Core/Bases/__init__.pyi +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/__init__.py +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/__init__.pyi +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/__main__.py +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/__main__.pyi +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/finders/__init__.py +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/finders/__init__.pyi +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/finders/adapter.py +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/finders/adapter.pyi +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/finders/bases/__init__.py +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/finders/bases/__init__.pyi +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/finders/cli.py +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/finders/cli.pyi +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/finders/module.py +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/finders/module.pyi +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/loaders/__init__.py +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/loaders/__init__.pyi +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/loaders/bases/__init__.py +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/loaders/bases/__init__.pyi +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/runtime/__init__.py +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/runtime/__init__.pyi +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/runtime/cleanup.py +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/runtime/cleanup.pyi +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/runtime/exceptions.py +0 -0
- {erispulse-2.3.9.dev3 → erispulse-2.4.0.dev3}/src/ErisPulse/runtime/exceptions.pyi +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ErisPulse
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.4.0.dev3
|
|
4
4
|
Summary: ErisPulse 是一个模块化、可扩展的异步 Python SDK 框架,主要用于构建高效、可维护的机器人应用程序。
|
|
5
5
|
Author-email: ErisDev <erisdev@88.com>
|
|
6
6
|
Maintainer-email: "艾莉丝·格雷拉特(WSu2059)" <wsu2059@qq.com>
|
|
@@ -50,6 +50,14 @@ Requires-Dist: pip>=23.0
|
|
|
50
50
|
Requires-Dist: rich>=13.0.0
|
|
51
51
|
Requires-Dist: toml>=0.10.2
|
|
52
52
|
Requires-Dist: watchdog>=4.0.0
|
|
53
|
+
Provides-Extra: dev
|
|
54
|
+
Requires-Dist: pyclean>=3.6.0; extra == 'dev'
|
|
55
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
|
|
56
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
|
|
57
|
+
Requires-Dist: pytest-mock>=3.10.0; extra == 'dev'
|
|
58
|
+
Requires-Dist: pytest-xdist>=3.0.0; extra == 'dev'
|
|
59
|
+
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
60
|
+
Requires-Dist: ruff>=0.1.7; extra == 'dev'
|
|
53
61
|
Provides-Extra: test
|
|
54
62
|
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'test'
|
|
55
63
|
Requires-Dist: pytest-cov>=4.0.0; extra == 'test'
|
|
@@ -205,6 +213,7 @@ epsdk run main.py --reload
|
|
|
205
213
|
- [OneBot12](https://github.com/ErisPulse/ErisPulse-OneBot12Adapter) - OneBot12 标准
|
|
206
214
|
- [邮件](https://github.com/ErisPulse/ErisPulse-EmailAdapter) - 邮件收发处理
|
|
207
215
|
- [沙箱](https://github.com/ErisPulse/ErisPulse-SandboxAdapter) - 网页调试界面,无需接入实际平台
|
|
216
|
+
- [Kook](https://github.com/shanfishapp/ErisPulse-KookAdapter) - Kook(开黑啦)即时通讯平台
|
|
208
217
|
|
|
209
218
|
查看 [适配器详情介绍](docs/zh-CN/platform-guide/README.md)
|
|
210
219
|
|
|
@@ -144,7 +144,8 @@ epsdk run main.py --reload
|
|
|
144
144
|
- [OneBot11](https://github.com/ErisPulse/ErisPulse-OneBot11Adapter) - 通用机器人接口标准
|
|
145
145
|
- [OneBot12](https://github.com/ErisPulse/ErisPulse-OneBot12Adapter) - OneBot12 标准
|
|
146
146
|
- [邮件](https://github.com/ErisPulse/ErisPulse-EmailAdapter) - 邮件收发处理
|
|
147
|
-
- [沙箱](https://github.com/ErisPulse/ErisPulse-SandboxAdapter) - 网页调试界面,无需接入实际平台
|
|
147
|
+
- [沙箱](https://github.com/ErisPulse/ErisPulse-SandboxAdapter) - 网页调试界面,无需接入实际平台
|
|
148
|
+
- [Kook](https://github.com/shanfishapp/ErisPulse-KookAdapter) - Kook(开黑啦)即时通讯平台
|
|
148
149
|
|
|
149
150
|
查看 [适配器详情介绍](docs/zh-CN/platform-guide/README.md)
|
|
150
151
|
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "ErisPulse"
|
|
7
|
-
version = "2.
|
|
7
|
+
version = "2.4.0-dev.3"
|
|
8
8
|
description = "ErisPulse 是一个模块化、可扩展的异步 Python SDK 框架,主要用于构建高效、可维护的机器人应用程序。"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -67,6 +67,15 @@ test = [
|
|
|
67
67
|
"pytest-xdist>=3.0.0",
|
|
68
68
|
"pytest-mock>=3.10.0",
|
|
69
69
|
]
|
|
70
|
+
dev = [
|
|
71
|
+
"pytest>=7.0.0",
|
|
72
|
+
"pytest-cov>=4.0.0",
|
|
73
|
+
"pytest-asyncio>=0.21.0",
|
|
74
|
+
"pytest-xdist>=3.0.0",
|
|
75
|
+
"pytest-mock>=3.10.0",
|
|
76
|
+
"pyclean>=3.6.0",
|
|
77
|
+
"ruff>=0.1.7",
|
|
78
|
+
]
|
|
70
79
|
|
|
71
80
|
[project.scripts]
|
|
72
81
|
ep-init = "ErisPulse.__init__:init_sync"
|
|
@@ -168,7 +168,8 @@ class CLI:
|
|
|
168
168
|
:raises KeyboardInterrupt: 用户中断时抛出
|
|
169
169
|
:raises Exception: 命令执行失败时抛出
|
|
170
170
|
"""
|
|
171
|
-
args = self.parser.
|
|
171
|
+
args, unknown = self.parser.parse_known_args()
|
|
172
|
+
args._unknown_args = unknown
|
|
172
173
|
|
|
173
174
|
# 处理版本选项
|
|
174
175
|
if args.version:
|
|
@@ -177,9 +178,14 @@ class CLI:
|
|
|
177
178
|
|
|
178
179
|
# 没有指定命令时显示帮助
|
|
179
180
|
if not args.command:
|
|
181
|
+
if unknown:
|
|
182
|
+
console.print(f"[warning]未识别的参数: {' '.join(unknown)}[/]")
|
|
180
183
|
self.parser.print_help()
|
|
181
184
|
return
|
|
182
185
|
|
|
186
|
+
if unknown and args.command not in ('install',):
|
|
187
|
+
console.print(f"[warning]未识别的参数: {' '.join(unknown)}[/]")
|
|
188
|
+
|
|
183
189
|
try:
|
|
184
190
|
# 执行命令
|
|
185
191
|
command = self.registry.get(args.command)
|
|
@@ -41,19 +41,211 @@ class InstallCommand(Command):
|
|
|
41
41
|
action='store_true',
|
|
42
42
|
help='包含预发布版本'
|
|
43
43
|
)
|
|
44
|
+
parser.add_argument(
|
|
45
|
+
'-e', '--editable',
|
|
46
|
+
action='append',
|
|
47
|
+
metavar='PATH',
|
|
48
|
+
help='以可编辑模式安装包(开发者模式,可多次指定)'
|
|
49
|
+
)
|
|
50
|
+
parser.add_argument(
|
|
51
|
+
'--user',
|
|
52
|
+
action='store_true',
|
|
53
|
+
help='安装到用户目录'
|
|
54
|
+
)
|
|
55
|
+
parser.add_argument(
|
|
56
|
+
'--no-deps',
|
|
57
|
+
action='store_true',
|
|
58
|
+
help='不安装依赖包'
|
|
59
|
+
)
|
|
60
|
+
parser.add_argument(
|
|
61
|
+
'-t', '--target',
|
|
62
|
+
metavar='DIR',
|
|
63
|
+
help='安装到指定目录'
|
|
64
|
+
)
|
|
65
|
+
parser.add_argument(
|
|
66
|
+
'--index-url',
|
|
67
|
+
metavar='URL',
|
|
68
|
+
help='指定包索引 URL'
|
|
69
|
+
)
|
|
70
|
+
parser.add_argument(
|
|
71
|
+
'--extra-index-url',
|
|
72
|
+
action='append',
|
|
73
|
+
metavar='URL',
|
|
74
|
+
help='额外的包索引 URL(可多次指定)'
|
|
75
|
+
)
|
|
76
|
+
parser.add_argument(
|
|
77
|
+
'--no-cache-dir',
|
|
78
|
+
action='store_true',
|
|
79
|
+
help='禁用 pip 缓存'
|
|
80
|
+
)
|
|
81
|
+
parser.add_argument(
|
|
82
|
+
'-r', '--requirement',
|
|
83
|
+
metavar='FILE',
|
|
84
|
+
help='从 requirements 文件安装'
|
|
85
|
+
)
|
|
86
|
+
parser.add_argument(
|
|
87
|
+
'-c', '--constraint',
|
|
88
|
+
metavar='FILE',
|
|
89
|
+
help='使用约束文件限制版本'
|
|
90
|
+
)
|
|
91
|
+
parser.add_argument(
|
|
92
|
+
'--force-reinstall',
|
|
93
|
+
action='store_true',
|
|
94
|
+
help='强制重新安装所有包'
|
|
95
|
+
)
|
|
96
|
+
parser.add_argument(
|
|
97
|
+
'--ignore-installed',
|
|
98
|
+
action='store_true',
|
|
99
|
+
help='忽略已安装的包'
|
|
100
|
+
)
|
|
101
|
+
parser.add_argument(
|
|
102
|
+
'--compile',
|
|
103
|
+
action='store_true',
|
|
104
|
+
help='编译 Python 源文件'
|
|
105
|
+
)
|
|
106
|
+
parser.add_argument(
|
|
107
|
+
'--no-compile',
|
|
108
|
+
action='store_true',
|
|
109
|
+
help='不编译 Python 源文件'
|
|
110
|
+
)
|
|
111
|
+
parser.add_argument(
|
|
112
|
+
'--prefix',
|
|
113
|
+
metavar='DIR',
|
|
114
|
+
help='安装前缀目录'
|
|
115
|
+
)
|
|
116
|
+
parser.add_argument(
|
|
117
|
+
'--src',
|
|
118
|
+
metavar='DIR',
|
|
119
|
+
help='可编辑包的检出目录'
|
|
120
|
+
)
|
|
121
|
+
parser.add_argument(
|
|
122
|
+
'--config-settings',
|
|
123
|
+
action='append',
|
|
124
|
+
metavar='SETTINGS',
|
|
125
|
+
help='构建后端的配置设置(可多次指定)'
|
|
126
|
+
)
|
|
127
|
+
parser.add_argument(
|
|
128
|
+
'--no-binary',
|
|
129
|
+
action='append',
|
|
130
|
+
metavar='FORMAT',
|
|
131
|
+
help='不使用二进制包'
|
|
132
|
+
)
|
|
133
|
+
parser.add_argument(
|
|
134
|
+
'--only-binary',
|
|
135
|
+
action='append',
|
|
136
|
+
metavar='FORMAT',
|
|
137
|
+
help='只使用二进制包'
|
|
138
|
+
)
|
|
139
|
+
parser.add_argument(
|
|
140
|
+
'--prefer-binary',
|
|
141
|
+
action='store_true',
|
|
142
|
+
help='优先使用二进制包'
|
|
143
|
+
)
|
|
144
|
+
parser.add_argument(
|
|
145
|
+
'--build-isolation',
|
|
146
|
+
action='store_true',
|
|
147
|
+
help='启用构建隔离'
|
|
148
|
+
)
|
|
149
|
+
parser.add_argument(
|
|
150
|
+
'--no-build-isolation',
|
|
151
|
+
action='store_true',
|
|
152
|
+
help='禁用构建隔离'
|
|
153
|
+
)
|
|
154
|
+
parser.add_argument(
|
|
155
|
+
'--upgrade-strategy',
|
|
156
|
+
choices=['eager', 'only-if-needed', 'to-satisfy-only'],
|
|
157
|
+
help='升级策略'
|
|
158
|
+
)
|
|
159
|
+
parser.add_argument(
|
|
160
|
+
'--break-system-packages',
|
|
161
|
+
action='store_true',
|
|
162
|
+
help='允许覆盖系统管理的包'
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
def _build_extra_pip_args(self, args) -> list:
|
|
166
|
+
extra = []
|
|
167
|
+
if getattr(args, 'user', False):
|
|
168
|
+
extra.append('--user')
|
|
169
|
+
if getattr(args, 'no_deps', False):
|
|
170
|
+
extra.append('--no-deps')
|
|
171
|
+
if getattr(args, 'target', None):
|
|
172
|
+
extra.extend(['--target', args.target])
|
|
173
|
+
if getattr(args, 'index_url', None):
|
|
174
|
+
extra.extend(['--index-url', args.index_url])
|
|
175
|
+
if getattr(args, 'extra_index_url', None):
|
|
176
|
+
for url in args.extra_index_url:
|
|
177
|
+
extra.extend(['--extra-index-url', url])
|
|
178
|
+
if getattr(args, 'no_cache_dir', False):
|
|
179
|
+
extra.append('--no-cache-dir')
|
|
180
|
+
if getattr(args, 'constraint', None):
|
|
181
|
+
extra.extend(['--constraint', args.constraint])
|
|
182
|
+
if getattr(args, 'force_reinstall', False):
|
|
183
|
+
extra.append('--force-reinstall')
|
|
184
|
+
if getattr(args, 'ignore_installed', False):
|
|
185
|
+
extra.append('--ignore-installed')
|
|
186
|
+
if getattr(args, 'compile', False):
|
|
187
|
+
extra.append('--compile')
|
|
188
|
+
if getattr(args, 'no_compile', False):
|
|
189
|
+
extra.append('--no-compile')
|
|
190
|
+
if getattr(args, 'prefix', None):
|
|
191
|
+
extra.extend(['--prefix', args.prefix])
|
|
192
|
+
if getattr(args, 'src', None):
|
|
193
|
+
extra.extend(['--src', args.src])
|
|
194
|
+
if getattr(args, 'config_settings', None):
|
|
195
|
+
for settings in args.config_settings:
|
|
196
|
+
extra.extend(['--config-settings', settings])
|
|
197
|
+
if getattr(args, 'no_binary', None):
|
|
198
|
+
for fmt in args.no_binary:
|
|
199
|
+
extra.extend(['--no-binary', fmt])
|
|
200
|
+
if getattr(args, 'only_binary', None):
|
|
201
|
+
for fmt in args.only_binary:
|
|
202
|
+
extra.extend(['--only-binary', fmt])
|
|
203
|
+
if getattr(args, 'prefer_binary', False):
|
|
204
|
+
extra.append('--prefer-binary')
|
|
205
|
+
if getattr(args, 'build_isolation', False):
|
|
206
|
+
extra.append('--build-isolation')
|
|
207
|
+
if getattr(args, 'no_build_isolation', False):
|
|
208
|
+
extra.append('--no-build-isolation')
|
|
209
|
+
if getattr(args, 'upgrade_strategy', None):
|
|
210
|
+
extra.extend(['--upgrade-strategy', args.upgrade_strategy])
|
|
211
|
+
if getattr(args, 'break_system_packages', False):
|
|
212
|
+
extra.append('--break-system-packages')
|
|
213
|
+
|
|
214
|
+
unknown_args = getattr(args, '_unknown_args', []) or []
|
|
215
|
+
extra.extend(unknown_args)
|
|
216
|
+
|
|
217
|
+
return extra
|
|
44
218
|
|
|
45
219
|
def execute(self, args):
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
)
|
|
220
|
+
editable_paths = getattr(args, 'editable', None)
|
|
221
|
+
requirement_file = getattr(args, 'requirement', None)
|
|
222
|
+
|
|
223
|
+
if args.package or editable_paths or requirement_file:
|
|
224
|
+
success = True
|
|
225
|
+
pm = self.package_manager
|
|
226
|
+
extra = self._build_extra_pip_args(args)
|
|
227
|
+
|
|
228
|
+
if editable_paths:
|
|
229
|
+
for path in editable_paths:
|
|
230
|
+
if not pm.install_direct(['-e', path] + extra, f"可编辑安装 {path}"):
|
|
231
|
+
success = False
|
|
232
|
+
|
|
233
|
+
if requirement_file:
|
|
234
|
+
if not pm.install_direct(['-r', requirement_file] + extra, f"从文件安装 {requirement_file}"):
|
|
235
|
+
success = False
|
|
236
|
+
|
|
237
|
+
if args.package:
|
|
238
|
+
if not pm.install_package(
|
|
239
|
+
args.package,
|
|
240
|
+
upgrade=args.upgrade,
|
|
241
|
+
pre=args.pre,
|
|
242
|
+
extra_pip_args=extra
|
|
243
|
+
):
|
|
244
|
+
success = False
|
|
245
|
+
|
|
53
246
|
if not success:
|
|
54
247
|
sys.exit(1)
|
|
55
248
|
else:
|
|
56
|
-
# 交互式安装
|
|
57
249
|
self._interactive_install(args.upgrade, args.pre)
|
|
58
250
|
|
|
59
251
|
def _interactive_install(self, upgrade: bool = False, pre: bool = False):
|
|
@@ -70,7 +262,6 @@ class InstallCommand(Command):
|
|
|
70
262
|
border_style="cyan"
|
|
71
263
|
))
|
|
72
264
|
|
|
73
|
-
# 预加载远程包列表,避免每次选择都请求
|
|
74
265
|
console.print("[info]正在获取远程包列表...[/]")
|
|
75
266
|
remote_packages = asyncio.run(self.package_manager.get_remote_packages())
|
|
76
267
|
console.print("[success]远程包列表获取完成[/]")
|
|
@@ -103,12 +294,10 @@ class InstallCommand(Command):
|
|
|
103
294
|
elif choice == "4":
|
|
104
295
|
self._install_custom(upgrade, pre)
|
|
105
296
|
|
|
106
|
-
# 询问是否继续
|
|
107
297
|
if not Confirm.ask("\n[cyan]是否继续安装其他组件?[/cyan]", default=False):
|
|
108
298
|
break
|
|
109
299
|
|
|
110
300
|
def _install_adapters(self, remote_packages: dict, upgrade: bool, pre: bool):
|
|
111
|
-
"""安装适配器"""
|
|
112
301
|
console.print("\n[bold]可用的适配器:[/bold]")
|
|
113
302
|
|
|
114
303
|
adapters = remote_packages.get("adapters", {})
|
|
@@ -117,7 +306,6 @@ class InstallCommand(Command):
|
|
|
117
306
|
console.print("[yellow]没有可用的适配器[/yellow]")
|
|
118
307
|
return
|
|
119
308
|
|
|
120
|
-
# 显示适配器列表
|
|
121
309
|
table = Table(box=SIMPLE, header_style="adapter")
|
|
122
310
|
table.add_column("序号", style="cyan")
|
|
123
311
|
table.add_column("适配器名", style="adapter")
|
|
@@ -135,7 +323,6 @@ class InstallCommand(Command):
|
|
|
135
323
|
|
|
136
324
|
console.print(table)
|
|
137
325
|
|
|
138
|
-
# 选择适配器
|
|
139
326
|
selected = Prompt.ask(
|
|
140
327
|
"\n[cyan]请输入要安装的适配器序号(多个用逗号分隔,如: 1,3)或按 q 返回:[/cyan]"
|
|
141
328
|
)
|
|
@@ -156,7 +343,6 @@ class InstallCommand(Command):
|
|
|
156
343
|
console.print(f"[red]无效的序号: {idx}[/]")
|
|
157
344
|
|
|
158
345
|
if selected_packages:
|
|
159
|
-
# 确认安装
|
|
160
346
|
if Confirm.ask(
|
|
161
347
|
f"\n[cyan]确认安装以下 {len(selected_packages)} 个适配器吗?[/cyan]",
|
|
162
348
|
default=True
|
|
@@ -167,7 +353,6 @@ class InstallCommand(Command):
|
|
|
167
353
|
console.print("[red]输入格式错误,请输入数字序号[/]")
|
|
168
354
|
|
|
169
355
|
def _install_modules(self, remote_packages: dict, upgrade: bool, pre: bool):
|
|
170
|
-
"""安装模块"""
|
|
171
356
|
console.print("\n[bold]可用的模块:[/bold]")
|
|
172
357
|
|
|
173
358
|
modules = remote_packages.get("modules", {})
|
|
@@ -176,7 +361,6 @@ class InstallCommand(Command):
|
|
|
176
361
|
console.print("[yellow]没有可用的模块[/yellow]")
|
|
177
362
|
return
|
|
178
363
|
|
|
179
|
-
# 显示模块列表
|
|
180
364
|
table = Table(box=SIMPLE, header_style="module")
|
|
181
365
|
table.add_column("序号", style="cyan")
|
|
182
366
|
table.add_column("模块名", style="module")
|
|
@@ -194,7 +378,6 @@ class InstallCommand(Command):
|
|
|
194
378
|
|
|
195
379
|
console.print(table)
|
|
196
380
|
|
|
197
|
-
# 选择模块
|
|
198
381
|
selected = Prompt.ask(
|
|
199
382
|
"\n[cyan]请输入要安装的模块序号(多个用逗号分隔,如: 1,3)或按 q 返回:[/cyan]"
|
|
200
383
|
)
|
|
@@ -215,7 +398,6 @@ class InstallCommand(Command):
|
|
|
215
398
|
console.print(f"[red]无效的序号: {idx}[/]")
|
|
216
399
|
|
|
217
400
|
if selected_packages:
|
|
218
|
-
# 确认安装
|
|
219
401
|
if Confirm.ask(
|
|
220
402
|
f"\n[cyan]确认安装以下 {len(selected_packages)} 个模块吗?[/cyan]",
|
|
221
403
|
default=True
|
|
@@ -226,7 +408,6 @@ class InstallCommand(Command):
|
|
|
226
408
|
console.print("[red]输入格式错误,请输入数字序号[/]")
|
|
227
409
|
|
|
228
410
|
def _install_cli_extensions(self, remote_packages: dict, upgrade: bool, pre: bool):
|
|
229
|
-
"""安装 CLI 扩展"""
|
|
230
411
|
console.print("\n[bold]可用的 CLI 扩展:[/bold]")
|
|
231
412
|
|
|
232
413
|
cli_extensions = remote_packages.get("cli_extensions", {})
|
|
@@ -235,7 +416,6 @@ class InstallCommand(Command):
|
|
|
235
416
|
console.print("[yellow]没有可用的 CLI 扩展[/yellow]")
|
|
236
417
|
return
|
|
237
418
|
|
|
238
|
-
# 显示 CLI 扩展列表
|
|
239
419
|
table = Table(box=SIMPLE, header_style="cli")
|
|
240
420
|
table.add_column("序号", style="cyan")
|
|
241
421
|
table.add_column("命令名", style="cli")
|
|
@@ -253,7 +433,6 @@ class InstallCommand(Command):
|
|
|
253
433
|
|
|
254
434
|
console.print(table)
|
|
255
435
|
|
|
256
|
-
# 选择 CLI 扩展
|
|
257
436
|
selected = Prompt.ask(
|
|
258
437
|
"\n[cyan]请输入要安装的 CLI 扩展序号(多个用逗号分隔,如: 1,3)或按 q 返回:[/cyan]"
|
|
259
438
|
)
|
|
@@ -274,7 +453,6 @@ class InstallCommand(Command):
|
|
|
274
453
|
console.print(f"[red]无效的序号: {idx}[/]")
|
|
275
454
|
|
|
276
455
|
if selected_packages:
|
|
277
|
-
# 确认安装
|
|
278
456
|
if Confirm.ask(
|
|
279
457
|
f"\n[cyan]确认安装以下 {len(selected_packages)} 个 CLI 扩展吗?[/cyan]",
|
|
280
458
|
default=True
|
|
@@ -285,7 +463,6 @@ class InstallCommand(Command):
|
|
|
285
463
|
console.print("[red]输入格式错误,请输入数字序号[/]")
|
|
286
464
|
|
|
287
465
|
def _install_custom(self, upgrade: bool, pre: bool):
|
|
288
|
-
"""自定义安装"""
|
|
289
466
|
package_name = Prompt.ask(
|
|
290
467
|
"\n[cyan]请输入要安装的包名(或按 q 返回):[/cyan]"
|
|
291
468
|
)
|
|
@@ -294,7 +471,6 @@ class InstallCommand(Command):
|
|
|
294
471
|
return
|
|
295
472
|
|
|
296
473
|
if package_name:
|
|
297
|
-
# 确认安装
|
|
298
474
|
if Confirm.ask(
|
|
299
475
|
f"\n[cyan]确认安装包 {package_name} 吗?[/cyan]",
|
|
300
476
|
default=True
|
|
@@ -26,6 +26,8 @@ class InstallCommand(Command):
|
|
|
26
26
|
...
|
|
27
27
|
def add_arguments(self: object, parser: ArgumentParser) -> ...:
|
|
28
28
|
...
|
|
29
|
+
def _build_extra_pip_args(self: object, args: ...) -> list:
|
|
30
|
+
...
|
|
29
31
|
def execute(self: object, args: ...) -> ...:
|
|
30
32
|
...
|
|
31
33
|
def _interactive_install(self: object, upgrade: bool = ..., pre: bool = ...) -> ...:
|
|
@@ -37,22 +39,10 @@ class InstallCommand(Command):
|
|
|
37
39
|
"""
|
|
38
40
|
...
|
|
39
41
|
def _install_adapters(self: object, remote_packages: dict, upgrade: bool, pre: bool) -> ...:
|
|
40
|
-
"""
|
|
41
|
-
安装适配器
|
|
42
|
-
"""
|
|
43
42
|
...
|
|
44
43
|
def _install_modules(self: object, remote_packages: dict, upgrade: bool, pre: bool) -> ...:
|
|
45
|
-
"""
|
|
46
|
-
安装模块
|
|
47
|
-
"""
|
|
48
44
|
...
|
|
49
45
|
def _install_cli_extensions(self: object, remote_packages: dict, upgrade: bool, pre: bool) -> ...:
|
|
50
|
-
"""
|
|
51
|
-
安装 CLI 扩展
|
|
52
|
-
"""
|
|
53
46
|
...
|
|
54
47
|
def _install_custom(self: object, upgrade: bool, pre: bool) -> ...:
|
|
55
|
-
"""
|
|
56
|
-
自定义安装
|
|
57
|
-
"""
|
|
58
48
|
...
|
|
@@ -63,7 +63,7 @@ class PackageManager:
|
|
|
63
63
|
|
|
64
64
|
timeout = ClientTimeout(total=10)
|
|
65
65
|
try:
|
|
66
|
-
async with aiohttp.ClientSession(timeout=timeout) as session:
|
|
66
|
+
async with aiohttp.ClientSession(timeout=timeout, trust_env=True) as session:
|
|
67
67
|
async with session.get(url) as response:
|
|
68
68
|
if response.status == 200:
|
|
69
69
|
data = await response.text()
|
|
@@ -321,7 +321,7 @@ class PackageManager:
|
|
|
321
321
|
url = f"https://pypi.org/pypi/{package_name}/json"
|
|
322
322
|
|
|
323
323
|
try:
|
|
324
|
-
async with aiohttp.ClientSession(timeout=timeout) as session:
|
|
324
|
+
async with aiohttp.ClientSession(timeout=timeout, trust_env=True) as session:
|
|
325
325
|
async with session.get(url) as response:
|
|
326
326
|
if response.status == 200:
|
|
327
327
|
data = await response.json()
|
|
@@ -483,13 +483,14 @@ class PackageManager:
|
|
|
483
483
|
|
|
484
484
|
return None
|
|
485
485
|
|
|
486
|
-
def install_package(self, package_names: List[str], upgrade: bool = False, pre: bool = False) -> bool:
|
|
486
|
+
def install_package(self, package_names: List[str], upgrade: bool = False, pre: bool = False, extra_pip_args: List[str] = None) -> bool:
|
|
487
487
|
"""
|
|
488
488
|
安装指定包(支持多个包)
|
|
489
489
|
|
|
490
490
|
:param package_names: 要安装的包名或别名列表
|
|
491
491
|
:param upgrade: 是否升级已安装的包
|
|
492
492
|
:param pre: 是否包含预发布版本
|
|
493
|
+
:param extra_pip_args: 额外的 pip 参数
|
|
493
494
|
:return: 安装是否成功
|
|
494
495
|
"""
|
|
495
496
|
all_success = True
|
|
@@ -531,6 +532,8 @@ class PackageManager:
|
|
|
531
532
|
cmd.append("--upgrade")
|
|
532
533
|
if pre:
|
|
533
534
|
cmd.append("--pre")
|
|
535
|
+
if extra_pip_args:
|
|
536
|
+
cmd.extend(extra_pip_args)
|
|
534
537
|
cmd.append(current_package_name)
|
|
535
538
|
|
|
536
539
|
# 执行安装命令
|
|
@@ -554,6 +557,34 @@ class PackageManager:
|
|
|
554
557
|
|
|
555
558
|
return all_success
|
|
556
559
|
|
|
560
|
+
def install_direct(self, pip_args: List[str], description: str = "pip install") -> bool:
|
|
561
|
+
"""
|
|
562
|
+
直接执行 pip install 命令(跳过别名解析和兼容性检查)
|
|
563
|
+
|
|
564
|
+
:param pip_args: pip install 的参数列表(不含 "install" 本身)
|
|
565
|
+
:param description: 进度条描述
|
|
566
|
+
:return: 安装是否成功
|
|
567
|
+
"""
|
|
568
|
+
cmd = ["install"] + pip_args
|
|
569
|
+
success, stdout, stderr = self._run_pip_command_with_output(cmd, description)
|
|
570
|
+
|
|
571
|
+
if success:
|
|
572
|
+
console.print(Panel(
|
|
573
|
+
f"[success]安装成功[/]\n\n"
|
|
574
|
+
f"[dim]{stdout}[/]",
|
|
575
|
+
title="安装完成",
|
|
576
|
+
border_style="success"
|
|
577
|
+
))
|
|
578
|
+
else:
|
|
579
|
+
console.print(Panel(
|
|
580
|
+
f"[error]安装失败[/]\n\n"
|
|
581
|
+
f"[dim]{stderr}[/]",
|
|
582
|
+
title="安装失败",
|
|
583
|
+
border_style="error"
|
|
584
|
+
))
|
|
585
|
+
|
|
586
|
+
return success
|
|
587
|
+
|
|
557
588
|
def uninstall_package(self, package_names: List[str]) -> bool:
|
|
558
589
|
"""
|
|
559
590
|
卸载指定包(支持多个包,支持别名)
|
|
@@ -829,7 +860,7 @@ class PackageManager:
|
|
|
829
860
|
url = "https://pypi.org/pypi/ErisPulse/json"
|
|
830
861
|
|
|
831
862
|
try:
|
|
832
|
-
async with aiohttp.ClientSession(timeout=timeout) as session:
|
|
863
|
+
async with aiohttp.ClientSession(timeout=timeout, trust_env=True) as session:
|
|
833
864
|
async with session.get(url) as response:
|
|
834
865
|
if response.status == 200:
|
|
835
866
|
data = await response.json()
|
|
@@ -165,13 +165,23 @@ class PackageManager:
|
|
|
165
165
|
:return: 包信息字典
|
|
166
166
|
"""
|
|
167
167
|
...
|
|
168
|
-
def install_package(self: object, package_names: List[str], upgrade: bool = ..., pre: bool = ...) -> bool:
|
|
168
|
+
def install_package(self: object, package_names: List[str], upgrade: bool = ..., pre: bool = ..., extra_pip_args: List[str] = ...) -> bool:
|
|
169
169
|
"""
|
|
170
170
|
安装指定包(支持多个包)
|
|
171
171
|
|
|
172
172
|
:param package_names: 要安装的包名或别名列表
|
|
173
173
|
:param upgrade: 是否升级已安装的包
|
|
174
174
|
:param pre: 是否包含预发布版本
|
|
175
|
+
:param extra_pip_args: 额外的 pip 参数
|
|
176
|
+
:return: 安装是否成功
|
|
177
|
+
"""
|
|
178
|
+
...
|
|
179
|
+
def install_direct(self: object, pip_args: List[str], description: str = ...) -> bool:
|
|
180
|
+
"""
|
|
181
|
+
直接执行 pip install 命令(跳过别名解析和兼容性检查)
|
|
182
|
+
|
|
183
|
+
:param pip_args: pip install 的参数列表(不含 "install" 本身)
|
|
184
|
+
:param description: 进度条描述
|
|
175
185
|
:return: 安装是否成功
|
|
176
186
|
"""
|
|
177
187
|
...
|