adagio-cli 0.1.0a1__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.
Files changed (56) hide show
  1. adagio_cli-0.1.0a1/LICENSE +21 -0
  2. adagio_cli-0.1.0a1/PKG-INFO +310 -0
  3. adagio_cli-0.1.0a1/README.md +278 -0
  4. adagio_cli-0.1.0a1/pyproject.toml +83 -0
  5. adagio_cli-0.1.0a1/src/adagio/__init__.py +15 -0
  6. adagio_cli-0.1.0a1/src/adagio/app/parsers/pipeline.py +89 -0
  7. adagio_cli-0.1.0a1/src/adagio/check.py +16 -0
  8. adagio_cli-0.1.0a1/src/adagio/cli/__init__.py +1 -0
  9. adagio_cli-0.1.0a1/src/adagio/cli/args.py +62 -0
  10. adagio_cli-0.1.0a1/src/adagio/cli/cache.py +82 -0
  11. adagio_cli-0.1.0a1/src/adagio/cli/config.py +39 -0
  12. adagio_cli-0.1.0a1/src/adagio/cli/dynamic.py +618 -0
  13. adagio_cli-0.1.0a1/src/adagio/cli/main.py +263 -0
  14. adagio_cli-0.1.0a1/src/adagio/cli/pipeline.py +27 -0
  15. adagio_cli-0.1.0a1/src/adagio/cli/qapi.py +172 -0
  16. adagio_cli-0.1.0a1/src/adagio/cli/runner.py +285 -0
  17. adagio_cli-0.1.0a1/src/adagio/cli/runtime.py +388 -0
  18. adagio_cli-0.1.0a1/src/adagio/cli/task_exec.py +289 -0
  19. adagio_cli-0.1.0a1/src/adagio/convert.py +0 -0
  20. adagio_cli-0.1.0a1/src/adagio/describe.py +366 -0
  21. adagio_cli-0.1.0a1/src/adagio/execute.py +65 -0
  22. adagio_cli-0.1.0a1/src/adagio/execution/context.py +102 -0
  23. adagio_cli-0.1.0a1/src/adagio/execution/proxy.py +243 -0
  24. adagio_cli-0.1.0a1/src/adagio/executors/__init__.py +29 -0
  25. adagio_cli-0.1.0a1/src/adagio/executors/apptainer.py +214 -0
  26. adagio_cli-0.1.0a1/src/adagio/executors/base.py +78 -0
  27. adagio_cli-0.1.0a1/src/adagio/executors/cache_support.py +55 -0
  28. adagio_cli-0.1.0a1/src/adagio/executors/common.py +55 -0
  29. adagio_cli-0.1.0a1/src/adagio/executors/container_support.py +169 -0
  30. adagio_cli-0.1.0a1/src/adagio/executors/defaults.py +115 -0
  31. adagio_cli-0.1.0a1/src/adagio/executors/docker.py +184 -0
  32. adagio_cli-0.1.0a1/src/adagio/executors/path_utils.py +47 -0
  33. adagio_cli-0.1.0a1/src/adagio/executors/serial_runner.py +135 -0
  34. adagio_cli-0.1.0a1/src/adagio/executors/task_contract.py +88 -0
  35. adagio_cli-0.1.0a1/src/adagio/executors/task_environments.py +225 -0
  36. adagio_cli-0.1.0a1/src/adagio/io.py +41 -0
  37. adagio_cli-0.1.0a1/src/adagio/model/__init__.py +0 -0
  38. adagio_cli-0.1.0a1/src/adagio/model/arguments.py +39 -0
  39. adagio_cli-0.1.0a1/src/adagio/model/ast.py +55 -0
  40. adagio_cli-0.1.0a1/src/adagio/model/pipeline.py +134 -0
  41. adagio_cli-0.1.0a1/src/adagio/model/task.py +135 -0
  42. adagio_cli-0.1.0a1/src/adagio/monitor/__init__.py +0 -0
  43. adagio_cli-0.1.0a1/src/adagio/monitor/api.py +60 -0
  44. adagio_cli-0.1.0a1/src/adagio/monitor/base.py +0 -0
  45. adagio_cli-0.1.0a1/src/adagio/monitor/composite.py +74 -0
  46. adagio_cli-0.1.0a1/src/adagio/monitor/connected.py +106 -0
  47. adagio_cli-0.1.0a1/src/adagio/monitor/log.py +72 -0
  48. adagio_cli-0.1.0a1/src/adagio/monitor/tty.py +293 -0
  49. adagio_cli-0.1.0a1/src/adagio/protocol/__init__.py +0 -0
  50. adagio_cli-0.1.0a1/src/adagio/protocol/base.py +0 -0
  51. adagio_cli-0.1.0a1/src/adagio/protocol/file.py +0 -0
  52. adagio_cli-0.1.0a1/src/adagio/protocol/http.py +0 -0
  53. adagio_cli-0.1.0a1/src/adagio/protocol/s3.py +0 -0
  54. adagio_cli-0.1.0a1/src/adagio/qapi/__init__.py +8 -0
  55. adagio_cli-0.1.0a1/src/adagio/qapi/build.py +158 -0
  56. adagio_cli-0.1.0a1/src/adagio/qapi/client.py +56 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Cymis
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,310 @@
1
+ Metadata-Version: 2.4
2
+ Name: adagio-cli
3
+ Version: 0.1.0a1
4
+ Summary: Command-line runner for Adagio pipeline files.
5
+ Keywords: adagio,bioinformatics,cli,pipelines,qiime2,workflow
6
+ Author: Cymis
7
+ License-Expression: MIT
8
+ License-File: LICENSE
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Environment :: Console
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3 :: Only
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
20
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
+ Requires-Dist: cyclopts>=4.5.3
22
+ Requires-Dist: pydantic>=2.12.5
23
+ Requires-Dist: rich>=14.1.0
24
+ Requires-Dist: parsl>=2024.12.16
25
+ Requires-Dist: tomli>=2.2.1 ; python_full_version < '3.11'
26
+ Requires-Python: >=3.10
27
+ Project-URL: Changelog, https://github.com/cymis/adagio-cli/blob/dev/CHANGELOG.md
28
+ Project-URL: Homepage, https://github.com/cymis/adagio-cli
29
+ Project-URL: Issues, https://github.com/cymis/adagio-cli/issues
30
+ Project-URL: Repository, https://github.com/cymis/adagio-cli
31
+ Description-Content-Type: text/markdown
32
+
33
+ # Adagio CLI
34
+
35
+ Command-line runner for Adagio pipeline files
36
+
37
+ ## Requirements
38
+
39
+ - Python 3.10+
40
+ - `uv` (recommended for development)
41
+ - Docker for the default task runtime
42
+ - Apptainer or Singularity when using `kind = "apptainer"` with local `.sif` images
43
+
44
+ ## Installation
45
+
46
+ Install from PyPI:
47
+
48
+ ```bash
49
+ pip install adagio-cli
50
+ ```
51
+
52
+ Install a prerelease from TestPyPI while validating a release candidate:
53
+
54
+ ```bash
55
+ pip install \
56
+ --index-url https://test.pypi.org/simple/ \
57
+ --extra-index-url https://pypi.org/simple \
58
+ adagio-cli
59
+ ```
60
+
61
+ Install from the current checkout:
62
+
63
+ ```bash
64
+ pip install .
65
+ ```
66
+
67
+ Or with `uv`:
68
+
69
+ ```bash
70
+ uv pip install .
71
+ ```
72
+
73
+ Verify install:
74
+
75
+ ```bash
76
+ adagio --version
77
+ adagio --help
78
+ ```
79
+
80
+ ## Usage
81
+
82
+ ### Run a pipeline
83
+
84
+ Show command help:
85
+
86
+ ```bash
87
+ adagio run --help
88
+ ```
89
+
90
+ Run with a pipeline file:
91
+
92
+ ```bash
93
+ adagio run --pipeline path/to/pipeline.json --cache-dir /path/to/cache
94
+ ```
95
+
96
+ `adagio run` executes each plugin task in its own task environment.
97
+ The default task environment is a Docker image in GHCR derived from the plugin
98
+ name in the pipeline spec, for example `dada2` -> `ghcr.io/cymis/qiime2-plugin-dada2:2026.1`.
99
+ Runtime config can override that per default/plugin/task and switch selected work to
100
+ Apptainer/Singularity with a local `.sif` image path. The cache directory is required
101
+ and is reused across reruns by default so unchanged successful tasks can be replayed.
102
+
103
+ Equivalent positional form:
104
+
105
+ ```bash
106
+ adagio run path/to/pipeline.json --cache-dir /path/to/cache
107
+ ```
108
+
109
+ Use an arguments file:
110
+
111
+ ```bash
112
+ adagio run --pipeline path/to/pipeline.json --cache-dir /path/to/cache --arguments path/to/arguments.json
113
+ ```
114
+
115
+ Use a runtime config file with defaults, plugin-level overrides, and optional task overrides:
116
+
117
+ ```bash
118
+ adagio run --pipeline path/to/pipeline.json --cache-dir /path/to/cache --config path/to/runtime.toml
119
+ ```
120
+
121
+ Control which dynamic flags are shown in help:
122
+
123
+ ```bash
124
+ adagio run --pipeline path/to/pipeline.json --cache-dir /path/to/cache --show-params required
125
+ # choices: all | missing | required
126
+ ```
127
+
128
+ Disable reuse for a run while still writing outputs into the selected cache directory:
129
+
130
+ ```bash
131
+ adagio run --pipeline path/to/pipeline.json --cache-dir /path/to/cache --no-reuse
132
+ ```
133
+
134
+ The same boolean pair is available as `--reuse` / `--no-reuse`. `--reuse` is the default.
135
+
136
+ Clear an existing cache directory:
137
+
138
+ ```bash
139
+ adagio cache clear --cache-dir /path/to/cache
140
+ ```
141
+
142
+ ### Inspect a pipeline
143
+
144
+ Print a dependency-ordered summary of the plugin actions in a pipeline:
145
+
146
+ ```bash
147
+ adagio pipeline show path/to/pipeline.json
148
+ ```
149
+
150
+ ### Arguments file format
151
+
152
+ `--arguments` can be downloaded from Adagio directly in the "Run" workflow :
153
+
154
+ ```json
155
+ {
156
+ "version": 1,
157
+ "inputs": {
158
+ "input_name": "/path/to/input.qza"
159
+ },
160
+ "parameters": {
161
+ "param_name": "value"
162
+ },
163
+ "outputs": "/path/to/output-dir"
164
+ }
165
+ ```
166
+
167
+ `outputs` may also be a map keyed by output name (WIP: not currently generated by Adagio):
168
+
169
+ ```json
170
+ {
171
+ "outputs": {
172
+ "output_a": "/path/to/output-a",
173
+ "output_b": "/path/to/output-b"
174
+ }
175
+ }
176
+ ```
177
+
178
+ If outputs are omitted, defaults are generated under `./adagio-outputs`.
179
+
180
+ ### Runtime config format
181
+
182
+ `--config` accepts TOML. Defaults apply first, then plugin keys, then task keys:
183
+
184
+ ```toml
185
+ version = 1
186
+
187
+ [defaults]
188
+ platform = "linux/amd64"
189
+
190
+ [plugins]
191
+ dada2 = { image = "ghcr.io/cymis/qiime2-plugin-dada2:2026.1" }
192
+ demux = { image = "ghcr.io/cymis/qiime2-plugin-demux:2026.1" }
193
+
194
+ [tasks]
195
+ "dada2.denoise_single" = { image = "registry.internal/custom-dada2:1.0", platform = "linux/amd64" }
196
+ ```
197
+
198
+ `kind`, `image`, and `platform` are all optional on defaults, plugin entries, and task entries.
199
+ `kind` may be `docker` or `apptainer`. `image` remains the environment reference:
200
+ for Docker it is the container image, and for Apptainer it must be a local `.sif` path.
201
+
202
+ Precedence is `task override > plugin override > defaults > default resolver`.
203
+
204
+ Task lookup supports graph node `id`, optional task `name` when present in the
205
+ pipeline, and `plugin.action` as a fallback. Plugin lookup uses the pipeline's
206
+ plugin name. If `platform` is omitted all the way through, Adagio uses normal
207
+ Docker platform resolution with no implicit fallback. Anything not listed in the
208
+ config uses the default plugin image resolver.
209
+
210
+ Concrete Apptainer example:
211
+
212
+ ```toml
213
+ version = 1
214
+
215
+ [defaults]
216
+ kind = "docker"
217
+
218
+ [plugins]
219
+ bowtie2 = { kind = "apptainer", image = "/shared/qiime-images/q2-bowtie2-test.sif" }
220
+ ```
221
+
222
+ For `kind = "apptainer"`, Adagio prefers the `apptainer` executable and falls back to
223
+ `singularity`. The current implementation supports only local `.sif` paths and runs
224
+ tasks serially; no scheduler submission or remote image pull behavior is included.
225
+
226
+ ### QAPI generation/submission
227
+
228
+ Generate and submit plugin metadata from the active QIIME environment:
229
+
230
+ ```bash
231
+ adagio qapi build --action-url http://localhost:81/api/v1
232
+ ```
233
+
234
+ Submit to a protected deployment such as `adagio.run` with a scoped submission token:
235
+
236
+ ```bash
237
+ export ACTION_URL=https://adagio.run/api/v1
238
+ export QAPI_SUBMISSION_TOKEN=<token copied from https://adagio.run/app/profile>
239
+ uv run adagio qapi build
240
+ ```
241
+
242
+ You can also pass `--submission-token`, but the environment variable is safer because it does
243
+ not end up in shell history.
244
+
245
+ Write payload to disk without submitting:
246
+
247
+ ```bash
248
+ adagio qapi build --output qapi.json --dry-run
249
+ ```
250
+
251
+ Submit selected plugins only:
252
+
253
+ ```bash
254
+ adagio qapi build --plugin dada2 --plugin feature-table
255
+ ```
256
+
257
+ ## Development
258
+
259
+ ### Setup
260
+
261
+ Install runtime and dev dependencies:
262
+
263
+ ```bash
264
+ uv sync --group dev
265
+ ```
266
+
267
+ Run commands inside the project environment:
268
+
269
+ ```bash
270
+ uv run adagio --help
271
+ ```
272
+
273
+ ### Linting
274
+
275
+ ```bash
276
+ uv run ruff check .
277
+ uv run ruff format --check .
278
+ uv run ruff format .
279
+ ```
280
+
281
+ ### Tests
282
+
283
+ ```bash
284
+ uv run pytest
285
+ ```
286
+
287
+ ### Build distributions
288
+
289
+ ```bash
290
+ uv run python -m build
291
+ uv run python -m twine check dist/*
292
+ ```
293
+
294
+ ### Running locally during development
295
+
296
+ ```bash
297
+ uv run adagio run --pipeline path/to/pipeline.json --cache-dir /path/to/cache
298
+ ```
299
+
300
+ ### Runtime entrypoint (container/integration use)
301
+
302
+ The `runtime` subcommand is intended for runtime-adapter jobs:
303
+
304
+ ```bash
305
+ uv run adagio runtime --spec spec.json --config runtime.toml --arguments arguments.json --cache-dir /path/to/cache
306
+ ```
307
+
308
+ ### Releasing
309
+
310
+ See [RELEASING.md](RELEASING.md) for the one-time PyPI/GitHub setup, version/tag workflow, and TestPyPI/PyPI publishing steps.
@@ -0,0 +1,278 @@
1
+ # Adagio CLI
2
+
3
+ Command-line runner for Adagio pipeline files
4
+
5
+ ## Requirements
6
+
7
+ - Python 3.10+
8
+ - `uv` (recommended for development)
9
+ - Docker for the default task runtime
10
+ - Apptainer or Singularity when using `kind = "apptainer"` with local `.sif` images
11
+
12
+ ## Installation
13
+
14
+ Install from PyPI:
15
+
16
+ ```bash
17
+ pip install adagio-cli
18
+ ```
19
+
20
+ Install a prerelease from TestPyPI while validating a release candidate:
21
+
22
+ ```bash
23
+ pip install \
24
+ --index-url https://test.pypi.org/simple/ \
25
+ --extra-index-url https://pypi.org/simple \
26
+ adagio-cli
27
+ ```
28
+
29
+ Install from the current checkout:
30
+
31
+ ```bash
32
+ pip install .
33
+ ```
34
+
35
+ Or with `uv`:
36
+
37
+ ```bash
38
+ uv pip install .
39
+ ```
40
+
41
+ Verify install:
42
+
43
+ ```bash
44
+ adagio --version
45
+ adagio --help
46
+ ```
47
+
48
+ ## Usage
49
+
50
+ ### Run a pipeline
51
+
52
+ Show command help:
53
+
54
+ ```bash
55
+ adagio run --help
56
+ ```
57
+
58
+ Run with a pipeline file:
59
+
60
+ ```bash
61
+ adagio run --pipeline path/to/pipeline.json --cache-dir /path/to/cache
62
+ ```
63
+
64
+ `adagio run` executes each plugin task in its own task environment.
65
+ The default task environment is a Docker image in GHCR derived from the plugin
66
+ name in the pipeline spec, for example `dada2` -> `ghcr.io/cymis/qiime2-plugin-dada2:2026.1`.
67
+ Runtime config can override that per default/plugin/task and switch selected work to
68
+ Apptainer/Singularity with a local `.sif` image path. The cache directory is required
69
+ and is reused across reruns by default so unchanged successful tasks can be replayed.
70
+
71
+ Equivalent positional form:
72
+
73
+ ```bash
74
+ adagio run path/to/pipeline.json --cache-dir /path/to/cache
75
+ ```
76
+
77
+ Use an arguments file:
78
+
79
+ ```bash
80
+ adagio run --pipeline path/to/pipeline.json --cache-dir /path/to/cache --arguments path/to/arguments.json
81
+ ```
82
+
83
+ Use a runtime config file with defaults, plugin-level overrides, and optional task overrides:
84
+
85
+ ```bash
86
+ adagio run --pipeline path/to/pipeline.json --cache-dir /path/to/cache --config path/to/runtime.toml
87
+ ```
88
+
89
+ Control which dynamic flags are shown in help:
90
+
91
+ ```bash
92
+ adagio run --pipeline path/to/pipeline.json --cache-dir /path/to/cache --show-params required
93
+ # choices: all | missing | required
94
+ ```
95
+
96
+ Disable reuse for a run while still writing outputs into the selected cache directory:
97
+
98
+ ```bash
99
+ adagio run --pipeline path/to/pipeline.json --cache-dir /path/to/cache --no-reuse
100
+ ```
101
+
102
+ The same boolean pair is available as `--reuse` / `--no-reuse`. `--reuse` is the default.
103
+
104
+ Clear an existing cache directory:
105
+
106
+ ```bash
107
+ adagio cache clear --cache-dir /path/to/cache
108
+ ```
109
+
110
+ ### Inspect a pipeline
111
+
112
+ Print a dependency-ordered summary of the plugin actions in a pipeline:
113
+
114
+ ```bash
115
+ adagio pipeline show path/to/pipeline.json
116
+ ```
117
+
118
+ ### Arguments file format
119
+
120
+ `--arguments` can be downloaded from Adagio directly in the "Run" workflow :
121
+
122
+ ```json
123
+ {
124
+ "version": 1,
125
+ "inputs": {
126
+ "input_name": "/path/to/input.qza"
127
+ },
128
+ "parameters": {
129
+ "param_name": "value"
130
+ },
131
+ "outputs": "/path/to/output-dir"
132
+ }
133
+ ```
134
+
135
+ `outputs` may also be a map keyed by output name (WIP: not currently generated by Adagio):
136
+
137
+ ```json
138
+ {
139
+ "outputs": {
140
+ "output_a": "/path/to/output-a",
141
+ "output_b": "/path/to/output-b"
142
+ }
143
+ }
144
+ ```
145
+
146
+ If outputs are omitted, defaults are generated under `./adagio-outputs`.
147
+
148
+ ### Runtime config format
149
+
150
+ `--config` accepts TOML. Defaults apply first, then plugin keys, then task keys:
151
+
152
+ ```toml
153
+ version = 1
154
+
155
+ [defaults]
156
+ platform = "linux/amd64"
157
+
158
+ [plugins]
159
+ dada2 = { image = "ghcr.io/cymis/qiime2-plugin-dada2:2026.1" }
160
+ demux = { image = "ghcr.io/cymis/qiime2-plugin-demux:2026.1" }
161
+
162
+ [tasks]
163
+ "dada2.denoise_single" = { image = "registry.internal/custom-dada2:1.0", platform = "linux/amd64" }
164
+ ```
165
+
166
+ `kind`, `image`, and `platform` are all optional on defaults, plugin entries, and task entries.
167
+ `kind` may be `docker` or `apptainer`. `image` remains the environment reference:
168
+ for Docker it is the container image, and for Apptainer it must be a local `.sif` path.
169
+
170
+ Precedence is `task override > plugin override > defaults > default resolver`.
171
+
172
+ Task lookup supports graph node `id`, optional task `name` when present in the
173
+ pipeline, and `plugin.action` as a fallback. Plugin lookup uses the pipeline's
174
+ plugin name. If `platform` is omitted all the way through, Adagio uses normal
175
+ Docker platform resolution with no implicit fallback. Anything not listed in the
176
+ config uses the default plugin image resolver.
177
+
178
+ Concrete Apptainer example:
179
+
180
+ ```toml
181
+ version = 1
182
+
183
+ [defaults]
184
+ kind = "docker"
185
+
186
+ [plugins]
187
+ bowtie2 = { kind = "apptainer", image = "/shared/qiime-images/q2-bowtie2-test.sif" }
188
+ ```
189
+
190
+ For `kind = "apptainer"`, Adagio prefers the `apptainer` executable and falls back to
191
+ `singularity`. The current implementation supports only local `.sif` paths and runs
192
+ tasks serially; no scheduler submission or remote image pull behavior is included.
193
+
194
+ ### QAPI generation/submission
195
+
196
+ Generate and submit plugin metadata from the active QIIME environment:
197
+
198
+ ```bash
199
+ adagio qapi build --action-url http://localhost:81/api/v1
200
+ ```
201
+
202
+ Submit to a protected deployment such as `adagio.run` with a scoped submission token:
203
+
204
+ ```bash
205
+ export ACTION_URL=https://adagio.run/api/v1
206
+ export QAPI_SUBMISSION_TOKEN=<token copied from https://adagio.run/app/profile>
207
+ uv run adagio qapi build
208
+ ```
209
+
210
+ You can also pass `--submission-token`, but the environment variable is safer because it does
211
+ not end up in shell history.
212
+
213
+ Write payload to disk without submitting:
214
+
215
+ ```bash
216
+ adagio qapi build --output qapi.json --dry-run
217
+ ```
218
+
219
+ Submit selected plugins only:
220
+
221
+ ```bash
222
+ adagio qapi build --plugin dada2 --plugin feature-table
223
+ ```
224
+
225
+ ## Development
226
+
227
+ ### Setup
228
+
229
+ Install runtime and dev dependencies:
230
+
231
+ ```bash
232
+ uv sync --group dev
233
+ ```
234
+
235
+ Run commands inside the project environment:
236
+
237
+ ```bash
238
+ uv run adagio --help
239
+ ```
240
+
241
+ ### Linting
242
+
243
+ ```bash
244
+ uv run ruff check .
245
+ uv run ruff format --check .
246
+ uv run ruff format .
247
+ ```
248
+
249
+ ### Tests
250
+
251
+ ```bash
252
+ uv run pytest
253
+ ```
254
+
255
+ ### Build distributions
256
+
257
+ ```bash
258
+ uv run python -m build
259
+ uv run python -m twine check dist/*
260
+ ```
261
+
262
+ ### Running locally during development
263
+
264
+ ```bash
265
+ uv run adagio run --pipeline path/to/pipeline.json --cache-dir /path/to/cache
266
+ ```
267
+
268
+ ### Runtime entrypoint (container/integration use)
269
+
270
+ The `runtime` subcommand is intended for runtime-adapter jobs:
271
+
272
+ ```bash
273
+ uv run adagio runtime --spec spec.json --config runtime.toml --arguments arguments.json --cache-dir /path/to/cache
274
+ ```
275
+
276
+ ### Releasing
277
+
278
+ See [RELEASING.md](RELEASING.md) for the one-time PyPI/GitHub setup, version/tag workflow, and TestPyPI/PyPI publishing steps.
@@ -0,0 +1,83 @@
1
+ [project]
2
+ name = "adagio-cli"
3
+ version = "0.1.0a1"
4
+ description = "Command-line runner for Adagio pipeline files."
5
+ readme = "README.md"
6
+ requires-python = ">=3.10"
7
+ authors = [{ name = "Cymis" }]
8
+ license = "MIT"
9
+ license-files = ["LICENSE"]
10
+ keywords = ["adagio", "bioinformatics", "cli", "pipelines", "qiime2", "workflow"]
11
+ classifiers = [
12
+ "Development Status :: 3 - Alpha",
13
+ "Environment :: Console",
14
+ "Intended Audience :: Developers",
15
+ "Intended Audience :: Science/Research",
16
+ "License :: OSI Approved :: MIT License",
17
+ "Programming Language :: Python :: 3",
18
+ "Programming Language :: Python :: 3 :: Only",
19
+ "Programming Language :: Python :: 3.10",
20
+ "Programming Language :: Python :: 3.11",
21
+ "Programming Language :: Python :: 3.12",
22
+ "Topic :: Scientific/Engineering :: Bio-Informatics",
23
+ "Topic :: Software Development :: Libraries :: Python Modules",
24
+ ]
25
+ dependencies = [
26
+ "cyclopts>=4.5.3",
27
+ "pydantic>=2.12.5",
28
+ "rich>=14.1.0",
29
+ "parsl>=2024.12.16",
30
+ "tomli>=2.2.1; python_version < '3.11'",
31
+ ]
32
+
33
+ [project.urls]
34
+ Homepage = "https://github.com/cymis/adagio-cli"
35
+ Repository = "https://github.com/cymis/adagio-cli"
36
+ Issues = "https://github.com/cymis/adagio-cli/issues"
37
+ Changelog = "https://github.com/cymis/adagio-cli/blob/dev/CHANGELOG.md"
38
+
39
+ [dependency-groups]
40
+ dev = [
41
+ "build>=1.2.2",
42
+ "pytest>=8.4.0",
43
+ "ruff>=0.13.0",
44
+ "twine>=6.2.0",
45
+ ]
46
+
47
+ [project.scripts]
48
+ adagio = "adagio.cli.main:main"
49
+
50
+ [build-system]
51
+ requires = ["uv_build>=0.8.17,<0.9.0"]
52
+ build-backend = "uv_build"
53
+
54
+ [tool.uv.build-backend]
55
+ module-name = "adagio"
56
+
57
+ [tool.ruff.format]
58
+ quote-style = "double"
59
+ indent-style = "space"
60
+ docstring-code-format = true
61
+
62
+ [tool.ruff.lint.isort]
63
+
64
+
65
+ known-first-party = ["adagio"]
66
+ section-order = [
67
+ "future",
68
+ "standard-library",
69
+ "third-party",
70
+ "first-party",
71
+ "local-folder",
72
+ ]
73
+ [tool.mypy]
74
+ plugins = ['pydantic.mypy']
75
+
76
+ [[tool.mypy.overrides]]
77
+
78
+ module = ["qiime2.*"]
79
+ ignore_missing_imports = true
80
+
81
+ [tool.pytest.ini_options]
82
+ addopts = "-ra"
83
+ testpaths = ["tests"]
@@ -0,0 +1,15 @@
1
+ from importlib.metadata import PackageNotFoundError, version
2
+
3
+
4
+ def _resolve_version() -> str:
5
+ for dist_name in ("adagio-cli", "adagio"):
6
+ try:
7
+ return version(dist_name)
8
+ except PackageNotFoundError:
9
+ continue
10
+ return "0.0.0"
11
+
12
+
13
+ __version__ = _resolve_version()
14
+
15
+ __all__ = ["__version__"]