sdu-ucloud-cli 0.1.0__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.
@@ -0,0 +1,22 @@
1
+ # Python-generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ build/
5
+ dist/
6
+ dist_pypi/
7
+ wheels/
8
+ *.egg-info
9
+ .pytest_cache/
10
+ .ruff_cache/
11
+ .mypy_cache/
12
+ .DS_Store
13
+
14
+ # Virtual environments
15
+ .venv
16
+
17
+ # Local traffic captures may include auth tokens
18
+ *.curl
19
+ captures/
20
+
21
+ # Local cloned backend source (not part of this CLI package)
22
+ ucloud/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Rasmus Larsen
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,306 @@
1
+ Metadata-Version: 2.4
2
+ Name: sdu-ucloud-cli
3
+ Version: 0.1.0
4
+ Summary: Unofficial CLI for SDU UCloud web service
5
+ Author-email: Rasmus Larsen <rasmus.larsen@alexandra.dk>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2026 Rasmus Larsen
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+ License-File: LICENSE
28
+ Keywords: cli,hpc,sdu,ucloud
29
+ Classifier: Development Status :: 3 - Alpha
30
+ Classifier: Environment :: Console
31
+ Classifier: Intended Audience :: Developers
32
+ Classifier: License :: OSI Approved :: MIT License
33
+ Classifier: Operating System :: OS Independent
34
+ Classifier: Programming Language :: Python :: 3
35
+ Classifier: Programming Language :: Python :: 3.10
36
+ Classifier: Programming Language :: Python :: 3.11
37
+ Classifier: Programming Language :: Python :: 3.12
38
+ Classifier: Topic :: Utilities
39
+ Requires-Python: >=3.10.13
40
+ Requires-Dist: httpx<1.0,>=0.27
41
+ Requires-Dist: platformdirs<5.0,>=4.2
42
+ Requires-Dist: rich<14.0,>=13.7
43
+ Requires-Dist: typer<1.0,>=0.12
44
+ Provides-Extra: dev
45
+ Requires-Dist: pytest<9.0,>=8.2; extra == 'dev'
46
+ Requires-Dist: ruff<1.0,>=0.6.5; extra == 'dev'
47
+ Description-Content-Type: text/markdown
48
+
49
+ # ucloud-cli
50
+
51
+ `ucloud-cli` is an unofficial command-line client for SDU UCloud (`https://cloud.sdu.dk`).
52
+ It lets you manage common workflows from a terminal: projects, jobs, job submission, status checks, accounting, and SSH access.
53
+ It is published on PyPI as `sdu-ucloud-cli` and installs the `ucloud` command.
54
+
55
+ This tool uses the same web endpoints as the UCloud dashboard.
56
+ There is no stable public API contract for these endpoints, so behavior can change over time.
57
+
58
+ ## Install
59
+
60
+ Install from PyPI:
61
+
62
+ ```bash
63
+ uv tool install sdu-ucloud-cli
64
+ ucloud --help
65
+ ```
66
+
67
+ Install from a local checkout:
68
+
69
+ ```bash
70
+ uv tool install .
71
+ ucloud --help
72
+ ```
73
+
74
+ Run directly from source:
75
+
76
+ ```bash
77
+ uv sync
78
+ uv run ucloud --help
79
+ ```
80
+
81
+ Install from Git without cloning:
82
+
83
+ ```bash
84
+ uv tool install "git+https://github.com/rlrs/ucloud-cli.git"
85
+ ucloud --help
86
+ ```
87
+
88
+ ## First login flow
89
+
90
+ Login directly with username/password (supports MFA challenge):
91
+
92
+ ```bash
93
+ uv run ucloud auth login --username <username>
94
+ uv run ucloud auth status
95
+ ```
96
+
97
+ Refresh the access token from the stored `refreshToken` cookie:
98
+
99
+ ```bash
100
+ uv run ucloud auth refresh
101
+ ```
102
+
103
+ If you already have a browser session in Firefox, import it automatically:
104
+
105
+ ```bash
106
+ uv run ucloud auth import-firefox
107
+ ```
108
+
109
+ Fallbacks (manual browser capture):
110
+
111
+ ```bash
112
+ uv run ucloud auth import-curl capture.curl
113
+ uv run ucloud auth login-cookie --cookie-header "name=value; other=value"
114
+ ```
115
+
116
+ ## Probe endpoints
117
+
118
+ ```bash
119
+ uv run ucloud request GET /api/projects
120
+ uv run ucloud request GET /api/projects --output json
121
+ uv run ucloud request POST /api/example --json '{"id":"123"}'
122
+ ```
123
+
124
+ You can attach a project context header to any request:
125
+
126
+ ```bash
127
+ uv run ucloud request GET /api/jobs/browse --project <project-id>
128
+ ```
129
+
130
+ ## Project context
131
+
132
+ Set a default project once and reuse it across commands:
133
+
134
+ ```bash
135
+ uv run ucloud projects browse --limit 20
136
+ uv run ucloud projects use --project <project-id>
137
+ uv run ucloud projects current
138
+ ```
139
+
140
+ You can also run `uv run ucloud projects use` without `--project` to pick from an interactive list.
141
+
142
+ ## Drives and files (read-only)
143
+
144
+ Browse drives in the active project:
145
+
146
+ ```bash
147
+ uv run ucloud files drives
148
+ ```
149
+
150
+ List files in a directory:
151
+
152
+ ```bash
153
+ uv run ucloud files ls /
154
+ uv run ucloud files ls /1081839/DFM
155
+ ```
156
+
157
+ Inspect a single path:
158
+
159
+ ```bash
160
+ uv run ucloud files stat /1081839/DFM/readme.txt
161
+ ```
162
+
163
+ Show storage usage/quota from drives + wallets:
164
+
165
+ ```bash
166
+ uv run ucloud files df
167
+ uv run ucloud files df --project all
168
+ ```
169
+
170
+ Render a recursive tree (read-only crawl):
171
+
172
+ ```bash
173
+ uv run ucloud files tree /1093173
174
+ uv run ucloud files tree /1093173/eval-service --dirs-only
175
+ uv run ucloud files tree / --crawl-drives --max-depth 2
176
+ uv run ucloud files tree /1093173/eval-service --sort-by size --reverse --no-dirs-first
177
+ ```
178
+
179
+ `--max-depth` limits tree display depth only; size aggregation still uses crawl results.
180
+
181
+ ## Browse jobs
182
+
183
+ ```bash
184
+ uv run ucloud jobs browse
185
+ uv run ucloud jobs browse --filter-state RUNNING --items-per-page 100
186
+ uv run ucloud jobs browse --all --items-per-page 100
187
+ uv run ucloud jobs browse --project all
188
+ uv run ucloud jobs browse --output json --limit 20
189
+ ```
190
+
191
+ `jobs browse` uses the active project context and prints it above the result.
192
+ Set one with `ucloud projects use --project <project-id>` or override with `--project`.
193
+ Use `--project all` to browse across all visible projects.
194
+ When available, the project line includes both title and id.
195
+ Browse output includes remaining time until expiry (`remaining`).
196
+
197
+ ## Job status and stop
198
+
199
+ ```bash
200
+ uv run ucloud jobs status <job-id>
201
+ uv run ucloud jobs status <job-id> --poll --interval 2
202
+ uv run ucloud jobs stop <job-id>
203
+ ```
204
+
205
+ ## SSH into a job
206
+
207
+ Open SSH directly from the latest `jobs/retrieve` SSH update:
208
+
209
+ ```bash
210
+ uv run ucloud jobs ssh <job-id>
211
+ ```
212
+
213
+ Print the resolved command without executing:
214
+
215
+ ```bash
216
+ uv run ucloud jobs ssh <job-id> --print-only
217
+ ```
218
+
219
+ ## Submit jobs (safe default)
220
+
221
+ `jobs submit` is dry-run by default and does not send anything to UCloud unless `--execute` is present.
222
+ The selected project controls the `Project` request header (job ownership context), while mounted drive paths can still point to other projects.
223
+ Project-scoped commands print the active project and allow `--project` override.
224
+
225
+ ```bash
226
+ uv run ucloud jobs submit --from-curl job-submit.curl
227
+ uv run ucloud jobs submit --from-curl job-submit.curl --execute
228
+ ```
229
+
230
+ Copy a previous job as a template:
231
+
232
+ ```bash
233
+ uv run ucloud jobs submit --from <job-id>
234
+ uv run ucloud jobs submit --from <job-id> --execute
235
+ ```
236
+
237
+ Useful overrides (without editing raw JSON):
238
+
239
+ ```bash
240
+ uv run ucloud jobs submit --from-curl job-submit.curl \
241
+ --name "debug-run" \
242
+ --app-version Aug2026 \
243
+ --product-id u3-gpu-4 \
244
+ --replicas 1 \
245
+ --time 12:00 \
246
+ --mount /<id>/<dir> \
247
+ --mount-ro /<id>/<dir>
248
+ ```
249
+
250
+ This prints a readable summary first. Add `--show-payload` to inspect full JSON and `--write-payload job.json` to save it.
251
+
252
+ Other payload input modes:
253
+
254
+ ```bash
255
+ uv run ucloud jobs submit --payload-file job.json
256
+ uv run ucloud jobs submit --json '{"type":"bulk","items":[]}'
257
+ ```
258
+
259
+ ## Browse accounting wallets
260
+
261
+ ```bash
262
+ uv run ucloud accounting wallets
263
+ uv run ucloud accounting wallets --items-per-page 250
264
+ uv run ucloud accounting wallets --output json --limit 20
265
+ ```
266
+
267
+ `accounting wallets` is project-scoped and uses the active project (or `--project`).
268
+
269
+ ## Per-user job accounting
270
+
271
+ Aggregate historical job usage per user inside the active project:
272
+
273
+ ```bash
274
+ uv run ucloud accounting jobs
275
+ uv run ucloud accounting jobs --max-pages 10
276
+ uv run ucloud accounting jobs --output json
277
+ uv run ucloud accounting jobs --project all
278
+ ```
279
+
280
+ `accounting jobs` uses `jobs/browse` with pagination and sums estimated GPU-hours by owner.
281
+ By default it includes all job states; use `--filter-state` to narrow scope.
282
+ Pass `--project all` to aggregate across all visible projects.
283
+ Running jobs are counted only up to the current time (not full allocation).
284
+ Accounting tables include one column per machine family (for example `u3-gpu`, `u1-dfm`, `u1-standard-h`).
285
+ GPU families are shown in `gpuh`; non-GPU families are shown in `h`.
286
+
287
+ ## Project helper
288
+
289
+ ```bash
290
+ uv run ucloud projects browse
291
+ uv run ucloud projects browse --items-per-page 250 --sort-by favorite
292
+ uv run ucloud projects browse --output json --limit 20
293
+ ```
294
+
295
+ ## Auto-discover endpoints from source
296
+
297
+ If you have the UCloud source repository cloned as `ucloud/`, you can parse the generated endpoint map:
298
+
299
+ ```bash
300
+ uv run ucloud discover endpoints
301
+ uv run ucloud discover endpoints --contains jobs --contains browse
302
+ uv run ucloud discover endpoints --method GET --output json --write endpoints.json
303
+ ```
304
+
305
+ By default this reads:
306
+ `ucloud/frontend-web/webclient/app/Authentication/RpcNameTable.ts`
@@ -0,0 +1,258 @@
1
+ # ucloud-cli
2
+
3
+ `ucloud-cli` is an unofficial command-line client for SDU UCloud (`https://cloud.sdu.dk`).
4
+ It lets you manage common workflows from a terminal: projects, jobs, job submission, status checks, accounting, and SSH access.
5
+ It is published on PyPI as `sdu-ucloud-cli` and installs the `ucloud` command.
6
+
7
+ This tool uses the same web endpoints as the UCloud dashboard.
8
+ There is no stable public API contract for these endpoints, so behavior can change over time.
9
+
10
+ ## Install
11
+
12
+ Install from PyPI:
13
+
14
+ ```bash
15
+ uv tool install sdu-ucloud-cli
16
+ ucloud --help
17
+ ```
18
+
19
+ Install from a local checkout:
20
+
21
+ ```bash
22
+ uv tool install .
23
+ ucloud --help
24
+ ```
25
+
26
+ Run directly from source:
27
+
28
+ ```bash
29
+ uv sync
30
+ uv run ucloud --help
31
+ ```
32
+
33
+ Install from Git without cloning:
34
+
35
+ ```bash
36
+ uv tool install "git+https://github.com/rlrs/ucloud-cli.git"
37
+ ucloud --help
38
+ ```
39
+
40
+ ## First login flow
41
+
42
+ Login directly with username/password (supports MFA challenge):
43
+
44
+ ```bash
45
+ uv run ucloud auth login --username <username>
46
+ uv run ucloud auth status
47
+ ```
48
+
49
+ Refresh the access token from the stored `refreshToken` cookie:
50
+
51
+ ```bash
52
+ uv run ucloud auth refresh
53
+ ```
54
+
55
+ If you already have a browser session in Firefox, import it automatically:
56
+
57
+ ```bash
58
+ uv run ucloud auth import-firefox
59
+ ```
60
+
61
+ Fallbacks (manual browser capture):
62
+
63
+ ```bash
64
+ uv run ucloud auth import-curl capture.curl
65
+ uv run ucloud auth login-cookie --cookie-header "name=value; other=value"
66
+ ```
67
+
68
+ ## Probe endpoints
69
+
70
+ ```bash
71
+ uv run ucloud request GET /api/projects
72
+ uv run ucloud request GET /api/projects --output json
73
+ uv run ucloud request POST /api/example --json '{"id":"123"}'
74
+ ```
75
+
76
+ You can attach a project context header to any request:
77
+
78
+ ```bash
79
+ uv run ucloud request GET /api/jobs/browse --project <project-id>
80
+ ```
81
+
82
+ ## Project context
83
+
84
+ Set a default project once and reuse it across commands:
85
+
86
+ ```bash
87
+ uv run ucloud projects browse --limit 20
88
+ uv run ucloud projects use --project <project-id>
89
+ uv run ucloud projects current
90
+ ```
91
+
92
+ You can also run `uv run ucloud projects use` without `--project` to pick from an interactive list.
93
+
94
+ ## Drives and files (read-only)
95
+
96
+ Browse drives in the active project:
97
+
98
+ ```bash
99
+ uv run ucloud files drives
100
+ ```
101
+
102
+ List files in a directory:
103
+
104
+ ```bash
105
+ uv run ucloud files ls /
106
+ uv run ucloud files ls /1081839/DFM
107
+ ```
108
+
109
+ Inspect a single path:
110
+
111
+ ```bash
112
+ uv run ucloud files stat /1081839/DFM/readme.txt
113
+ ```
114
+
115
+ Show storage usage/quota from drives + wallets:
116
+
117
+ ```bash
118
+ uv run ucloud files df
119
+ uv run ucloud files df --project all
120
+ ```
121
+
122
+ Render a recursive tree (read-only crawl):
123
+
124
+ ```bash
125
+ uv run ucloud files tree /1093173
126
+ uv run ucloud files tree /1093173/eval-service --dirs-only
127
+ uv run ucloud files tree / --crawl-drives --max-depth 2
128
+ uv run ucloud files tree /1093173/eval-service --sort-by size --reverse --no-dirs-first
129
+ ```
130
+
131
+ `--max-depth` limits tree display depth only; size aggregation still uses crawl results.
132
+
133
+ ## Browse jobs
134
+
135
+ ```bash
136
+ uv run ucloud jobs browse
137
+ uv run ucloud jobs browse --filter-state RUNNING --items-per-page 100
138
+ uv run ucloud jobs browse --all --items-per-page 100
139
+ uv run ucloud jobs browse --project all
140
+ uv run ucloud jobs browse --output json --limit 20
141
+ ```
142
+
143
+ `jobs browse` uses the active project context and prints it above the result.
144
+ Set one with `ucloud projects use --project <project-id>` or override with `--project`.
145
+ Use `--project all` to browse across all visible projects.
146
+ When available, the project line includes both title and id.
147
+ Browse output includes remaining time until expiry (`remaining`).
148
+
149
+ ## Job status and stop
150
+
151
+ ```bash
152
+ uv run ucloud jobs status <job-id>
153
+ uv run ucloud jobs status <job-id> --poll --interval 2
154
+ uv run ucloud jobs stop <job-id>
155
+ ```
156
+
157
+ ## SSH into a job
158
+
159
+ Open SSH directly from the latest `jobs/retrieve` SSH update:
160
+
161
+ ```bash
162
+ uv run ucloud jobs ssh <job-id>
163
+ ```
164
+
165
+ Print the resolved command without executing:
166
+
167
+ ```bash
168
+ uv run ucloud jobs ssh <job-id> --print-only
169
+ ```
170
+
171
+ ## Submit jobs (safe default)
172
+
173
+ `jobs submit` is dry-run by default and does not send anything to UCloud unless `--execute` is present.
174
+ The selected project controls the `Project` request header (job ownership context), while mounted drive paths can still point to other projects.
175
+ Project-scoped commands print the active project and allow `--project` override.
176
+
177
+ ```bash
178
+ uv run ucloud jobs submit --from-curl job-submit.curl
179
+ uv run ucloud jobs submit --from-curl job-submit.curl --execute
180
+ ```
181
+
182
+ Copy a previous job as a template:
183
+
184
+ ```bash
185
+ uv run ucloud jobs submit --from <job-id>
186
+ uv run ucloud jobs submit --from <job-id> --execute
187
+ ```
188
+
189
+ Useful overrides (without editing raw JSON):
190
+
191
+ ```bash
192
+ uv run ucloud jobs submit --from-curl job-submit.curl \
193
+ --name "debug-run" \
194
+ --app-version Aug2026 \
195
+ --product-id u3-gpu-4 \
196
+ --replicas 1 \
197
+ --time 12:00 \
198
+ --mount /<id>/<dir> \
199
+ --mount-ro /<id>/<dir>
200
+ ```
201
+
202
+ This prints a readable summary first. Add `--show-payload` to inspect full JSON and `--write-payload job.json` to save it.
203
+
204
+ Other payload input modes:
205
+
206
+ ```bash
207
+ uv run ucloud jobs submit --payload-file job.json
208
+ uv run ucloud jobs submit --json '{"type":"bulk","items":[]}'
209
+ ```
210
+
211
+ ## Browse accounting wallets
212
+
213
+ ```bash
214
+ uv run ucloud accounting wallets
215
+ uv run ucloud accounting wallets --items-per-page 250
216
+ uv run ucloud accounting wallets --output json --limit 20
217
+ ```
218
+
219
+ `accounting wallets` is project-scoped and uses the active project (or `--project`).
220
+
221
+ ## Per-user job accounting
222
+
223
+ Aggregate historical job usage per user inside the active project:
224
+
225
+ ```bash
226
+ uv run ucloud accounting jobs
227
+ uv run ucloud accounting jobs --max-pages 10
228
+ uv run ucloud accounting jobs --output json
229
+ uv run ucloud accounting jobs --project all
230
+ ```
231
+
232
+ `accounting jobs` uses `jobs/browse` with pagination and sums estimated GPU-hours by owner.
233
+ By default it includes all job states; use `--filter-state` to narrow scope.
234
+ Pass `--project all` to aggregate across all visible projects.
235
+ Running jobs are counted only up to the current time (not full allocation).
236
+ Accounting tables include one column per machine family (for example `u3-gpu`, `u1-dfm`, `u1-standard-h`).
237
+ GPU families are shown in `gpuh`; non-GPU families are shown in `h`.
238
+
239
+ ## Project helper
240
+
241
+ ```bash
242
+ uv run ucloud projects browse
243
+ uv run ucloud projects browse --items-per-page 250 --sort-by favorite
244
+ uv run ucloud projects browse --output json --limit 20
245
+ ```
246
+
247
+ ## Auto-discover endpoints from source
248
+
249
+ If you have the UCloud source repository cloned as `ucloud/`, you can parse the generated endpoint map:
250
+
251
+ ```bash
252
+ uv run ucloud discover endpoints
253
+ uv run ucloud discover endpoints --contains jobs --contains browse
254
+ uv run ucloud discover endpoints --method GET --output json --write endpoints.json
255
+ ```
256
+
257
+ By default this reads:
258
+ `ucloud/frontend-web/webclient/app/Authentication/RpcNameTable.ts`
@@ -0,0 +1,72 @@
1
+ [build-system]
2
+ requires = ["hatchling>=1.25"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "sdu-ucloud-cli"
7
+ dynamic = ["version"]
8
+ description = "Unofficial CLI for SDU UCloud web service"
9
+ authors = [
10
+ { name = "Rasmus Larsen", email = "rasmus.larsen@alexandra.dk" },
11
+ ]
12
+ license = { file = "LICENSE" }
13
+ readme = "README.md"
14
+ requires-python = ">=3.10.13"
15
+ keywords = ["ucloud", "sdu", "cli", "hpc"]
16
+ classifiers = [
17
+ "Development Status :: 3 - Alpha",
18
+ "Environment :: Console",
19
+ "Intended Audience :: Developers",
20
+ "License :: OSI Approved :: MIT License",
21
+ "Operating System :: OS Independent",
22
+ "Programming Language :: Python :: 3",
23
+ "Programming Language :: Python :: 3.10",
24
+ "Programming Language :: Python :: 3.11",
25
+ "Programming Language :: Python :: 3.12",
26
+ "Topic :: Utilities",
27
+ ]
28
+ dependencies = [
29
+ "httpx>=0.27,<1.0",
30
+ "platformdirs>=4.2,<5.0",
31
+ "rich>=13.7,<14.0",
32
+ "typer>=0.12,<1.0",
33
+ ]
34
+
35
+ [project.optional-dependencies]
36
+ dev = [
37
+ "pytest>=8.2,<9.0",
38
+ "ruff>=0.6.5,<1.0",
39
+ ]
40
+
41
+ [project.scripts]
42
+ ucloud = "ucloud_cli.cli:main"
43
+
44
+ [tool.hatch.version]
45
+ path = "ucloud_cli/__init__.py"
46
+
47
+ [tool.hatch.build.targets.wheel]
48
+ packages = ["ucloud_cli"]
49
+
50
+ [tool.hatch.build.targets.sdist]
51
+ only-include = [
52
+ "LICENSE",
53
+ "README.md",
54
+ "pyproject.toml",
55
+ "ucloud_cli",
56
+ ]
57
+
58
+ [tool.pytest.ini_options]
59
+ pythonpath = ["."]
60
+ markers = [
61
+ "live: tests that talk to a live UCloud environment (opt-in with UCLOUD_LIVE_TESTS=1).",
62
+ ]
63
+
64
+ [tool.ruff]
65
+ target-version = "py310"
66
+ extend-exclude = ["ucloud"]
67
+
68
+ [dependency-groups]
69
+ dev = [
70
+ "build>=1.4.0",
71
+ "twine>=6.2.0",
72
+ ]
@@ -0,0 +1,5 @@
1
+ """ucloud-cli package."""
2
+
3
+ __all__ = ["__version__"]
4
+
5
+ __version__ = "0.1.0"
@@ -0,0 +1,5 @@
1
+ from .cli import main
2
+
3
+
4
+ if __name__ == "__main__":
5
+ main()