modelctl-mlflow 1.1.2__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,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026
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,312 @@
1
+ Metadata-Version: 2.4
2
+ Name: modelctl-mlflow
3
+ Version: 1.1.2
4
+ Summary: Small MLflow Model Registry utility for versioning arbitrary model payloads.
5
+ Author: rexologue
6
+ License-Expression: MIT
7
+ Keywords: cli,utilities,mlflow,registry
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Operating System :: OS Independent
10
+ Requires-Python: >=3.10
11
+ Description-Content-Type: text/markdown
12
+ License-File: LICENSE
13
+ Requires-Dist: mlflow>=2.9
14
+ Dynamic: license-file
15
+
16
+ # modelctl-mlflow
17
+
18
+ `modelctl` is a small CLI wrapper around MLflow Model Registry for storing, verifying, promoting and pulling arbitrary model payloads.
19
+
20
+ The tool does not try to interpret a payload as a specific ML framework. A registered version is always:
21
+
22
+ ```text
23
+ small metadata package + opaque payload directory
24
+ ```
25
+
26
+ MLflow backend storage keeps metadata: runs, versions, aliases, tags and source URIs. MLflow artifact storage keeps the actual payload bytes.
27
+
28
+ ## Installation
29
+
30
+ Install as a CLI tool with uv:
31
+
32
+ ```bash
33
+ uv tool install modelctl-mlflow
34
+ ```
35
+
36
+ Run once without installing the tool globally:
37
+
38
+ ```bash
39
+ uvx --from modelctl-mlflow modelctl --help
40
+ ```
41
+
42
+ Install with pip:
43
+
44
+ ```bash
45
+ pip install modelctl-mlflow
46
+ ```
47
+
48
+ For local development from a checkout:
49
+
50
+ ```bash
51
+ pip install -e .
52
+ ```
53
+
54
+ or:
55
+
56
+ ```bash
57
+ uv pip install -e .
58
+ ```
59
+
60
+ After installation, the CLI command is:
61
+
62
+ ```bash
63
+ modelctl --help
64
+ ```
65
+
66
+ The PyPI package name is `modelctl-mlflow`; the installed command is `modelctl`.
67
+
68
+ ## Quick start
69
+
70
+ ```bash
71
+ modelctl register ./model my-model
72
+ modelctl list my-model
73
+ modelctl info my-model@champion
74
+ modelctl pull my-model@champion ./downloaded-model
75
+ modelctl verify my-model@champion ./downloaded-model
76
+ modelctl promote my-model 3 champion
77
+ ```
78
+
79
+ Commands print machine-readable JSON to stdout. Human-readable progress and errors are printed to stderr.
80
+
81
+ ## MLflow connection
82
+
83
+ Default tracking URI:
84
+
85
+ ```text
86
+ http://localhost:5000
87
+ ```
88
+
89
+ Override host and port:
90
+
91
+ ```bash
92
+ modelctl list <model_name> --host <host> --port <port>
93
+ ```
94
+
95
+ Or pass a full tracking URI:
96
+
97
+ ```bash
98
+ modelctl list <model_name> --tracking-uri <tracking_uri>
99
+ ```
100
+
101
+ MLflow authentication is handled by MLflow itself through its usual environment variables, for example `MLFLOW_TRACKING_USERNAME` and `MLFLOW_TRACKING_PASSWORD`.
102
+
103
+ ## Register
104
+
105
+ ```bash
106
+ modelctl register <payload_dir> <model_name>
107
+ ```
108
+
109
+ With explicit aliases:
110
+
111
+ ```bash
112
+ modelctl register <payload_dir> <model_name> --alias <alias_a> --alias <alias_b>
113
+ ```
114
+
115
+ Default alias behavior:
116
+
117
+ ```text
118
+ first version -> baseline + champion
119
+ later versions -> candidate
120
+ ```
121
+
122
+ During registration, `modelctl`:
123
+
124
+ ```text
125
+ 1. connects to MLflow
126
+ 2. computes a stable SHA256 payload hash
127
+ 3. starts a short technical MLflow run
128
+ 4. writes metadata files
129
+ 5. logs payload bytes to the artifact store under model/payload
130
+ 6. creates a Model Registry version
131
+ 7. writes modelctl.payload_hash to Model Version tags
132
+ 8. attaches aliases
133
+ ```
134
+
135
+ The registration result is printed as JSON. Human-readable progress is printed to stderr.
136
+
137
+ ## Metadata tags
138
+
139
+ Two optional metadata namespaces are supported:
140
+
141
+ ```text
142
+ general - stable descriptive metadata
143
+ training - training, dataset, evaluation or build metadata
144
+ ```
145
+
146
+ Full metadata dictionaries are stored as JSON artifacts. A flattened searchable projection is also written to MLflow Model Version tags.
147
+
148
+ Register with JSON metadata:
149
+
150
+ ```bash
151
+ modelctl register <payload_dir> <model_name> --general-tags-json <general.json> --training-tags-json <training.json>
152
+ ```
153
+
154
+ Register with inline metadata:
155
+
156
+ ```bash
157
+ modelctl register <payload_dir> <model_name> --general-tag <key>=<value> --training-tag <key>=<value>
158
+ ```
159
+
160
+ Inline values are parsed as JSON when possible, so numbers, booleans, objects and lists are supported.
161
+
162
+ ## Artifact layout
163
+
164
+ Every registered version stores this package in the artifact store:
165
+
166
+ ```text
167
+ model/
168
+ ├── MLmodel
169
+ ├── manifest.json
170
+ ├── payload.sha256.json
171
+ ├── metadata/
172
+ │ ├── general_tags.json
173
+ │ └── training_tags.json
174
+ └── payload/
175
+ └── ... payload contents ...
176
+ ```
177
+
178
+ `model/payload/` contains the actual registered payload.
179
+
180
+ `model/payload.sha256.json` contains the hash contract:
181
+
182
+ ```json
183
+ {
184
+ "created_by": "modelctl",
185
+ "hash_algorithm": "sha256",
186
+ "hash_scope": "payload_tree_v1",
187
+ "payload_hash": "sha256:...",
188
+ "schema_version": "1.0"
189
+ }
190
+ ```
191
+
192
+ The same hash is always written to Model Version tags as:
193
+
194
+ ```text
195
+ modelctl.payload_hash=sha256:...
196
+ modelctl.source_uri=runs:/<run_id>/model
197
+ ```
198
+
199
+ That tag is the fast path for hash-only verification because it can be read from the registry without downloading the payload.
200
+
201
+ ## Pull
202
+
203
+ Download payload only:
204
+
205
+ ```bash
206
+ modelctl pull <model_ref> <output_dir>
207
+ ```
208
+
209
+ Download the full package:
210
+
211
+ ```bash
212
+ modelctl pull <model_ref> <output_dir> --full-package
213
+ ```
214
+
215
+ Supported refs:
216
+
217
+ ```text
218
+ <model_name>@<alias>
219
+ <model_name>:<version>
220
+ models:/<model_name>@<alias>
221
+ models:/<model_name>/<version>
222
+ ```
223
+
224
+ By default, `pull` verifies the downloaded payload hash against `modelctl.payload_hash`. To skip this verification:
225
+
226
+ ```bash
227
+ modelctl pull <model_ref> <output_dir> --no-verify
228
+ ```
229
+
230
+ If the destination already exists, pass `--overwrite`:
231
+
232
+ ```bash
233
+ modelctl pull <model_ref> <output_dir> --overwrite
234
+ ```
235
+
236
+ `pull --overwrite` is intentionally safe: the existing destination is not removed before download. The new artifact is downloaded into a staging directory next to the destination, verified, and only then swapped into place. If download or verification fails, the previous destination is kept.
237
+
238
+ ## Verify
239
+
240
+ Compare an existing directory with the payload hash stored in the registry:
241
+
242
+ ```bash
243
+ modelctl verify <model_ref> <path>
244
+ ```
245
+
246
+ Both payload-only directories and full modelctl packages are accepted. If `<path>` is a full package, `modelctl` verifies `<path>/payload`.
247
+
248
+ Exit codes:
249
+
250
+ ```text
251
+ 0 - hash matches
252
+ 1 - command failed
253
+ 2 - hash mismatch
254
+ ```
255
+
256
+ Example JSON shape:
257
+
258
+ ```json
259
+ {
260
+ "actual_payload_hash": "sha256:...",
261
+ "expected_payload_hash": "sha256:...",
262
+ "matches": true,
263
+ "model_uri": "models:/<model_name>@<alias>",
264
+ "path": "<path>",
265
+ "ref": "<model_ref>"
266
+ }
267
+ ```
268
+
269
+ ## List
270
+
271
+ ```bash
272
+ modelctl list <model_name>
273
+ ```
274
+
275
+ Shows versions, aliases, registry source URI, status, creation time and payload hash.
276
+
277
+ ## Info
278
+
279
+ ```bash
280
+ modelctl info <model_ref>
281
+ ```
282
+
283
+ Shows one resolved registry version with all Model Version tags.
284
+
285
+ ## Promote
286
+
287
+ ```bash
288
+ modelctl promote <model_name> <version> <alias>
289
+ ```
290
+
291
+ Promotion only moves an alias. It does not copy or modify artifacts.
292
+
293
+ ## Hash semantics
294
+
295
+ The payload hash includes:
296
+
297
+ ```text
298
+ relative file paths
299
+ file bytes
300
+ ```
301
+
302
+ The payload hash ignores:
303
+
304
+ ```text
305
+ absolute paths
306
+ file mtimes
307
+ owners
308
+ groups
309
+ permissions
310
+ ```
311
+
312
+ This makes the digest stable across machines, mount points and container environments.
@@ -0,0 +1,297 @@
1
+ # modelctl-mlflow
2
+
3
+ `modelctl` is a small CLI wrapper around MLflow Model Registry for storing, verifying, promoting and pulling arbitrary model payloads.
4
+
5
+ The tool does not try to interpret a payload as a specific ML framework. A registered version is always:
6
+
7
+ ```text
8
+ small metadata package + opaque payload directory
9
+ ```
10
+
11
+ MLflow backend storage keeps metadata: runs, versions, aliases, tags and source URIs. MLflow artifact storage keeps the actual payload bytes.
12
+
13
+ ## Installation
14
+
15
+ Install as a CLI tool with uv:
16
+
17
+ ```bash
18
+ uv tool install modelctl-mlflow
19
+ ```
20
+
21
+ Run once without installing the tool globally:
22
+
23
+ ```bash
24
+ uvx --from modelctl-mlflow modelctl --help
25
+ ```
26
+
27
+ Install with pip:
28
+
29
+ ```bash
30
+ pip install modelctl-mlflow
31
+ ```
32
+
33
+ For local development from a checkout:
34
+
35
+ ```bash
36
+ pip install -e .
37
+ ```
38
+
39
+ or:
40
+
41
+ ```bash
42
+ uv pip install -e .
43
+ ```
44
+
45
+ After installation, the CLI command is:
46
+
47
+ ```bash
48
+ modelctl --help
49
+ ```
50
+
51
+ The PyPI package name is `modelctl-mlflow`; the installed command is `modelctl`.
52
+
53
+ ## Quick start
54
+
55
+ ```bash
56
+ modelctl register ./model my-model
57
+ modelctl list my-model
58
+ modelctl info my-model@champion
59
+ modelctl pull my-model@champion ./downloaded-model
60
+ modelctl verify my-model@champion ./downloaded-model
61
+ modelctl promote my-model 3 champion
62
+ ```
63
+
64
+ Commands print machine-readable JSON to stdout. Human-readable progress and errors are printed to stderr.
65
+
66
+ ## MLflow connection
67
+
68
+ Default tracking URI:
69
+
70
+ ```text
71
+ http://localhost:5000
72
+ ```
73
+
74
+ Override host and port:
75
+
76
+ ```bash
77
+ modelctl list <model_name> --host <host> --port <port>
78
+ ```
79
+
80
+ Or pass a full tracking URI:
81
+
82
+ ```bash
83
+ modelctl list <model_name> --tracking-uri <tracking_uri>
84
+ ```
85
+
86
+ MLflow authentication is handled by MLflow itself through its usual environment variables, for example `MLFLOW_TRACKING_USERNAME` and `MLFLOW_TRACKING_PASSWORD`.
87
+
88
+ ## Register
89
+
90
+ ```bash
91
+ modelctl register <payload_dir> <model_name>
92
+ ```
93
+
94
+ With explicit aliases:
95
+
96
+ ```bash
97
+ modelctl register <payload_dir> <model_name> --alias <alias_a> --alias <alias_b>
98
+ ```
99
+
100
+ Default alias behavior:
101
+
102
+ ```text
103
+ first version -> baseline + champion
104
+ later versions -> candidate
105
+ ```
106
+
107
+ During registration, `modelctl`:
108
+
109
+ ```text
110
+ 1. connects to MLflow
111
+ 2. computes a stable SHA256 payload hash
112
+ 3. starts a short technical MLflow run
113
+ 4. writes metadata files
114
+ 5. logs payload bytes to the artifact store under model/payload
115
+ 6. creates a Model Registry version
116
+ 7. writes modelctl.payload_hash to Model Version tags
117
+ 8. attaches aliases
118
+ ```
119
+
120
+ The registration result is printed as JSON. Human-readable progress is printed to stderr.
121
+
122
+ ## Metadata tags
123
+
124
+ Two optional metadata namespaces are supported:
125
+
126
+ ```text
127
+ general - stable descriptive metadata
128
+ training - training, dataset, evaluation or build metadata
129
+ ```
130
+
131
+ Full metadata dictionaries are stored as JSON artifacts. A flattened searchable projection is also written to MLflow Model Version tags.
132
+
133
+ Register with JSON metadata:
134
+
135
+ ```bash
136
+ modelctl register <payload_dir> <model_name> --general-tags-json <general.json> --training-tags-json <training.json>
137
+ ```
138
+
139
+ Register with inline metadata:
140
+
141
+ ```bash
142
+ modelctl register <payload_dir> <model_name> --general-tag <key>=<value> --training-tag <key>=<value>
143
+ ```
144
+
145
+ Inline values are parsed as JSON when possible, so numbers, booleans, objects and lists are supported.
146
+
147
+ ## Artifact layout
148
+
149
+ Every registered version stores this package in the artifact store:
150
+
151
+ ```text
152
+ model/
153
+ ├── MLmodel
154
+ ├── manifest.json
155
+ ├── payload.sha256.json
156
+ ├── metadata/
157
+ │ ├── general_tags.json
158
+ │ └── training_tags.json
159
+ └── payload/
160
+ └── ... payload contents ...
161
+ ```
162
+
163
+ `model/payload/` contains the actual registered payload.
164
+
165
+ `model/payload.sha256.json` contains the hash contract:
166
+
167
+ ```json
168
+ {
169
+ "created_by": "modelctl",
170
+ "hash_algorithm": "sha256",
171
+ "hash_scope": "payload_tree_v1",
172
+ "payload_hash": "sha256:...",
173
+ "schema_version": "1.0"
174
+ }
175
+ ```
176
+
177
+ The same hash is always written to Model Version tags as:
178
+
179
+ ```text
180
+ modelctl.payload_hash=sha256:...
181
+ modelctl.source_uri=runs:/<run_id>/model
182
+ ```
183
+
184
+ That tag is the fast path for hash-only verification because it can be read from the registry without downloading the payload.
185
+
186
+ ## Pull
187
+
188
+ Download payload only:
189
+
190
+ ```bash
191
+ modelctl pull <model_ref> <output_dir>
192
+ ```
193
+
194
+ Download the full package:
195
+
196
+ ```bash
197
+ modelctl pull <model_ref> <output_dir> --full-package
198
+ ```
199
+
200
+ Supported refs:
201
+
202
+ ```text
203
+ <model_name>@<alias>
204
+ <model_name>:<version>
205
+ models:/<model_name>@<alias>
206
+ models:/<model_name>/<version>
207
+ ```
208
+
209
+ By default, `pull` verifies the downloaded payload hash against `modelctl.payload_hash`. To skip this verification:
210
+
211
+ ```bash
212
+ modelctl pull <model_ref> <output_dir> --no-verify
213
+ ```
214
+
215
+ If the destination already exists, pass `--overwrite`:
216
+
217
+ ```bash
218
+ modelctl pull <model_ref> <output_dir> --overwrite
219
+ ```
220
+
221
+ `pull --overwrite` is intentionally safe: the existing destination is not removed before download. The new artifact is downloaded into a staging directory next to the destination, verified, and only then swapped into place. If download or verification fails, the previous destination is kept.
222
+
223
+ ## Verify
224
+
225
+ Compare an existing directory with the payload hash stored in the registry:
226
+
227
+ ```bash
228
+ modelctl verify <model_ref> <path>
229
+ ```
230
+
231
+ Both payload-only directories and full modelctl packages are accepted. If `<path>` is a full package, `modelctl` verifies `<path>/payload`.
232
+
233
+ Exit codes:
234
+
235
+ ```text
236
+ 0 - hash matches
237
+ 1 - command failed
238
+ 2 - hash mismatch
239
+ ```
240
+
241
+ Example JSON shape:
242
+
243
+ ```json
244
+ {
245
+ "actual_payload_hash": "sha256:...",
246
+ "expected_payload_hash": "sha256:...",
247
+ "matches": true,
248
+ "model_uri": "models:/<model_name>@<alias>",
249
+ "path": "<path>",
250
+ "ref": "<model_ref>"
251
+ }
252
+ ```
253
+
254
+ ## List
255
+
256
+ ```bash
257
+ modelctl list <model_name>
258
+ ```
259
+
260
+ Shows versions, aliases, registry source URI, status, creation time and payload hash.
261
+
262
+ ## Info
263
+
264
+ ```bash
265
+ modelctl info <model_ref>
266
+ ```
267
+
268
+ Shows one resolved registry version with all Model Version tags.
269
+
270
+ ## Promote
271
+
272
+ ```bash
273
+ modelctl promote <model_name> <version> <alias>
274
+ ```
275
+
276
+ Promotion only moves an alias. It does not copy or modify artifacts.
277
+
278
+ ## Hash semantics
279
+
280
+ The payload hash includes:
281
+
282
+ ```text
283
+ relative file paths
284
+ file bytes
285
+ ```
286
+
287
+ The payload hash ignores:
288
+
289
+ ```text
290
+ absolute paths
291
+ file mtimes
292
+ owners
293
+ groups
294
+ permissions
295
+ ```
296
+
297
+ This makes the digest stable across machines, mount points and container environments.
@@ -0,0 +1,7 @@
1
+ """Small MLflow Model Registry utility.
2
+
3
+ The package exposes a command line interface via ``python -m modelctl`` and the
4
+ ``modelctl`` console script declared in ``pyproject.toml``.
5
+ """
6
+
7
+ __version__ = "1.1.2"
@@ -0,0 +1,5 @@
1
+ """Entrypoint for ``python -m modelctl``."""
2
+
3
+ from .cli import main
4
+
5
+ raise SystemExit(main())