cli-anything-cliproxyapi 1.0.0__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.
- cli_anything/cliproxyapi/__init__.py +3 -0
- cli_anything/cliproxyapi/cliproxyapi_cli.py +1238 -0
- cli_anything/cliproxyapi/core/__init__.py +1 -0
- cli_anything/cliproxyapi/core/api_keys.py +144 -0
- cli_anything/cliproxyapi/core/auth.py +176 -0
- cli_anything/cliproxyapi/core/client.py +101 -0
- cli_anything/cliproxyapi/core/config.py +194 -0
- cli_anything/cliproxyapi/core/logs.py +47 -0
- cli_anything/cliproxyapi/core/models.py +65 -0
- cli_anything/cliproxyapi/core/oauth.py +57 -0
- cli_anything/cliproxyapi/core/proxy.py +145 -0
- cli_anything/cliproxyapi/core/usage.py +25 -0
- cli_anything/cliproxyapi/tests/test_core.py +621 -0
- cli_anything/cliproxyapi/tests/test_full_e2e.py +309 -0
- cli_anything/cliproxyapi/utils/__init__.py +1 -0
- cli_anything/cliproxyapi/utils/output.py +77 -0
- cli_anything_cliproxyapi-1.0.0.dist-info/METADATA +10 -0
- cli_anything_cliproxyapi-1.0.0.dist-info/RECORD +21 -0
- cli_anything_cliproxyapi-1.0.0.dist-info/WHEEL +5 -0
- cli_anything_cliproxyapi-1.0.0.dist-info/entry_points.txt +2 -0
- cli_anything_cliproxyapi-1.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
"""E2E 测试 - 需要运行中的 CLIProxyAPI 服务器。
|
|
2
|
+
|
|
3
|
+
通过环境变量配置连接:
|
|
4
|
+
CPA_URL=http://127.0.0.1:8317 CPA_KEY=your-management-key pytest test_full_e2e.py -v
|
|
5
|
+
|
|
6
|
+
设置 CLI_ANYTHING_FORCE_INSTALLED=1 可强制使用已安装的 CLI 命令。
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import json
|
|
12
|
+
import os
|
|
13
|
+
import shutil
|
|
14
|
+
import subprocess
|
|
15
|
+
import sys
|
|
16
|
+
import tempfile
|
|
17
|
+
|
|
18
|
+
import pytest
|
|
19
|
+
|
|
20
|
+
# ============================================================
|
|
21
|
+
# 配置
|
|
22
|
+
# ============================================================
|
|
23
|
+
|
|
24
|
+
CPA_URL = os.getenv("CPA_URL", "http://127.0.0.1:8317")
|
|
25
|
+
CPA_KEY = os.getenv("CPA_KEY", "")
|
|
26
|
+
HARNESS_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", ".."))
|
|
27
|
+
os.environ["PYTHONPATH"] = HARNESS_ROOT + os.pathsep + os.environ.get("PYTHONPATH", "")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _resolve_cli(name: str = "cli-anything-cliproxyapi") -> list[str]:
|
|
31
|
+
"""解析 CLI 命令路径。默认使用当前源码的 python -m 调用,避免依赖外部安装状态。"""
|
|
32
|
+
if os.getenv("CLI_ANYTHING_FORCE_INSTALLED"):
|
|
33
|
+
return [name]
|
|
34
|
+
return [sys.executable, "-m", "cli_anything.cliproxyapi.cliproxyapi_cli"]
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _cli(*args, json_mode: bool = True) -> subprocess.CompletedProcess:
|
|
38
|
+
"""执行 CLI 命令。"""
|
|
39
|
+
cmd = _resolve_cli()
|
|
40
|
+
cmd = cmd + ["--url", CPA_URL, "--key", CPA_KEY]
|
|
41
|
+
if json_mode:
|
|
42
|
+
cmd.append("--json")
|
|
43
|
+
cmd.extend(args)
|
|
44
|
+
return subprocess.run(cmd, capture_output=True, text=True, timeout=30)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
# ============================================================
|
|
48
|
+
# Skip 条件
|
|
49
|
+
# ============================================================
|
|
50
|
+
|
|
51
|
+
def _server_available() -> bool:
|
|
52
|
+
try:
|
|
53
|
+
result = _cli("server", "status", json_mode=False)
|
|
54
|
+
return result.returncode == 0
|
|
55
|
+
except Exception:
|
|
56
|
+
return False
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
skip_no_server = pytest.mark.skipif(
|
|
60
|
+
not _server_available(),
|
|
61
|
+
reason="CLIProxyAPI 服务器不可用,设置 CPA_URL 和 CPA_KEY 环境变量",
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
# ============================================================
|
|
66
|
+
# 服务器状态测试
|
|
67
|
+
# ============================================================
|
|
68
|
+
|
|
69
|
+
class TestServer:
|
|
70
|
+
|
|
71
|
+
@skip_no_server
|
|
72
|
+
def test_health_check(self):
|
|
73
|
+
result = _cli("server", "status")
|
|
74
|
+
assert result.returncode == 0
|
|
75
|
+
data = json.loads(result.stdout)
|
|
76
|
+
assert data.get("status") == "ok"
|
|
77
|
+
|
|
78
|
+
@skip_no_server
|
|
79
|
+
def test_version(self):
|
|
80
|
+
result = _cli("server", "version")
|
|
81
|
+
assert result.returncode == 0
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
# ============================================================
|
|
85
|
+
# 配置测试
|
|
86
|
+
# ============================================================
|
|
87
|
+
|
|
88
|
+
class TestConfig:
|
|
89
|
+
|
|
90
|
+
@skip_no_server
|
|
91
|
+
def test_get_config(self):
|
|
92
|
+
result = _cli("config", "get")
|
|
93
|
+
assert result.returncode == 0
|
|
94
|
+
data = json.loads(result.stdout)
|
|
95
|
+
assert isinstance(data, dict)
|
|
96
|
+
|
|
97
|
+
@skip_no_server
|
|
98
|
+
def test_get_config_yaml(self):
|
|
99
|
+
result = _cli("config", "get-yaml")
|
|
100
|
+
assert result.returncode == 0
|
|
101
|
+
assert "port" in result.stdout
|
|
102
|
+
|
|
103
|
+
@skip_no_server
|
|
104
|
+
def test_get_debug(self):
|
|
105
|
+
result = _cli("config", "debug")
|
|
106
|
+
assert result.returncode == 0
|
|
107
|
+
|
|
108
|
+
@skip_no_server
|
|
109
|
+
def test_get_routing_strategy(self):
|
|
110
|
+
result = _cli("config", "routing")
|
|
111
|
+
assert result.returncode == 0
|
|
112
|
+
|
|
113
|
+
@skip_no_server
|
|
114
|
+
def test_get_request_retry(self):
|
|
115
|
+
result = _cli("config", "retry")
|
|
116
|
+
assert result.returncode == 0
|
|
117
|
+
|
|
118
|
+
@skip_no_server
|
|
119
|
+
def test_get_proxy_url(self):
|
|
120
|
+
result = _cli("config", "proxy-url")
|
|
121
|
+
assert result.returncode == 0
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
# ============================================================
|
|
125
|
+
# 认证文件测试
|
|
126
|
+
# ============================================================
|
|
127
|
+
|
|
128
|
+
class TestAuth:
|
|
129
|
+
|
|
130
|
+
@skip_no_server
|
|
131
|
+
def test_list_auth_files(self):
|
|
132
|
+
result = _cli("auth", "list")
|
|
133
|
+
assert result.returncode == 0
|
|
134
|
+
|
|
135
|
+
@skip_no_server
|
|
136
|
+
def test_list_enabled_auth_files(self):
|
|
137
|
+
result = _cli("auth", "list", "--enabled")
|
|
138
|
+
assert result.returncode == 0
|
|
139
|
+
data = json.loads(result.stdout)
|
|
140
|
+
assert "files" in data
|
|
141
|
+
|
|
142
|
+
@skip_no_server
|
|
143
|
+
def test_list_disabled_auth_files(self):
|
|
144
|
+
result = _cli("auth", "list", "--disabled")
|
|
145
|
+
assert result.returncode == 0
|
|
146
|
+
data = json.loads(result.stdout)
|
|
147
|
+
assert "files" in data
|
|
148
|
+
|
|
149
|
+
@skip_no_server
|
|
150
|
+
def test_codex_quota(self):
|
|
151
|
+
result = _cli("auth", "codex-quota")
|
|
152
|
+
assert result.returncode == 0
|
|
153
|
+
data = json.loads(result.stdout)
|
|
154
|
+
assert "quotas" in data
|
|
155
|
+
assert {"total", "success", "failed"}.issubset(data.keys())
|
|
156
|
+
|
|
157
|
+
@skip_no_server
|
|
158
|
+
def test_list_auth_models(self):
|
|
159
|
+
result = _cli("auth", "models")
|
|
160
|
+
assert result.returncode == 0
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
# ============================================================
|
|
164
|
+
# OAuth 测试
|
|
165
|
+
# ============================================================
|
|
166
|
+
|
|
167
|
+
class TestOAuth:
|
|
168
|
+
|
|
169
|
+
@skip_no_server
|
|
170
|
+
def test_providers_list(self):
|
|
171
|
+
"""验证 oauth login 命令接受所有提供商。"""
|
|
172
|
+
for provider in ["anthropic", "codex", "gemini", "antigravity", "qwen", "kimi", "iflow"]:
|
|
173
|
+
# 不实际登录,只验证命令解析
|
|
174
|
+
result = _cli("oauth", "login", "--help")
|
|
175
|
+
assert result.returncode == 0
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
# ============================================================
|
|
179
|
+
# API 密钥测试
|
|
180
|
+
# ============================================================
|
|
181
|
+
|
|
182
|
+
class TestKeys:
|
|
183
|
+
|
|
184
|
+
@skip_no_server
|
|
185
|
+
def test_list_api_keys(self):
|
|
186
|
+
result = _cli("keys", "list")
|
|
187
|
+
assert result.returncode == 0
|
|
188
|
+
|
|
189
|
+
@skip_no_server
|
|
190
|
+
def test_list_gemini_keys(self):
|
|
191
|
+
result = _cli("keys", "gemini", "list")
|
|
192
|
+
assert result.returncode == 0
|
|
193
|
+
|
|
194
|
+
@skip_no_server
|
|
195
|
+
def test_list_claude_keys(self):
|
|
196
|
+
result = _cli("keys", "claude", "list")
|
|
197
|
+
assert result.returncode == 0
|
|
198
|
+
|
|
199
|
+
@skip_no_server
|
|
200
|
+
def test_list_codex_keys(self):
|
|
201
|
+
result = _cli("keys", "codex", "list")
|
|
202
|
+
assert result.returncode == 0
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
# ============================================================
|
|
206
|
+
# 模型测试
|
|
207
|
+
# ============================================================
|
|
208
|
+
|
|
209
|
+
class TestModels:
|
|
210
|
+
|
|
211
|
+
@skip_no_server
|
|
212
|
+
def test_get_aliases(self):
|
|
213
|
+
result = _cli("models", "aliases")
|
|
214
|
+
assert result.returncode == 0
|
|
215
|
+
|
|
216
|
+
@skip_no_server
|
|
217
|
+
def test_get_excluded(self):
|
|
218
|
+
result = _cli("models", "excluded")
|
|
219
|
+
assert result.returncode == 0
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
# ============================================================
|
|
223
|
+
# 使用统计测试
|
|
224
|
+
# ============================================================
|
|
225
|
+
|
|
226
|
+
class TestUsage:
|
|
227
|
+
|
|
228
|
+
@skip_no_server
|
|
229
|
+
def test_get_stats(self):
|
|
230
|
+
result = _cli("usage", "stats")
|
|
231
|
+
assert result.returncode == 0
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
# ============================================================
|
|
235
|
+
# 日志测试
|
|
236
|
+
# ============================================================
|
|
237
|
+
|
|
238
|
+
class TestLogs:
|
|
239
|
+
|
|
240
|
+
@skip_no_server
|
|
241
|
+
def test_list_logs(self):
|
|
242
|
+
result = _cli("logs", "list")
|
|
243
|
+
assert result.returncode == 0
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
# ============================================================
|
|
247
|
+
# Amp 测试
|
|
248
|
+
# ============================================================
|
|
249
|
+
|
|
250
|
+
class TestAmp:
|
|
251
|
+
|
|
252
|
+
@skip_no_server
|
|
253
|
+
def test_get_amp_config(self):
|
|
254
|
+
result = _cli("amp", "config")
|
|
255
|
+
assert result.returncode == 0
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
# ============================================================
|
|
259
|
+
# CLI Subprocess 测试
|
|
260
|
+
# ============================================================
|
|
261
|
+
|
|
262
|
+
class TestCLISubprocess:
|
|
263
|
+
"""测试安装后的 CLI 命令行工具。"""
|
|
264
|
+
|
|
265
|
+
def test_help_flag(self):
|
|
266
|
+
cli = _resolve_cli()
|
|
267
|
+
result = subprocess.run(cli + ["--help"], capture_output=True, text=True, timeout=10)
|
|
268
|
+
assert result.returncode == 0
|
|
269
|
+
assert "CLIProxyAPI" in result.stdout
|
|
270
|
+
|
|
271
|
+
def test_version_flag(self):
|
|
272
|
+
cli = _resolve_cli()
|
|
273
|
+
result = subprocess.run(cli + ["--version"], capture_output=True, text=True, timeout=10)
|
|
274
|
+
assert result.returncode == 0
|
|
275
|
+
assert "1.0.0" in result.stdout
|
|
276
|
+
|
|
277
|
+
def test_no_args_shows_help(self):
|
|
278
|
+
cli = _resolve_cli()
|
|
279
|
+
result = subprocess.run(cli, capture_output=True, text=True, timeout=10)
|
|
280
|
+
assert result.returncode == 0
|
|
281
|
+
assert "Usage" in result.stdout
|
|
282
|
+
|
|
283
|
+
def test_json_flag_no_server(self):
|
|
284
|
+
"""无服务器时 --json 应输出错误 JSON。"""
|
|
285
|
+
result = _cli("server", "status")
|
|
286
|
+
# 连接失败时返回非零退出码
|
|
287
|
+
assert result.returncode != 0 or "ok" in result.stdout
|
|
288
|
+
|
|
289
|
+
def test_all_command_groups_have_help(self):
|
|
290
|
+
"""验证所有命令组的 --help 正常工作。"""
|
|
291
|
+
groups = ["server", "config", "auth", "oauth", "keys", "models", "usage", "logs", "amp"]
|
|
292
|
+
cli = _resolve_cli()
|
|
293
|
+
for group in groups:
|
|
294
|
+
result = subprocess.run(cli + [group, "--help"], capture_output=True, text=True, timeout=10)
|
|
295
|
+
assert result.returncode == 0, f"'{group} --help' 失败: {result.stderr}"
|
|
296
|
+
assert "Usage" in result.stdout, f"'{group} --help' 无 Usage"
|
|
297
|
+
|
|
298
|
+
def test_api_call_help(self):
|
|
299
|
+
"""验证 api-call 命令帮助。"""
|
|
300
|
+
cli = _resolve_cli()
|
|
301
|
+
result = subprocess.run(cli + ["api-call", "--help"], capture_output=True, text=True, timeout=10)
|
|
302
|
+
assert result.returncode == 0
|
|
303
|
+
|
|
304
|
+
def test_auth_codex_quota_help(self):
|
|
305
|
+
"""验证 auth codex-quota 命令帮助。"""
|
|
306
|
+
cli = _resolve_cli()
|
|
307
|
+
result = subprocess.run(cli + ["auth", "codex-quota", "--help"], capture_output=True, text=True, timeout=10)
|
|
308
|
+
assert result.returncode == 0
|
|
309
|
+
assert "获取已启用 Codex 凭证额度" in result.stdout
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Utility modules for CLIProxyAPI CLI harness."""
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"""输出格式化工具。"""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
from typing import Any, List, Dict
|
|
7
|
+
|
|
8
|
+
from rich.console import Console
|
|
9
|
+
from rich.table import Table
|
|
10
|
+
from rich.panel import Panel
|
|
11
|
+
from rich.text import Text
|
|
12
|
+
|
|
13
|
+
console = Console()
|
|
14
|
+
error_console = Console(stderr=True)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def output_json(data: Any) -> None:
|
|
18
|
+
"""输出 JSON 格式。"""
|
|
19
|
+
console.print(json.dumps(data, indent=2, ensure_ascii=False))
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def output_result(data: Any, json_mode: bool = False) -> None:
|
|
23
|
+
"""统一输出入口。"""
|
|
24
|
+
if json_mode:
|
|
25
|
+
output_json(data)
|
|
26
|
+
elif isinstance(data, str):
|
|
27
|
+
console.print(data)
|
|
28
|
+
elif isinstance(data, dict):
|
|
29
|
+
_output_dict(data)
|
|
30
|
+
elif isinstance(data, list):
|
|
31
|
+
_output_list(data)
|
|
32
|
+
else:
|
|
33
|
+
console.print(str(data))
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _output_dict(data: dict) -> None:
|
|
37
|
+
if "value" in data and len(data) <= 2:
|
|
38
|
+
console.print(str(data["value"]))
|
|
39
|
+
elif "status" in data and data["status"] == "ok":
|
|
40
|
+
console.print("[green]OK[/green]")
|
|
41
|
+
elif "error" in data:
|
|
42
|
+
console.print(f"[red]错误: {data['error']}[/red]")
|
|
43
|
+
else:
|
|
44
|
+
console.print_json(json.dumps(data, ensure_ascii=False))
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _output_list(data: list) -> None:
|
|
48
|
+
if not data:
|
|
49
|
+
console.print("[dim](空)[/dim]")
|
|
50
|
+
return
|
|
51
|
+
for item in data:
|
|
52
|
+
if isinstance(item, dict):
|
|
53
|
+
_output_dict(item)
|
|
54
|
+
else:
|
|
55
|
+
console.print(str(item))
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def output_table(headers: List[str], rows: List[List[str]], title: str = "") -> None:
|
|
59
|
+
"""输出 Rich 表格。"""
|
|
60
|
+
table = Table(title=title, show_header=True, header_style="bold cyan")
|
|
61
|
+
for h in headers:
|
|
62
|
+
table.add_column(h)
|
|
63
|
+
for row in rows:
|
|
64
|
+
table.add_row(*[str(c) for c in row])
|
|
65
|
+
console.print(table)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def output_kv(data: dict, title: str = "") -> None:
|
|
69
|
+
"""输出键值对。"""
|
|
70
|
+
if title:
|
|
71
|
+
console.print(f"[bold]{title}[/bold]")
|
|
72
|
+
for k, v in data.items():
|
|
73
|
+
console.print(f" [cyan]{k}[/cyan]: {v}")
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def output_error(msg: str) -> None:
|
|
77
|
+
error_console.print(f"[red]错误: {msg}[/red]")
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: cli-anything-cliproxyapi
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: CLI harness for CLIProxyAPI - proxy server with OpenAI/Gemini/Claude/Codex compatible APIs
|
|
5
|
+
Requires-Python: >=3.9
|
|
6
|
+
Requires-Dist: click >=8.0
|
|
7
|
+
Requires-Dist: requests >=2.28
|
|
8
|
+
Requires-Dist: rich >=13.0
|
|
9
|
+
Requires-Dist: PyYAML >=6.0
|
|
10
|
+
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
cli_anything/cliproxyapi/__init__.py,sha256=SxTEjspfkfc47HH3FFOYRzPgtExokJmtEEW-8M3jIis,117
|
|
2
|
+
cli_anything/cliproxyapi/cliproxyapi_cli.py,sha256=Pc4fAvNJ0ORIfaF7ZnOEAi7q2i1tJRTLmid5ap2Q9As,36681
|
|
3
|
+
cli_anything/cliproxyapi/core/__init__.py,sha256=xJno96prqlLjY_g0sFLUI2csOf3bCJBQeTniyTkywNQ,48
|
|
4
|
+
cli_anything/cliproxyapi/core/api_keys.py,sha256=_XN-egpTa4pM1Hl3qLQfd8tp_5VT0mtSCZyDYywIcQ8,4901
|
|
5
|
+
cli_anything/cliproxyapi/core/auth.py,sha256=H47ihhI5k2TZBak7QaEK9wdbRID49923ZrKKRIVTyDg,6792
|
|
6
|
+
cli_anything/cliproxyapi/core/client.py,sha256=YEtgGzxXyCx9DfgiaUQsgY4e27rjry7Xl1Ovx4aZW5c,3750
|
|
7
|
+
cli_anything/cliproxyapi/core/config.py,sha256=o-WaoNyaYZ5p8Zzri6JuU-IacBgfm0u1FRFJHIWMMGg,6337
|
|
8
|
+
cli_anything/cliproxyapi/core/logs.py,sha256=n2ja9xJMKHzi03Gt5JrlObgeFqX7BdOgx5DP7ESEpdA,1405
|
|
9
|
+
cli_anything/cliproxyapi/core/models.py,sha256=znAE0KJiZaoGm2gl-0ypnNnLZx_oQwUYQwGOYo0kZvk,2313
|
|
10
|
+
cli_anything/cliproxyapi/core/oauth.py,sha256=Z0FUBH-jorKr7UaWhN5Lr2oF0MtsZR0SpAfdG5WOm0c,2058
|
|
11
|
+
cli_anything/cliproxyapi/core/proxy.py,sha256=BVwwp4I8Oz5wfGHKtfX-AntE3bxwsxZd72R2n2wNNTk,5075
|
|
12
|
+
cli_anything/cliproxyapi/core/usage.py,sha256=A3KHhvVxprOb65BO7RcTGgT2luslVzeTArzfGe1EG14,673
|
|
13
|
+
cli_anything/cliproxyapi/tests/test_core.py,sha256=23FUxO8M4UPKhElYVzUR5QdAuYl4il9jdq5YHjJpwWE,24079
|
|
14
|
+
cli_anything/cliproxyapi/tests/test_full_e2e.py,sha256=KP-Re-ebqOMYYIWSaEn-KG119rtD5oIiFqqiUg1cJbM,9618
|
|
15
|
+
cli_anything/cliproxyapi/utils/__init__.py,sha256=7cQdBgWYoBZNtVXRMJ_WI2oidWSNSu-CtjGVDZRrV9A,51
|
|
16
|
+
cli_anything/cliproxyapi/utils/output.py,sha256=DKWZRaR59W689WG6dMf0QDDyUNpAA_QGNMiN5zJbmZk,2081
|
|
17
|
+
cli_anything_cliproxyapi-1.0.0.dist-info/METADATA,sha256=0ranBZbibBZEtFOT7lWKZymAcBe1KWtnSPL-31GgMJ4,305
|
|
18
|
+
cli_anything_cliproxyapi-1.0.0.dist-info/WHEEL,sha256=BNRMDyzLkkcmlv0J8ppDQkk2VED33SesJDynr9ED1gc,91
|
|
19
|
+
cli_anything_cliproxyapi-1.0.0.dist-info/entry_points.txt,sha256=KKK-gkUAuWjcnPPImEUNpoH3E55IuiFa_p1owQ_6DNk,91
|
|
20
|
+
cli_anything_cliproxyapi-1.0.0.dist-info/top_level.txt,sha256=LI1GTe19xehXrxQtg-3ltETALXYkoctC4Y_iuDiCSRo,13
|
|
21
|
+
cli_anything_cliproxyapi-1.0.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
cli_anything
|