Skip to main content

Dependency-light, soft-importing provider clients over the nirs4all ecosystem's optional dataset and pipeline repositories.

Project description

nirs4all-providers

A dependency-light, soft-importing client layer over the nirs4all ecosystem's optional dataset catalogue and pipeline repository.

This package owns no NIRS, ML, IO, or parsing logic. Each adapter is a thin, uniform client over one sibling repo's real public API, exposed behind a single ProviderPlugin contract and discovered through soft-import. When a backing extra is not installed, the provider degrades to health().available == False instead of failing at import time. Providers are not controllers and never execute ML or write back to the ecosystem.

Scope: read slice. Publish/upload, benchmark arenas, and paper export/publishing stay outside this package. to_dataset_package is present only as a soft, transparent bridge to nirs4all-io, forwarding to the io entrypoint verbatim and returning a typed availability/refusal when the optional io bridge is absent or too old.

nirs4all-benchmarks and nirs4all-papers remain in their owning repositories. They are not provider facets, extras, conformance targets, or release-gate siblings of this package.

Install

PyPI publishing for nirs4all-providers is still pending. Until the package is published, install from a source checkout:

git clone https://github.com/GBeurier/nirs4all-providers.git
cd nirs4all-providers
python -m pip install .              # base: contracts + registry only (pure stdlib)
python -m pip install ".[datasets]"  # + nirs4all-datasets
python -m pip install ".[repository]" # + nirs4all-repository
python -m pip install ".[io]"        # + optional nirs4all-io package bridge
python -m pip install ".[all]"       # datasets + repository + io

Each backing is optional and soft-imported; install only what you consume. The base install depends on nothing but the standard library. .[all] installs the provider backings; bridge extras owned by backing projects stay explicit, for example nirs4all-datasets[nirs4all] for DatasetProvider.to_spectro_dataset().

Use

import nirs4all_providers as providers

providers.provider_ids()        # ('datasets', 'repository')
providers.available_providers() # the subset whose extra is installed

# Health never raises, even when the extra is absent:
providers.provider_health("datasets")
# Health(provider_id='datasets', available=True, reachable=True, version='0.3.4', detail=None)

# Get a typed adapter (raises ProviderUnavailable with a clear pip hint if the extra is missing):
datasets = providers.get_provider("datasets", root="/path/to/catalogue")
datasets.list_datasets(tier="public")        # -> list[card-dict]
datasets.card("some_id")                     # -> card dict | None
ds = datasets.get_dataset("some_id")         # -> NirsDataset (needs nirs4all-datasets)
datasets.retrieve_dataset("some_id")         # -> retrieval status dict; local cache only
sd = datasets.to_spectro_dataset("some_id")  # -> nirs4all SpectroDataset (needs nirs4all-datasets[nirs4all])

The two providers (read surface)

Provider provider_id Backing Read methods Writes
DatasetProvider datasets nirs4all-datasets list_datasets · card · get_dataset · retrieve_dataset · to_spectro_dataset · to_dataset_package · describe_dataset_package local cache (via get() / retrieve())
PipelineProvider repository nirs4all-repository get_pipeline_list · list_pipelines · card · get_pipeline · get_bundle · verify none

Every adapter also exposes the contract trio: provider_id, version(), health(), capabilities().

Lookup methods validate their identifiers before delegating. Use dataset ids with DatasetProvider methods, repository pipeline ids from PipelineProvider.get_pipeline_list() rows with repository get_pipeline(). list_pipelines() remains as a repository compatibility alias.

Benchmarks are consumed through nirs4all-benchmarks itself, where Arena stores, score ledgers, and planning/runner workflows belong. Paper bundles and reproducibility sidecars are consumed through nirs4all-papers itself. This package deliberately exposes no shims, fallbacks, or public provider ids for either domain.

Contract

  • ProviderPlugin — the structural protocol (provider_id, version(), health(), capabilities()). Adapters are duck-typed against it; they need not subclass it.
  • Health{available, reachable, version, detail}. available is import-availability; reachable is an optional network-free deeper probe (None when not performed).
  • Capabilities{serves, executes, writes, portability}. Provider-level and distinct from the operator-level ControllerCapability (LOCK-CAP); the portability field only references CAP-002/CAP-004 for served artifacts.
  • WriteAccessnone / local-cache / gated. The read slice never reaches gated.

Neutral contracts (multi-language)

This Python package is one conformant client of a language-neutral provider contract — not the definition of it. The read slice (datasets · repository) is fundamentally a set of static content artifacts (a catalogue index, identity cards, per-file SHA-256 fetch manifests, descriptors, recipes) served over HTTPS/DOI and integrity-verified. None of that requires Python, so R / JS-WASM / Rust clients reach the same data by porting the schemas + a thin fetcher, never by depending on this package.

The five schemas are frozen in the ecosystem repo (nirs4all-ecosystem/docs/contracts/providers/) and mirrored byte-identically here under src/nirs4all_providers/contracts/:

Schema Governs Behind
provider_descriptor.v1 neutral {provider_id, version, health, capabilities} a client emits provider_id/version()/health()/capabilities()
dataset_card.v2 dataset identity/metadata card DatasetProvider.card / list_datasets
dataset_manifest.v2 per-file SHA-256 fetch manifest dataset byte acquisition
repository_index.v1 pipeline catalogue index PipelineProvider.get_pipeline_list
pipeline_descriptor.v1 pipeline descriptor/card PipelineProvider.card
import nirs4all_providers as providers

# Emit the neutral descriptor for every registered provider (no backing extra required):
providers.all_provider_descriptors()          # -> [ {schema_version, provider_id, version, health, capabilities}, ... ]
providers.provider_descriptor(providers.get_provider("datasets"))  # -> the same shape for one live adapter

# Load / validate against the vendored schemas (pure-stdlib subset validator, no third-party dep):
schema = providers.load_contract_schema("dataset_card.v2")
providers.iter_contract_errors(providers.load_contract_fixture("dataset_card.example"), schema)  # -> [] when valid

For datasets specifically, the non-Python provider is the nirs4all-datasets acquisition contract: catalog/index.json is served/bundled as JSON, n4ds_resolve returns the tier-sanitized descriptor plus the SHA-256-pinned file list, and R/WASM/Rust hosts fetch/verify those files and read canonical Parquet with native tooling. This package may emit a Python provider_descriptor.v1, but R/WASM/Rust do not link to nirs4all_providers to consume datasets.

The R and WASM story is explicit in the ecosystem docs/contracts/providers/README.md: port the schemas and a thin HTTP-GET + SHA-256-verify fetcher over these contracts. Where a language client does not yet exist, the deliverable is the neutral contract plus a gate (GATE-PROV-R, GATE-PROV-WASM, GATE-PROV-NATIVE) — never a Python shim, and never a new dependency on this package.

Contract gate: PYTHONPATH=src python scripts/validate_contracts.py --canonical ../nirs4all-ecosystem/docs/contracts/providers. The CI/release gate requires this canonical byte-identity check; set NIRS4ALL_PROVIDERS_CANONICAL_CONTRACTS only when the ecosystem checkout lives somewhere else.

Boundaries

  • The provider layer is net-new glue only; each backing repo keeps its own package + API and stays the single source of truth for its domain.
  • Not a dependency of nirs4all-core / dag-ml / nirs4all-io. Consumers depend on the contract (the schemas / served artifacts) and may optionally use this Python client; the arrow never points into those packages from here.
  • No adapter re-implements nirs4all / nirs4all-io / nirs4all-methods. nirs4all-io remains the dataset-assembly owner; package methods delegate to nirs4all-io and do not assemble packages here.
  • No network calls originate in this layer, and no ecosystem write-back is performed.
  • nirs4all-drafts / nirs4all-lab are private and out of scope.

Develop

python scripts/ci_gate.py  # version-sync + ruff + mypy + tests + conformance + neutral contracts
ruff check .       # lint
mypy src           # types
pytest -q          # tests (hermetic: fakes, no network, no real backing required)

Release Gate

nirs4all-providers-release-gate
# or
python -m nirs4all_providers.release_gate --json

Release publication also runs the version-sync guard:

nirs4all-providers-version-sync
# explicit release/tag check
nirs4all-providers-version-sync --expected-tag v0.2.6 --json

The canonical version is src/nirs4all_providers/__init__.py::__version__; the expected release tag is v{__version__}. Branch CI and local non-release runs pass without a tag, while GitHub release/tag contexts or NIRS4ALL_PROVIDERS_EXPECTED_TAG must match exactly.

This gate is intentionally stricter than the hermetic unit suite. It fails when a registered backing extra is absent and reports the exact install hint, so a release environment cannot get a false green from skipped sibling conformance. It also fails if any provider advertises execution through Capabilities.executes or an execution-like served method. The only allowed boundary is serving dataset/repository metadata and config; runtime execution, benchmark proof, and paper export stay with their owning packages.

For a local nirs4all workspace, use the sibling harness:

python -m nirs4all_providers.local_release_gate --workspace-root /path/to/nirs4all --json
# or
nirs4all-providers-local-release-gate --workspace-root /path/to/nirs4all
# optionally add an existing dependency venv/site-packages/PYTHONPATH directory
python -m nirs4all_providers.local_release_gate --workspace-root /path/to/nirs4all --dependency-path /path/to/.venv

The harness verifies that nirs4all-datasets and nirs4all-repository each expose a real src/<module>/__init__.py, prepends those source paths, then runs the same strict release gate. Existing dependency paths may be supplied with repeated --dependency-path flags or NIRS4ALL_PROVIDERS_LOCAL_DEPENDENCY_PATHS (using the platform path separator); venv roots are resolved to their site-packages directories. It does not install dependencies or fake missing packages; missing sibling trees, non-package layouts, or import-time dependency blockers remain release-gate failures, with the missing transitive module and matching sibling requirement reported when available.

Brand

Logo assets live in assets/brand/icon.svg plus stacked.svg / stacked-dark.svg, using the shared ecosystem mark (spectral wave, white content) recolored to this package's key. The key is magenta #D946EF with the n4v lettermark; v keeps the mark distinct from nirs4all-papers (n4p), which already owns the p initial. The raster/wordmark kit is generated by the nirs4all-org pipeline and mirrored here, not hand-authored. See assets/brand/README.md for the rationale.

License

Dual-licensed CeCILL-2.1 OR AGPL-3.0-or-later, consistent with the nirs4all ecosystem policy. See LICENSE, LICENSING.md, and the full texts under LICENSES/.

Community

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nirs4all_providers-0.2.7.tar.gz (64.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

nirs4all_providers-0.2.7-py3-none-any.whl (61.2 kB view details)

Uploaded Python 3

File details

Details for the file nirs4all_providers-0.2.7.tar.gz.

File metadata

  • Download URL: nirs4all_providers-0.2.7.tar.gz
  • Upload date:
  • Size: 64.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for nirs4all_providers-0.2.7.tar.gz
Algorithm Hash digest
SHA256 84971c8fdd4274efbeea02869c3748df2922804a3e486fb04ea1930fac8538b7
MD5 993f96e36cf4aeb282ab981dffa89ab0
BLAKE2b-256 09dae090f068f9df9e0cb572de121dcc02c66b118fc3abf711b8ee76749ecbfb

See more details on using hashes here.

Provenance

The following attestation bundles were made for nirs4all_providers-0.2.7.tar.gz:

Publisher: publish.yml on GBeurier/nirs4all-providers

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file nirs4all_providers-0.2.7-py3-none-any.whl.

File metadata

File hashes

Hashes for nirs4all_providers-0.2.7-py3-none-any.whl
Algorithm Hash digest
SHA256 818ab1b4cfee21b1ca06613721816b5dfe4cdbb79997ce9e11bcfbf9d79ee9c6
MD5 c994e485c85c21581aba8ab3b65f5919
BLAKE2b-256 92f243ab477394d51f2b30c0e12d40dfa2fb949cca9ecf249fb8ca8280ce67fa

See more details on using hashes here.

Provenance

The following attestation bundles were made for nirs4all_providers-0.2.7-py3-none-any.whl:

Publisher: publish.yml on GBeurier/nirs4all-providers

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page