dataeval-flow 0.2.2__tar.gz → 0.2.4__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.
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/.gitignore +1 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/PKG-INFO +26 -28
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/README.md +22 -22
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/pyproject.toml +5 -10
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/__main__.py +54 -21
- dataeval_flow-0.2.4/src/dataeval_flow/_env.py +74 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/_logging.py +32 -15
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/_version.py +2 -2
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/coverage/workflow.py +17 -2
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/LICENSE +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/__init__.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/_app/__init__.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/_app/_model/__init__.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/_app/_model/_coerce.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/_app/_model/_discover.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/_app/_model/_execution.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/_app/_model/_introspect.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/_app/_model/_item.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/_app/_model/_registry.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/_app/_model/_state.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/_app/_model/_undo.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/_app/_panes/__init__.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/_app/_panes/_config_pane.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/_app/_panes/_result_pane.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/_app/_panes/_task_pane.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/_app/_panes/_widgets.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/_app/_screens/__init__.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/_app/_screens/_base.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/_app/_screens/_detail.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/_app/_screens/_model.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/_app/_screens/_params.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/_app/_screens/_pathpicker.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/_app/_screens/_section.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/_app/_screens/_settings.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/_app/_viewmodel/__init__.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/_app/_viewmodel/_builder_vm.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/_app/_viewmodel/_model_vm.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/_app/_viewmodel/_rendering.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/_app/_viewmodel/_result_vm.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/_app/_viewmodel/_section_vm.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/_app/app.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/_app/cli.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/_encoding_cli.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/binning.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/cache.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/config/__init__.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/config/_loader.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/config/_merge.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/config/_models.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/config/_paths.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/config/schemas/__init__.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/config/schemas/_dataset.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/config/schemas/_extractor.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/config/schemas/_metadata.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/config/schemas/_preprocessor.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/config/schemas/_task.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/config/schemas/_view.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/config/schemas/_workflow.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/dataset.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/embeddings.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/metadata.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/policy.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/preprocessing.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/preprocessors.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/py.typed +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/runner.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/view.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflow/__init__.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflow/_text_report.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflow/base.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflow/orchestrator.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/__init__.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/_common.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/_ontology.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/analysis/__init__.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/analysis/outputs.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/analysis/params.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/analysis/workflow.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/cleaning/__init__.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/cleaning/_internal.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/cleaning/outputs.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/cleaning/params.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/cleaning/report.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/cleaning/workflow.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/coverage/__init__.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/coverage/ontology.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/coverage/outputs.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/coverage/params.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/coverage/report.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/drift/__init__.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/drift/outputs.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/drift/params.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/drift/report.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/drift/workflow.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/ood/__init__.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/ood/outputs.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/ood/params.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/ood/report.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/ood/workflow.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/parameter_sweep/__init__.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/parameter_sweep/outputs.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/parameter_sweep/params.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/parameter_sweep/workflow.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/prioritization/__init__.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/prioritization/outputs.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/prioritization/params.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/prioritization/report.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/prioritization/workflow.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/splitting/__init__.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/splitting/outputs.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/splitting/params.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/splitting/report.py +0 -0
- {dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/splitting/workflow.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: dataeval-flow
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: DataEval Workflows container for data evaluation
|
|
5
5
|
Project-URL: Homepage, https://github.com/aria-ml/dataeval-flow
|
|
6
6
|
Project-URL: Documentation, https://dataeval-flow.readthedocs.io/
|
|
@@ -19,7 +19,7 @@ Classifier: Topic :: Scientific/Engineering
|
|
|
19
19
|
Classifier: Typing :: Typed
|
|
20
20
|
Requires-Python: <3.15,>=3.10
|
|
21
21
|
Requires-Dist: click>=8.0
|
|
22
|
-
Requires-Dist: dataeval>=1.1.
|
|
22
|
+
Requires-Dist: dataeval>=1.1.1
|
|
23
23
|
Requires-Dist: datamaite[ic,od]==0.4.1
|
|
24
24
|
Requires-Dist: numpy>=1.24.2
|
|
25
25
|
Requires-Dist: pydantic>=2.0
|
|
@@ -49,11 +49,9 @@ Requires-Dist: onnx>=1.15; extra == 'onnx-cu130'
|
|
|
49
49
|
Requires-Dist: onnxruntime-gpu>=1.27; (python_version >= '3.11' and extra != 'onnx-cu126') and extra == 'onnx-cu130'
|
|
50
50
|
Requires-Dist: onnxruntime>=1.20; (python_version == '3.10' and extra != 'onnx-cu126') and extra == 'onnx-cu130'
|
|
51
51
|
Provides-Extra: ontology
|
|
52
|
-
Requires-Dist: dataeval[ontology]
|
|
52
|
+
Requires-Dist: dataeval[ontology]>=1.1.1; extra == 'ontology'
|
|
53
53
|
Provides-Extra: opencv
|
|
54
|
-
Requires-Dist: opencv-python-headless
|
|
55
|
-
Provides-Extra: opencv-fips
|
|
56
|
-
Requires-Dist: opencv-python-headless<4.13.0,>=4.8.0; extra == 'opencv-fips'
|
|
54
|
+
Requires-Dist: opencv-python-headless<4.13.0,>=4.8.0; extra == 'opencv'
|
|
57
55
|
Description-Content-Type: text/markdown
|
|
58
56
|
|
|
59
57
|
<!-- markdownlint-disable MD041 -->
|
|
@@ -165,16 +163,16 @@ at least the minimum CPU/memory above; size memory to your largest dataset.
|
|
|
165
163
|
|
|
166
164
|
```bash
|
|
167
165
|
# 1. Build CUDA 12.6 container
|
|
168
|
-
docker build -f docker/Dockerfile.cu126 -t dataeval:cu126 .
|
|
166
|
+
docker build -f docker/Dockerfile.cu126 -t dataeval-flow:cu126 .
|
|
169
167
|
|
|
170
168
|
# 2. Show help
|
|
171
|
-
docker run dataeval:cu126
|
|
169
|
+
docker run dataeval-flow:cu126
|
|
172
170
|
|
|
173
171
|
# 3. Run with data and output
|
|
174
172
|
docker run --gpus all \
|
|
175
173
|
--mount type=bind,source=/path/to/data,target=/dataeval,readonly \
|
|
176
174
|
--mount type=bind,source=/path/to/output,target=/output \
|
|
177
|
-
dataeval:cu126
|
|
175
|
+
dataeval-flow:cu126
|
|
178
176
|
```
|
|
179
177
|
|
|
180
178
|
## Pulling pre-built images
|
|
@@ -186,13 +184,13 @@ if you don't need to modify the code.
|
|
|
186
184
|
**Rolling channel** — tracks the latest commit on `main`. The tag is overwritten on every merge.
|
|
187
185
|
|
|
188
186
|
```bash
|
|
189
|
-
docker pull harbor.jatic.net/aria/dataeval:cu126 # cpu / cu126 / cu130
|
|
187
|
+
docker pull harbor.jatic.net/aria/dataeval-flow:latest-cu126 # cpu / cu126 / cu130
|
|
190
188
|
```
|
|
191
189
|
|
|
192
190
|
**Pinned release channel** — immutable, version-tagged images cut from `v*` git tags. Use these for reproducible workloads.
|
|
193
191
|
|
|
194
192
|
```bash
|
|
195
|
-
docker pull harbor.jatic.net/aria/dataeval:0.2.
|
|
193
|
+
docker pull harbor.jatic.net/aria/dataeval-flow:0.2.4-cu126
|
|
196
194
|
```
|
|
197
195
|
|
|
198
196
|
**Verifying the signature** — every published image is signed with
|
|
@@ -200,12 +198,12 @@ docker pull harbor.jatic.net/aria/dataeval:0.2.1-cu126
|
|
|
200
198
|
[docker/cosign.pub](docker/cosign.pub).
|
|
201
199
|
|
|
202
200
|
```bash
|
|
203
|
-
cosign verify --key docker/cosign.pub harbor.jatic.net/aria/dataeval:cu126
|
|
201
|
+
cosign verify --key docker/cosign.pub harbor.jatic.net/aria/dataeval-flow:latest-cu126
|
|
204
202
|
```
|
|
205
203
|
|
|
206
|
-
Then
|
|
207
|
-
commands above with the fully-qualified
|
|
208
|
-
(or pinned version) and skip step 1.
|
|
204
|
+
Then replace the locally-built `dataeval-flow:cu126` reference in the Quick Start
|
|
205
|
+
`docker run` commands above with the fully-qualified
|
|
206
|
+
`harbor.jatic.net/aria/dataeval-flow:latest-cu126` (or a pinned version) and skip step 1.
|
|
209
207
|
|
|
210
208
|
> **Note on feature branches.** Containers are only built and published from
|
|
211
209
|
> `main` and release tags — no image is produced for MRs or topic branches. If
|
|
@@ -257,7 +255,7 @@ docker run --gpus all \
|
|
|
257
255
|
--user "$(id -u):$(id -g)" \
|
|
258
256
|
--mount type=bind,source=/path/to/data,target=/dataeval,readonly \
|
|
259
257
|
--mount type=bind,source=/path/to/output,target=/output \
|
|
260
|
-
dataeval:cu126
|
|
258
|
+
dataeval-flow:cu126
|
|
261
259
|
```
|
|
262
260
|
|
|
263
261
|
#### Option 2: Open directory permissions
|
|
@@ -279,7 +277,7 @@ docker run --gpus all \
|
|
|
279
277
|
-e DATAEVAL_DATA=/data \
|
|
280
278
|
--mount type=bind,source=/path/to/data,target=/data,readonly \
|
|
281
279
|
--mount type=bind,source=/path/to/output,target=/output \
|
|
282
|
-
dataeval:cu126
|
|
280
|
+
dataeval-flow:cu126
|
|
283
281
|
```
|
|
284
282
|
|
|
285
283
|
## Environment Variables
|
|
@@ -320,7 +318,7 @@ options, precedence, and examples — via its help command, which is also the
|
|
|
320
318
|
default when the container runs with no pipeline arguments:
|
|
321
319
|
|
|
322
320
|
```bash
|
|
323
|
-
docker run dataeval:cu126 --help
|
|
321
|
+
docker run dataeval-flow:cu126 --help
|
|
324
322
|
```
|
|
325
323
|
|
|
326
324
|
The library form exposes the same options via `python -m dataeval_flow --help`.
|
|
@@ -340,13 +338,13 @@ To specify a config path explicitly:
|
|
|
340
338
|
docker run --gpus all \
|
|
341
339
|
--mount type=bind,source=/path/to/data,target=/dataeval,readonly \
|
|
342
340
|
--mount type=bind,source=/path/to/output,target=/output \
|
|
343
|
-
dataeval:cu126 --config config/
|
|
341
|
+
dataeval-flow:cu126 --config config/
|
|
344
342
|
|
|
345
343
|
# Single config file
|
|
346
344
|
docker run --gpus all \
|
|
347
345
|
--mount type=bind,source=/path/to/data,target=/dataeval,readonly \
|
|
348
346
|
--mount type=bind,source=/path/to/output,target=/output \
|
|
349
|
-
dataeval:cu126 --config params.yaml
|
|
347
|
+
dataeval-flow:cu126 --config params.yaml
|
|
350
348
|
```
|
|
351
349
|
|
|
352
350
|
Dataset and model paths in config files are resolved relative to the data root (`/dataeval` by default).
|
|
@@ -355,10 +353,10 @@ Dataset and model paths in config files are resolved relative to the data root (
|
|
|
355
353
|
|
|
356
354
|
A `datasets` entry selects its loader with `format`:
|
|
357
355
|
|
|
358
|
-
| `format` | Structure | Split selection
|
|
359
|
-
| -------------- | ------------------------------------------------------------- |
|
|
360
|
-
| `huggingface` | HuggingFace arrow dataset or dataset dict | `split:` (omit for a single split)
|
|
361
|
-
| `image_folder` | Directory of images, optionally one subdirectory per class | n/a
|
|
356
|
+
| `format` | Structure | Split selection |
|
|
357
|
+
| -------------- | ------------------------------------------------------------- | ----------------------------------- |
|
|
358
|
+
| `huggingface` | HuggingFace arrow dataset or dataset dict | `split:` (omit for a single split) |
|
|
359
|
+
| `image_folder` | Directory of images, optionally one subdirectory per class | n/a |
|
|
362
360
|
| `coco` | COCO images plus a JSON annotation file | `annotations_file:` + `images_dir:` |
|
|
363
361
|
| `yolo` | Ultralytics root — `data.yaml` plus image/label trees | `split:` (omit to load every split) |
|
|
364
362
|
|
|
@@ -373,12 +371,12 @@ guide for the full field list of each format.
|
|
|
373
371
|
For machines without NVIDIA GPU:
|
|
374
372
|
|
|
375
373
|
```bash
|
|
376
|
-
docker build -f docker/Dockerfile.cpu -t dataeval:cpu .
|
|
377
|
-
docker run dataeval:cpu # Shows help
|
|
374
|
+
docker build -f docker/Dockerfile.cpu -t dataeval-flow:cpu .
|
|
375
|
+
docker run dataeval-flow:cpu # Shows help
|
|
378
376
|
docker run \
|
|
379
377
|
--mount type=bind,source=/path/to/data,target=/dataeval,readonly \
|
|
380
378
|
--mount type=bind,source=/path/to/output,target=/output \
|
|
381
|
-
dataeval:cpu
|
|
379
|
+
dataeval-flow:cpu
|
|
382
380
|
```
|
|
383
381
|
|
|
384
382
|
## CLI Modes
|
|
@@ -549,7 +547,7 @@ pip install dataeval-flow
|
|
|
549
547
|
`torchvision` is not installed by default — it is imported lazily and is only needed
|
|
550
548
|
for preprocessing pipelines, the torchvision dataset adapter, and the TUI's transform
|
|
551
549
|
discovery. Install it together with `torch` in step 1 so both come from the same index.
|
|
552
|
-
Feature extras (`onnx`, `onnx-cu126`, `onnx-cu130`, `opencv`, `
|
|
550
|
+
Feature extras (`onnx`, `onnx-cu126`, `onnx-cu130`, `opencv`, `app`, `ontology`) work normally under
|
|
553
551
|
pip and are independent of the PyTorch variant:
|
|
554
552
|
|
|
555
553
|
```bash
|
|
@@ -107,16 +107,16 @@ at least the minimum CPU/memory above; size memory to your largest dataset.
|
|
|
107
107
|
|
|
108
108
|
```bash
|
|
109
109
|
# 1. Build CUDA 12.6 container
|
|
110
|
-
docker build -f docker/Dockerfile.cu126 -t dataeval:cu126 .
|
|
110
|
+
docker build -f docker/Dockerfile.cu126 -t dataeval-flow:cu126 .
|
|
111
111
|
|
|
112
112
|
# 2. Show help
|
|
113
|
-
docker run dataeval:cu126
|
|
113
|
+
docker run dataeval-flow:cu126
|
|
114
114
|
|
|
115
115
|
# 3. Run with data and output
|
|
116
116
|
docker run --gpus all \
|
|
117
117
|
--mount type=bind,source=/path/to/data,target=/dataeval,readonly \
|
|
118
118
|
--mount type=bind,source=/path/to/output,target=/output \
|
|
119
|
-
dataeval:cu126
|
|
119
|
+
dataeval-flow:cu126
|
|
120
120
|
```
|
|
121
121
|
|
|
122
122
|
## Pulling pre-built images
|
|
@@ -128,13 +128,13 @@ if you don't need to modify the code.
|
|
|
128
128
|
**Rolling channel** — tracks the latest commit on `main`. The tag is overwritten on every merge.
|
|
129
129
|
|
|
130
130
|
```bash
|
|
131
|
-
docker pull harbor.jatic.net/aria/dataeval:cu126 # cpu / cu126 / cu130
|
|
131
|
+
docker pull harbor.jatic.net/aria/dataeval-flow:latest-cu126 # cpu / cu126 / cu130
|
|
132
132
|
```
|
|
133
133
|
|
|
134
134
|
**Pinned release channel** — immutable, version-tagged images cut from `v*` git tags. Use these for reproducible workloads.
|
|
135
135
|
|
|
136
136
|
```bash
|
|
137
|
-
docker pull harbor.jatic.net/aria/dataeval:0.2.
|
|
137
|
+
docker pull harbor.jatic.net/aria/dataeval-flow:0.2.4-cu126
|
|
138
138
|
```
|
|
139
139
|
|
|
140
140
|
**Verifying the signature** — every published image is signed with
|
|
@@ -142,12 +142,12 @@ docker pull harbor.jatic.net/aria/dataeval:0.2.1-cu126
|
|
|
142
142
|
[docker/cosign.pub](docker/cosign.pub).
|
|
143
143
|
|
|
144
144
|
```bash
|
|
145
|
-
cosign verify --key docker/cosign.pub harbor.jatic.net/aria/dataeval:cu126
|
|
145
|
+
cosign verify --key docker/cosign.pub harbor.jatic.net/aria/dataeval-flow:latest-cu126
|
|
146
146
|
```
|
|
147
147
|
|
|
148
|
-
Then
|
|
149
|
-
commands above with the fully-qualified
|
|
150
|
-
(or pinned version) and skip step 1.
|
|
148
|
+
Then replace the locally-built `dataeval-flow:cu126` reference in the Quick Start
|
|
149
|
+
`docker run` commands above with the fully-qualified
|
|
150
|
+
`harbor.jatic.net/aria/dataeval-flow:latest-cu126` (or a pinned version) and skip step 1.
|
|
151
151
|
|
|
152
152
|
> **Note on feature branches.** Containers are only built and published from
|
|
153
153
|
> `main` and release tags — no image is produced for MRs or topic branches. If
|
|
@@ -199,7 +199,7 @@ docker run --gpus all \
|
|
|
199
199
|
--user "$(id -u):$(id -g)" \
|
|
200
200
|
--mount type=bind,source=/path/to/data,target=/dataeval,readonly \
|
|
201
201
|
--mount type=bind,source=/path/to/output,target=/output \
|
|
202
|
-
dataeval:cu126
|
|
202
|
+
dataeval-flow:cu126
|
|
203
203
|
```
|
|
204
204
|
|
|
205
205
|
#### Option 2: Open directory permissions
|
|
@@ -221,7 +221,7 @@ docker run --gpus all \
|
|
|
221
221
|
-e DATAEVAL_DATA=/data \
|
|
222
222
|
--mount type=bind,source=/path/to/data,target=/data,readonly \
|
|
223
223
|
--mount type=bind,source=/path/to/output,target=/output \
|
|
224
|
-
dataeval:cu126
|
|
224
|
+
dataeval-flow:cu126
|
|
225
225
|
```
|
|
226
226
|
|
|
227
227
|
## Environment Variables
|
|
@@ -262,7 +262,7 @@ options, precedence, and examples — via its help command, which is also the
|
|
|
262
262
|
default when the container runs with no pipeline arguments:
|
|
263
263
|
|
|
264
264
|
```bash
|
|
265
|
-
docker run dataeval:cu126 --help
|
|
265
|
+
docker run dataeval-flow:cu126 --help
|
|
266
266
|
```
|
|
267
267
|
|
|
268
268
|
The library form exposes the same options via `python -m dataeval_flow --help`.
|
|
@@ -282,13 +282,13 @@ To specify a config path explicitly:
|
|
|
282
282
|
docker run --gpus all \
|
|
283
283
|
--mount type=bind,source=/path/to/data,target=/dataeval,readonly \
|
|
284
284
|
--mount type=bind,source=/path/to/output,target=/output \
|
|
285
|
-
dataeval:cu126 --config config/
|
|
285
|
+
dataeval-flow:cu126 --config config/
|
|
286
286
|
|
|
287
287
|
# Single config file
|
|
288
288
|
docker run --gpus all \
|
|
289
289
|
--mount type=bind,source=/path/to/data,target=/dataeval,readonly \
|
|
290
290
|
--mount type=bind,source=/path/to/output,target=/output \
|
|
291
|
-
dataeval:cu126 --config params.yaml
|
|
291
|
+
dataeval-flow:cu126 --config params.yaml
|
|
292
292
|
```
|
|
293
293
|
|
|
294
294
|
Dataset and model paths in config files are resolved relative to the data root (`/dataeval` by default).
|
|
@@ -297,10 +297,10 @@ Dataset and model paths in config files are resolved relative to the data root (
|
|
|
297
297
|
|
|
298
298
|
A `datasets` entry selects its loader with `format`:
|
|
299
299
|
|
|
300
|
-
| `format` | Structure | Split selection
|
|
301
|
-
| -------------- | ------------------------------------------------------------- |
|
|
302
|
-
| `huggingface` | HuggingFace arrow dataset or dataset dict | `split:` (omit for a single split)
|
|
303
|
-
| `image_folder` | Directory of images, optionally one subdirectory per class | n/a
|
|
300
|
+
| `format` | Structure | Split selection |
|
|
301
|
+
| -------------- | ------------------------------------------------------------- | ----------------------------------- |
|
|
302
|
+
| `huggingface` | HuggingFace arrow dataset or dataset dict | `split:` (omit for a single split) |
|
|
303
|
+
| `image_folder` | Directory of images, optionally one subdirectory per class | n/a |
|
|
304
304
|
| `coco` | COCO images plus a JSON annotation file | `annotations_file:` + `images_dir:` |
|
|
305
305
|
| `yolo` | Ultralytics root — `data.yaml` plus image/label trees | `split:` (omit to load every split) |
|
|
306
306
|
|
|
@@ -315,12 +315,12 @@ guide for the full field list of each format.
|
|
|
315
315
|
For machines without NVIDIA GPU:
|
|
316
316
|
|
|
317
317
|
```bash
|
|
318
|
-
docker build -f docker/Dockerfile.cpu -t dataeval:cpu .
|
|
319
|
-
docker run dataeval:cpu # Shows help
|
|
318
|
+
docker build -f docker/Dockerfile.cpu -t dataeval-flow:cpu .
|
|
319
|
+
docker run dataeval-flow:cpu # Shows help
|
|
320
320
|
docker run \
|
|
321
321
|
--mount type=bind,source=/path/to/data,target=/dataeval,readonly \
|
|
322
322
|
--mount type=bind,source=/path/to/output,target=/output \
|
|
323
|
-
dataeval:cpu
|
|
323
|
+
dataeval-flow:cpu
|
|
324
324
|
```
|
|
325
325
|
|
|
326
326
|
## CLI Modes
|
|
@@ -491,7 +491,7 @@ pip install dataeval-flow
|
|
|
491
491
|
`torchvision` is not installed by default — it is imported lazily and is only needed
|
|
492
492
|
for preprocessing pipelines, the torchvision dataset adapter, and the TUI's transform
|
|
493
493
|
discovery. Install it together with `torch` in step 1 so both come from the same index.
|
|
494
|
-
Feature extras (`onnx`, `onnx-cu126`, `onnx-cu130`, `opencv`, `
|
|
494
|
+
Feature extras (`onnx`, `onnx-cu126`, `onnx-cu130`, `opencv`, `app`, `ontology`) work normally under
|
|
495
495
|
pip and are independent of the PyTorch variant:
|
|
496
496
|
|
|
497
497
|
```bash
|
|
@@ -19,7 +19,7 @@ classifiers = [
|
|
|
19
19
|
]
|
|
20
20
|
dependencies = [
|
|
21
21
|
"click>=8.0",
|
|
22
|
-
"dataeval>=1.1.
|
|
22
|
+
"dataeval>=1.1.1",
|
|
23
23
|
"datamaite[ic,od]==0.4.1",
|
|
24
24
|
"numpy>=1.24.2",
|
|
25
25
|
"pydantic>=2.0",
|
|
@@ -51,10 +51,9 @@ onnx-cu130 = [
|
|
|
51
51
|
"onnxruntime>=1.20; python_version == '3.10' and extra != 'onnx-cu126'", # CUDA 13.0 is not supported on Python 3.10
|
|
52
52
|
"onnxruntime-gpu>=1.27; python_version >= '3.11' and extra != 'onnx-cu126'",
|
|
53
53
|
]
|
|
54
|
-
opencv = ["opencv-python-headless>=4.8.0"]
|
|
55
|
-
opencv-fips = ["opencv-python-headless>=4.8.0,<4.13.0"] # OpenCV 4.13 and higher are not FIPS compliant
|
|
54
|
+
opencv = ["opencv-python-headless>=4.8.0,<4.13.0"] # OpenCV 4.13 and higher are not FIPS compliant
|
|
56
55
|
app = ["textual>=3.0"]
|
|
57
|
-
ontology = ["dataeval[ontology]
|
|
56
|
+
ontology = ["dataeval[ontology]>=1.1.1"]
|
|
58
57
|
|
|
59
58
|
[project.urls]
|
|
60
59
|
Homepage = "https://github.com/aria-ml/dataeval-flow"
|
|
@@ -167,10 +166,6 @@ conflicts = [
|
|
|
167
166
|
{ extra = "onnx" },
|
|
168
167
|
{ extra = "onnx-cu126" },
|
|
169
168
|
{ extra = "onnx-cu130" },
|
|
170
|
-
],
|
|
171
|
-
[
|
|
172
|
-
{ extra = "opencv" },
|
|
173
|
-
{ extra = "opencv-fips" },
|
|
174
169
|
]
|
|
175
170
|
]
|
|
176
171
|
|
|
@@ -332,7 +327,7 @@ ignore = [
|
|
|
332
327
|
"C416",
|
|
333
328
|
]
|
|
334
329
|
fixable = ["ALL"]
|
|
335
|
-
per-file-ignores = { "tests/*" = ["ANN", "S101", "D", "SLF001", "ARG002", "PT019"], "docs/*" = ["D", "E402", "E501", "S101"], "verification/*" = ["ANN", "S101", "D", "SLF001", "ARG001", "ARG002", "PT011", "PT019"] }
|
|
330
|
+
per-file-ignores = { "tests/*" = ["ANN", "S101", "D", "SLF001", "ARG002", "PT019"], "docs/*" = ["D", "E402", "E501", "S101"], "verification/*" = ["ANN", "S101", "D", "SLF001", "ARG001", "ARG002", "PT011", "PT019"], "scripts/*" = ["C901", "D", "S"] }
|
|
336
331
|
|
|
337
332
|
[tool.ruff.lint.pydocstyle]
|
|
338
333
|
convention = "pep257"
|
|
@@ -347,5 +342,5 @@ indent-style = "space"
|
|
|
347
342
|
# --- Codespell ---
|
|
348
343
|
|
|
349
344
|
[tool.codespell]
|
|
350
|
-
skip = "./*env*,./output,./htmlcov,./.nox,*.lock,./docs/source/notebooks/*,./docker/cosign.pub,./docker/Dockerfile.*,*.onnx"
|
|
345
|
+
skip = "./*env*,./output,./specs,./htmlcov,./.nox,*.lock,./docs/source/notebooks/*,./docker/cosign.pub,./docker/Dockerfile.*,*.onnx"
|
|
351
346
|
ignore-words-list = ["statics"]
|
|
@@ -3,11 +3,12 @@
|
|
|
3
3
|
|
|
4
4
|
import argparse
|
|
5
5
|
import logging
|
|
6
|
-
import os
|
|
7
6
|
import sys
|
|
8
7
|
from pathlib import Path
|
|
9
8
|
from typing import NoReturn
|
|
10
9
|
|
|
10
|
+
from dataeval_flow._env import env_bool, env_choice, env_int, env_list, env_path
|
|
11
|
+
|
|
11
12
|
_logger = logging.getLogger(__name__)
|
|
12
13
|
|
|
13
14
|
|
|
@@ -41,36 +42,43 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
41
42
|
"-c",
|
|
42
43
|
"--config",
|
|
43
44
|
type=Path,
|
|
44
|
-
default=
|
|
45
|
-
help=
|
|
45
|
+
default=env_path("DATAEVAL_CONFIG"),
|
|
46
|
+
help=(
|
|
47
|
+
"Path to config file or folder (default: $DATAEVAL_CONFIG). If omitted, "
|
|
48
|
+
"auto-discovers YAML/JSON at the data root."
|
|
49
|
+
),
|
|
46
50
|
)
|
|
47
|
-
|
|
48
|
-
_data_default = os.environ.get("DATAEVAL_DATA")
|
|
49
51
|
parser.add_argument(
|
|
50
52
|
"-d",
|
|
51
53
|
"--data",
|
|
52
54
|
type=Path,
|
|
53
|
-
default=
|
|
55
|
+
default=env_path("DATAEVAL_DATA"),
|
|
54
56
|
help="Root directory for data files (default: $DATAEVAL_DATA or current directory)",
|
|
55
57
|
)
|
|
56
|
-
|
|
57
|
-
_output_default = os.environ.get("DATAEVAL_OUTPUT")
|
|
58
58
|
parser.add_argument(
|
|
59
59
|
"-o",
|
|
60
60
|
"--output",
|
|
61
61
|
type=Path,
|
|
62
|
-
default=
|
|
62
|
+
default=env_path("DATAEVAL_OUTPUT"),
|
|
63
63
|
help="Path to output directory for artifacts (default: $DATAEVAL_OUTPUT or None).",
|
|
64
64
|
)
|
|
65
|
-
|
|
66
|
-
_cache_default = os.environ.get("DATAEVAL_CACHE")
|
|
67
65
|
parser.add_argument(
|
|
68
66
|
"-k",
|
|
69
67
|
"--cache",
|
|
70
68
|
type=Path,
|
|
71
|
-
default=
|
|
69
|
+
default=env_path("DATAEVAL_CACHE"),
|
|
72
70
|
help="Directory for disk-backed computation cache (default: $DATAEVAL_CACHE or None).",
|
|
73
71
|
)
|
|
72
|
+
parser.add_argument(
|
|
73
|
+
"--log-format",
|
|
74
|
+
choices=("structured", "plain"),
|
|
75
|
+
default=env_choice("DATAEVAL_LOG_FORMAT", ("structured", "plain")) or "structured",
|
|
76
|
+
help=(
|
|
77
|
+
"Console log format (default: $DATAEVAL_LOG_FORMAT, else structured). "
|
|
78
|
+
"'structured' prefixes each record with an ISO-8601 UTC timestamp and level; "
|
|
79
|
+
"'plain' prints bare messages."
|
|
80
|
+
),
|
|
81
|
+
)
|
|
74
82
|
parser.add_argument(
|
|
75
83
|
"-t",
|
|
76
84
|
"--task",
|
|
@@ -85,10 +93,12 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
85
93
|
)
|
|
86
94
|
parser.add_argument(
|
|
87
95
|
"--fail-on-warning",
|
|
88
|
-
action=
|
|
96
|
+
action=argparse.BooleanOptionalAction,
|
|
97
|
+
default=env_bool("DATAEVAL_FAIL_ON_WARNING") or False,
|
|
89
98
|
help=(
|
|
90
99
|
"Exit non-zero when a task succeeds but reports findings that breached their "
|
|
91
|
-
"health thresholds
|
|
100
|
+
"health thresholds (default: $DATAEVAL_FAIL_ON_WARNING, else off). "
|
|
101
|
+
"Use --no-fail-on-warning to override the environment."
|
|
92
102
|
),
|
|
93
103
|
)
|
|
94
104
|
|
|
@@ -131,14 +141,14 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
131
141
|
"-d",
|
|
132
142
|
"--data",
|
|
133
143
|
type=Path,
|
|
134
|
-
default=
|
|
144
|
+
default=env_path("DATAEVAL_DATA"),
|
|
135
145
|
help="Root directory for data files (default: $DATAEVAL_DATA or current directory)",
|
|
136
146
|
)
|
|
137
147
|
app_parser.add_argument(
|
|
138
148
|
"-k",
|
|
139
149
|
"--cache",
|
|
140
150
|
type=Path,
|
|
141
|
-
default=
|
|
151
|
+
default=env_path("DATAEVAL_CACHE"),
|
|
142
152
|
help="Directory for disk-backed computation cache (embeddings, metadata, stats).",
|
|
143
153
|
)
|
|
144
154
|
|
|
@@ -157,6 +167,7 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
157
167
|
type=Path,
|
|
158
168
|
help="Path to a result.json written by a run",
|
|
159
169
|
)
|
|
170
|
+
# Do not read DATAEVAL_OUTPUT here: encoding defaults to stdout unless -o is explicitly specified.
|
|
160
171
|
encoding_parser.add_argument(
|
|
161
172
|
"-o",
|
|
162
173
|
"--output",
|
|
@@ -221,15 +232,37 @@ def _list_workflows(name: str | None, *, as_json: bool) -> int:
|
|
|
221
232
|
return 0
|
|
222
233
|
|
|
223
234
|
|
|
235
|
+
def apply_env_defaults(args: argparse.Namespace) -> argparse.Namespace:
|
|
236
|
+
"""Apply environment variable defaults that cannot be handled by argparse defaults.
|
|
237
|
+
|
|
238
|
+
For options with ``count`` or ``append`` actions (such as ``--verbose`` and
|
|
239
|
+
``--task``), setting defaults in argparse causes command-line arguments to
|
|
240
|
+
increment or append to the default instead of overriding it. Applying these
|
|
241
|
+
environment variables post-parsing ensures CLI arguments take precedence.
|
|
242
|
+
|
|
243
|
+
``DATAEVAL_TASKS`` applies only to headless execution, not subcommands.
|
|
244
|
+
"""
|
|
245
|
+
if getattr(args, "verbose", 0) == 0:
|
|
246
|
+
args.verbose = env_int("DATAEVAL_VERBOSITY") or 0
|
|
247
|
+
if args.command is None and getattr(args, "task", None) is None:
|
|
248
|
+
args.task = env_list("DATAEVAL_TASKS")
|
|
249
|
+
return args
|
|
250
|
+
|
|
251
|
+
|
|
224
252
|
def parse_args() -> argparse.Namespace:
|
|
225
|
-
"""Parse CLI arguments."""
|
|
253
|
+
"""Parse CLI arguments and apply environment defaults."""
|
|
226
254
|
parser = _build_parser()
|
|
227
|
-
return parser.parse_args()
|
|
255
|
+
return apply_env_defaults(parser.parse_args())
|
|
228
256
|
|
|
229
257
|
|
|
230
258
|
def main() -> NoReturn:
|
|
231
259
|
"""CLI entry point."""
|
|
232
|
-
|
|
260
|
+
try:
|
|
261
|
+
args = parse_args()
|
|
262
|
+
except ValueError as e:
|
|
263
|
+
# Report invalid environment variable values without a traceback.
|
|
264
|
+
print(f"ERROR: {e}", file=sys.stderr)
|
|
265
|
+
sys.exit(1)
|
|
233
266
|
|
|
234
267
|
if args.command == "app":
|
|
235
268
|
try:
|
|
@@ -256,7 +289,7 @@ def main() -> NoReturn:
|
|
|
256
289
|
# refused, and the "commit it" hand-off when it succeeds — is dropped and the user
|
|
257
290
|
# is left with a bare exit code. At INFO because this command's whole output is
|
|
258
291
|
# one artifact and one sentence saying where it went.
|
|
259
|
-
setup_logging(verbosity=max(args.verbose, 2))
|
|
292
|
+
setup_logging(verbosity=max(args.verbose, 2), log_format=args.log_format)
|
|
260
293
|
sys.exit(write_encoding(args.result, args.output, args.task))
|
|
261
294
|
|
|
262
295
|
if args.command == "workflows":
|
|
@@ -273,7 +306,7 @@ def main() -> NoReturn:
|
|
|
273
306
|
# resolution are reported even before the runner configures the file log.
|
|
274
307
|
from dataeval_flow._logging import setup_logging
|
|
275
308
|
|
|
276
|
-
setup_logging(verbosity=args.verbose)
|
|
309
|
+
setup_logging(verbosity=args.verbose, log_format=args.log_format)
|
|
277
310
|
try:
|
|
278
311
|
from dataeval_flow.runner import run
|
|
279
312
|
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"""Environment variable parsing for CLI options.
|
|
2
|
+
|
|
3
|
+
Functions return ``None`` when the variable is unset or blank. Invalid values
|
|
4
|
+
raise ``ValueError``.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import os
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
__all__ = ["env_bool", "env_choice", "env_int", "env_list", "env_path"]
|
|
11
|
+
|
|
12
|
+
_TRUE = ("1", "true", "yes", "on")
|
|
13
|
+
_FALSE = ("0", "false", "no", "off")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _raw(name: str) -> str | None:
|
|
17
|
+
"""Return the stripped value of *name*, or None when unset or blank."""
|
|
18
|
+
value = os.environ.get(name)
|
|
19
|
+
if value is None:
|
|
20
|
+
return None
|
|
21
|
+
stripped = value.strip()
|
|
22
|
+
return stripped or None
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def env_path(name: str) -> Path | None:
|
|
26
|
+
"""Read *name* as a filesystem path."""
|
|
27
|
+
raw = _raw(name)
|
|
28
|
+
return Path(raw) if raw is not None else None
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def env_int(name: str) -> int | None:
|
|
32
|
+
"""Read *name* as an integer, raising ValueError if invalid."""
|
|
33
|
+
raw = _raw(name)
|
|
34
|
+
if raw is None:
|
|
35
|
+
return None
|
|
36
|
+
try:
|
|
37
|
+
return int(raw)
|
|
38
|
+
except ValueError:
|
|
39
|
+
raise ValueError(f"{name} must be an integer, got {raw!r}") from None
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def env_bool(name: str) -> bool | None:
|
|
43
|
+
"""Read *name* as a boolean, raising ValueError if unrecognized."""
|
|
44
|
+
raw = _raw(name)
|
|
45
|
+
if raw is None:
|
|
46
|
+
return None
|
|
47
|
+
lowered = raw.lower()
|
|
48
|
+
if lowered in _TRUE:
|
|
49
|
+
return True
|
|
50
|
+
if lowered in _FALSE:
|
|
51
|
+
return False
|
|
52
|
+
accepted = ", ".join((*_TRUE, *_FALSE))
|
|
53
|
+
raise ValueError(f"{name} must be one of {accepted}; got {raw!r}")
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def env_list(name: str) -> list[str] | None:
|
|
57
|
+
"""Read *name* as a comma-separated list, raising ValueError if empty."""
|
|
58
|
+
raw = _raw(name)
|
|
59
|
+
if raw is None:
|
|
60
|
+
return None
|
|
61
|
+
items = [item.strip() for item in raw.split(",") if item.strip()]
|
|
62
|
+
if not items:
|
|
63
|
+
raise ValueError(f"{name} was set but lists no values: {raw!r}")
|
|
64
|
+
return items
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def env_choice(name: str, choices: tuple[str, ...]) -> str | None:
|
|
68
|
+
"""Read *name* and validate that its value is in *choices*."""
|
|
69
|
+
raw = _raw(name)
|
|
70
|
+
if raw is None:
|
|
71
|
+
return None
|
|
72
|
+
if raw not in choices:
|
|
73
|
+
raise ValueError(f"{name} must be one of {', '.join(choices)}; got {raw!r}")
|
|
74
|
+
return raw
|
|
@@ -32,22 +32,31 @@ _FILE_ROLE = "_dataeval_flow_file"
|
|
|
32
32
|
_FILE_FORMAT = "%(asctime)s [%(levelname)-5s] %(name)s: %(message)s"
|
|
33
33
|
_FILE_DATEFMT = "%Y-%m-%dT%H:%M:%SZ"
|
|
34
34
|
|
|
35
|
+
# Console format for structured mode (ISO-8601 UTC timestamp and log level).
|
|
36
|
+
_CONSOLE_FORMAT = "%(asctime)s [%(levelname)s] %(message)s"
|
|
37
|
+
_CONSOLE_DATEFMT = "%Y-%m-%dT%H:%M:%SZ"
|
|
38
|
+
|
|
35
39
|
|
|
36
40
|
class _ConsoleFormatter(logging.Formatter):
|
|
37
|
-
"""
|
|
41
|
+
"""Console formatter for CLI and container output.
|
|
38
42
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
visible. Tracebacks (``exc_info``) are appended via the standard machinery.
|
|
43
|
+
Supports ``structured`` mode (ISO-8601 UTC timestamp and level prefix)
|
|
44
|
+
and ``plain`` mode (bare messages, with a level prefix only for WARNING
|
|
45
|
+
and above).
|
|
43
46
|
"""
|
|
44
47
|
|
|
45
|
-
def __init__(self) -> None:
|
|
46
|
-
|
|
47
|
-
|
|
48
|
+
def __init__(self, log_format: str = "structured") -> None:
|
|
49
|
+
if log_format == "plain":
|
|
50
|
+
super().__init__("%(message)s")
|
|
51
|
+
self._warn_formatter: logging.Formatter | None = logging.Formatter("%(levelname)s: %(message)s")
|
|
52
|
+
else:
|
|
53
|
+
super().__init__(_CONSOLE_FORMAT, datefmt=_CONSOLE_DATEFMT)
|
|
54
|
+
# Ensure timestamps format in UTC
|
|
55
|
+
self.converter = time.gmtime
|
|
56
|
+
self._warn_formatter = None
|
|
48
57
|
|
|
49
58
|
def format(self, record: logging.LogRecord) -> str:
|
|
50
|
-
if record.levelno >= logging.WARNING:
|
|
59
|
+
if self._warn_formatter is not None and record.levelno >= logging.WARNING:
|
|
51
60
|
return self._warn_formatter.format(record)
|
|
52
61
|
return super().format(record)
|
|
53
62
|
|
|
@@ -72,7 +81,11 @@ class LogMessage:
|
|
|
72
81
|
return self._str
|
|
73
82
|
|
|
74
83
|
|
|
75
|
-
def setup_logging(
|
|
84
|
+
def setup_logging(
|
|
85
|
+
output_dir: Path | None = None,
|
|
86
|
+
verbosity: int = 0,
|
|
87
|
+
log_format: str = "structured",
|
|
88
|
+
) -> None:
|
|
76
89
|
"""Configure root logger with a clean console handler and optional file log.
|
|
77
90
|
|
|
78
91
|
Additive and idempotent: the console (stdout) handler and the file handler
|
|
@@ -81,10 +94,11 @@ def setup_logging(output_dir: Path | None = None, verbosity: int = 0) -> None:
|
|
|
81
94
|
file handler once ``output_dir`` is known — without ever duplicating a
|
|
82
95
|
handler.
|
|
83
96
|
|
|
84
|
-
The console handler uses :class:`_ConsoleFormatter`
|
|
85
|
-
``
|
|
86
|
-
|
|
87
|
-
|
|
97
|
+
The console handler uses :class:`_ConsoleFormatter` in either
|
|
98
|
+
``"structured"`` mode (ISO-8601 UTC timestamp and level prefix) or
|
|
99
|
+
``"plain"`` mode (bare messages, with a level prefix only for WARNING
|
|
100
|
+
and above). The file handler retains the timestamped format at DEBUG
|
|
101
|
+
level.
|
|
88
102
|
|
|
89
103
|
Parameters
|
|
90
104
|
----------
|
|
@@ -93,6 +107,9 @@ def setup_logging(output_dir: Path | None = None, verbosity: int = 0) -> None:
|
|
|
93
107
|
handler is created and output is console-only.
|
|
94
108
|
verbosity : int
|
|
95
109
|
Console verbosity level (0=quiet, 1=report, 2=+INFO, 3=+DEBUG).
|
|
110
|
+
log_format : str
|
|
111
|
+
Console format: ``"structured"`` (timestamp and level prefix) or
|
|
112
|
+
``"plain"`` (bare messages). The file handler is unaffected.
|
|
96
113
|
"""
|
|
97
114
|
global _initialized
|
|
98
115
|
_initialized = True
|
|
@@ -110,7 +127,7 @@ def setup_logging(output_dir: Path | None = None, verbosity: int = 0) -> None:
|
|
|
110
127
|
sh.setLevel(logging.INFO)
|
|
111
128
|
else:
|
|
112
129
|
sh.setLevel(logging.WARNING)
|
|
113
|
-
sh.setFormatter(_ConsoleFormatter())
|
|
130
|
+
sh.setFormatter(_ConsoleFormatter(log_format))
|
|
114
131
|
setattr(sh, _CONSOLE_ROLE, True)
|
|
115
132
|
root.addHandler(sh)
|
|
116
133
|
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '0.2.
|
|
22
|
-
__version_tuple__ = version_tuple = (0, 2,
|
|
21
|
+
__version__ = version = '0.2.4'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 2, 4)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
{dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/coverage/workflow.py
RENAMED
|
@@ -10,6 +10,7 @@ Assessments are organized by the dimension they evaluate:
|
|
|
10
10
|
"""
|
|
11
11
|
|
|
12
12
|
import contextlib
|
|
13
|
+
import inspect
|
|
13
14
|
import logging
|
|
14
15
|
import warnings
|
|
15
16
|
from typing import Any
|
|
@@ -20,6 +21,7 @@ from dataeval import Metadata
|
|
|
20
21
|
from dataeval.core import label_stats
|
|
21
22
|
from dataeval.protocols import AnnotatedDataset, ObjectDetectionTarget
|
|
22
23
|
from pydantic import BaseModel
|
|
24
|
+
from typing_extensions import get_protocol_members
|
|
23
25
|
|
|
24
26
|
from dataeval_flow.binning import attach_binning
|
|
25
27
|
from dataeval_flow.cache import active_cache, get_or_compute_embeddings, get_or_compute_metadata
|
|
@@ -149,12 +151,25 @@ def _run_coverage(
|
|
|
149
151
|
)
|
|
150
152
|
|
|
151
153
|
|
|
154
|
+
#: Protocol members declared by ObjectDetectionTarget.
|
|
155
|
+
_OD_TARGET_MEMBERS = get_protocol_members(ObjectDetectionTarget)
|
|
156
|
+
|
|
157
|
+
_MISSING = object()
|
|
158
|
+
|
|
159
|
+
|
|
152
160
|
def _is_object_detection(dataset: AnnotatedDataset[Any]) -> bool:
|
|
153
|
-
"""
|
|
161
|
+
"""Check whether dataset targets implement the ObjectDetectionTarget protocol.
|
|
162
|
+
|
|
163
|
+
Uses :func:`inspect.getattr_static` to verify member presence without
|
|
164
|
+
invoking property getters, ensuring consistent behavior across Python
|
|
165
|
+
versions.
|
|
166
|
+
"""
|
|
154
167
|
if len(dataset) == 0:
|
|
155
168
|
return False
|
|
156
169
|
datum = dataset[0]
|
|
157
|
-
|
|
170
|
+
if not isinstance(datum, tuple) or len(datum) != 3:
|
|
171
|
+
return False
|
|
172
|
+
return all(inspect.getattr_static(datum[1], name, _MISSING) is not _MISSING for name in _OD_TARGET_MEMBERS)
|
|
158
173
|
|
|
159
174
|
|
|
160
175
|
def _crop_view(
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/_app/_viewmodel/_builder_vm.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/_app/_viewmodel/_section_vm.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/config/schemas/_preprocessor.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/analysis/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/analysis/workflow.py
RENAMED
|
File without changes
|
{dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/cleaning/__init__.py
RENAMED
|
File without changes
|
{dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/cleaning/_internal.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/cleaning/workflow.py
RENAMED
|
File without changes
|
{dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/coverage/__init__.py
RENAMED
|
File without changes
|
{dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/coverage/ontology.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/parameter_sweep/__init__.py
RENAMED
|
File without changes
|
{dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/parameter_sweep/outputs.py
RENAMED
|
File without changes
|
{dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/parameter_sweep/params.py
RENAMED
|
File without changes
|
{dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/parameter_sweep/workflow.py
RENAMED
|
File without changes
|
{dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/prioritization/__init__.py
RENAMED
|
File without changes
|
{dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/prioritization/outputs.py
RENAMED
|
File without changes
|
{dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/prioritization/params.py
RENAMED
|
File without changes
|
{dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/prioritization/report.py
RENAMED
|
File without changes
|
{dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/prioritization/workflow.py
RENAMED
|
File without changes
|
{dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/splitting/__init__.py
RENAMED
|
File without changes
|
{dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/splitting/outputs.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dataeval_flow-0.2.2 → dataeval_flow-0.2.4}/src/dataeval_flow/workflows/splitting/workflow.py
RENAMED
|
File without changes
|