Offline, one-way, no-in-place migration tools for legacy nirs4all artifacts.
Project description
nirs4all-tools
Offline, one-way, no-in-place migration tools for legacy nirs4all
artifacts (workspaces, .n4a bundles, loose prediction files).
This is the standalone home for the legacy readers that used to live inside
the nirs4all runtime. The V1 runtime carries no legacy reader and no
auto-migration trigger; instead, nirs4all-tools converts old stores into
the format the runtime already reads (nirs4all-workspace-v2), so users keep
their predictions/pipelines without the runtime ever opening a legacy store.
Status: first transform (lane
L18, lockLOCK-MIG, decisionDEC-MIG-001). The CLI surface, the no-in-place safety machinery, detection, the contract vocabulary,inspect,migrate --dry-run, and--copy-onlyare implemented. The first schema transform lowerssqlite-workspace-legacy-arraysmetadata into a fresh workspace-v2store.sqlite; legacy array rows are lowered into runtime-readablearrays/<dataset>.parquetsidecars when the optionalparquetextra is installed, and the raw rows are still preserved as checksummed JSONL audit provenance. A native-results-v1 preview can lower one current dag-ml native results directory into runtime-readable workspace-v2 metadata plus array sidecars after strict hash/schema preflight. A legacyruns/*/*/manifest.yamlpreview can lower one completed run when it references one complete*_predictions.jsonpayload and the YAML/JSON metadata agree.
The one contract: no-in-place
Every command guarantees the source is never modified:
- the source is opened read-only (SQLite via
file:…?mode=ro&immutable=1); --outputis mandatory and must be disjoint from the input (aliasing / nesting is refused, exit40);- the output must be empty unless
--resume; - the whole source tree is snapshotted
(path, size, mtime_ns)before and after every run — including failure and abort paths — and asserted byte-for-byte identical (a mismatch is exit70).
Install
pip install -e ".[dev]" # scaffold core is pure standard library
pip install -e ".[duckdb]" # add DuckDB-source reading (optional)
pip install -e ".[parquet]" # add Parquet lowering/validation (optional)
CLI
nirs4all-tools --version
# Read-only: detect what a legacy location contains.
nirs4all-tools legacy inspect <input> [--format json|text] [--report PATH]
# Convert into a fresh output (one-way, no-in-place).
nirs4all-tools legacy migrate <input> --output DIR --target nirs4all-workspace-v2 \
[--manifest PATH] [--report PATH] [--id-map PATH] [--unsupported-report PATH] \
[--checksums sha256] [--dry-run | --verify] [--strict | --best-effort] \
[--copy-only] [--resume] [--trusted-load-joblib]
# Verify an output against its manifest (reads no source).
nirs4all-tools legacy verify <output-dir> --manifest PATH [--report PATH]
Current schema-transform support is intentionally narrow:
sqlite-workspace-legacy-arraysmetadata is lowered tostore.sqliteschema v2;- the legacy
prediction_arraystable is decoded offline, lowered to the runtime array sidecar schema (arrays/<dataset>.parquet), and also preserved inpreserved/legacy-prediction-arrays.jsonlfor audit; - one standalone current dag-ml
native-results-v1directory with a validscore_set_hashand canonicalpredictions.parquetprojection is lowered to workspace-v2 run/pipeline/chain/prediction/artifact metadata plus runtime-readablearrays/<dataset>.parquetsidecars; the original native payload is still checksummed underpreserved/native-results-v1/; - malformed, older, mixed, or multi-artifact
native-results-v1sources fail--strictwith a machine-checkable schema/preflight cause, and best-effort mode preserves them opaque with the same reason in the manifest; - one standalone complete
*_predictions.jsonloose-prediction payload is lowered to workspace-v2 run/pipeline/chain/prediction metadata plus runtime-readablearrays/<dataset>.parquetsidecars when theparquetextra is installed; the original loose JSON and sibling metadata files are still checksummed underpreserved/loose-predictions/; - one standalone legacy
runs/*/*/manifest.yamltree is lowered when its single manifest points to one complete*_predictions.jsonunder the same source root andrun_id,pipeline_id, dataset, model, and preprocessing metadata match; the manifest tree and referenced prediction payload remain checksummed underpreserved/; .n4a,.n4a.py, and non-lowerablenative-results-v1artifacts are preserved as opaque checksummed payloads underpreserved/with an empty workspace-v2 store;- non-lowerable legacy workspace payloads such as
store.duckdb, legacyruns/trees outside the single-manifest preview, incomplete or mixed loose prediction files, and already-v2 SQLite stores are also preserved opaque by default in best-effort mode;--strictrefuses them before writing; - every real migration writes
unsupported-report.jsonalongside the manifest, report, and id-map; dry runs write the same machine-readable unsupported report only when--unsupported-report PATHis provided; - best-effort migration exits
10only when semantic lowering is unavailable and content must be preserved opaque; --strictrequires semantic lowering and exits0for fully lowered array sources or native-results metadata previews.
Exit codes
| Code | Meaning |
|---|---|
0 |
success, no warnings |
10 |
migrated with warnings (best-effort preserved opaque / non-fatal skips) |
20 |
unsupported input (unknown / forward-version source, or strict unsupported item) |
30 |
verification failed |
40 |
refused by policy (in-place / aliased output, non-empty output without --resume) |
70 |
internal error (incl. source-tree integrity assertion failure) |
Contracts
Four durable JSON contracts are emitted alongside a migrated workspace
(SW4_MIG_CONVERTER_spec.md §7–10):
legacy_migration_manifest.v1— the exhaustive inventory + checksum + id-map ledger;legacy_migration_report.v1— the human/UX digest + next action;legacy_id_map.v1— the never-lossy old→new id map.legacy_unsupported_report.v1— the machine-readable list of unsupported, refused, or opaque-preserved items.
Development
ruff check .
mypy
pytest
Checked-in converter goldens live under tests/fixtures/legacy/. They are
small reduced legacy payloads for old workspaces, run/pipeline manifests, and
prediction arrays. Tests copy or materialize them into temporary directories
before migration so the source goldens stay read-only and the no-in-place
contract remains observable.
License
Dual-licensed CeCILL-2.1 OR AGPL-3.0-or-later (plus commercial), consistent
with the nirs4all ecosystem policy. See LICENSE. Contact:
nirs4all-admin@cirad.fr.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file nirs4all_tools-0.0.4.tar.gz.
File metadata
- Download URL: nirs4all_tools-0.0.4.tar.gz
- Upload date:
- Size: 63.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a8320ae7e0683697e98259db7c62073c0c328717a52b5b972837f52b3c595bf7
|
|
| MD5 |
b170863fb38afe278d0f1eea3dbdf3ea
|
|
| BLAKE2b-256 |
88090565884803ac844f7b350247013cd011b15e2aa00336496cf09b5c2d8edc
|
Provenance
The following attestation bundles were made for nirs4all_tools-0.0.4.tar.gz:
Publisher:
publish.yml on GBeurier/nirs4all-tools
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nirs4all_tools-0.0.4.tar.gz -
Subject digest:
a8320ae7e0683697e98259db7c62073c0c328717a52b5b972837f52b3c595bf7 - Sigstore transparency entry: 2102215544
- Sigstore integration time:
-
Permalink:
GBeurier/nirs4all-tools@659cdab0074c847ebd474b6e7badda7bdeb361ad -
Branch / Tag:
refs/tags/v0.0.4 - Owner: https://github.com/GBeurier
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@659cdab0074c847ebd474b6e7badda7bdeb361ad -
Trigger Event:
release
-
Statement type:
File details
Details for the file nirs4all_tools-0.0.4-py3-none-any.whl.
File metadata
- Download URL: nirs4all_tools-0.0.4-py3-none-any.whl
- Upload date:
- Size: 52.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7f4d17544e799994b32b8c9caf7c0ceba164afdf917f8faf0c6362e089d4b6b8
|
|
| MD5 |
8e0cc4f676ec2f78a118810beca9e516
|
|
| BLAKE2b-256 |
79997a9b2a60b31d1291dbac9162f8be98fd35be05e5442b745541e8462b9ed4
|
Provenance
The following attestation bundles were made for nirs4all_tools-0.0.4-py3-none-any.whl:
Publisher:
publish.yml on GBeurier/nirs4all-tools
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nirs4all_tools-0.0.4-py3-none-any.whl -
Subject digest:
7f4d17544e799994b32b8c9caf7c0ceba164afdf917f8faf0c6362e089d4b6b8 - Sigstore transparency entry: 2102216097
- Sigstore integration time:
-
Permalink:
GBeurier/nirs4all-tools@659cdab0074c847ebd474b6e7badda7bdeb361ad -
Branch / Tag:
refs/tags/v0.0.4 - Owner: https://github.com/GBeurier
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@659cdab0074c847ebd474b6e7badda7bdeb361ad -
Trigger Event:
release
-
Statement type: