Skip to main content

Official Python SDK for CAVS Hub — the deduplicating, content-addressed artifact store for AI, CI/CD and game pipelines.

Project description

cavs — Python SDK for CAVS Hub

Official Python client for CAVS Hub, the content-addressed, deduplicating artifact store for AI, CI/CD and game pipelines. It speaks the same canonical API the CLI uses — one API, one permission model, one data plane. The wire behaviour is defined in ../CONTRACT.md and pinned by the shared vectors in ../spec/contract/.

  • Requires Python 3.9+.
  • Only runtime dependency: httpx.

Install

pip install cavs

From this monorepo checkout:

cd python
pip install -e ".[dev]"

Quickstart

from cavs import CAVS

client = CAVS.from_env()          # reads CAVS_TOKEN + CAVS_API

artifact = client.artifacts.upload(
    path="./model",
    project="vision-models",
    name="resnet50",
    kind="model",
    version="1.4.0",
    metadata={"framework": "pytorch", "accuracy": 0.942},
)
print(artifact.reference)          # cavs://acme-ai/vision-models/model/resnet50:1.4.0
print(artifact.deduplication_ratio)

client.artifacts.download(artifact.reference, dest="./restored")

Track training runs and lineage:

run = client.runs.create(project="vision-models", name="nightly", system="mlflow")
client.runs.update("vision-models", run.id, status="completed")

Authentication

Create a service account in the CAVS dashboard and export its key. Tokens are resolved in this order: an explicit token= argument, then $CAVS_TOKEN.

export CAVS_TOKEN=cavs_sk_...
export CAVS_API=https://api.cavs.dev        # default; use http://localhost:8080 for dev

Other environment variables:

Variable Purpose
CAVS_TOKEN Auth token (cavs_sk_…, cavs_pat_…, …)
CAVS_API Base URL (default https://api.cavs.dev)
CAVS_ORG Default organization slug
CAVS_CA_BUNDLE Path to a custom CA bundle for TLS verification

Or construct explicitly:

client = CAVS(token="cavs_sk_...", api="https://api.cavs.dev", org="acme-ai")

project and org resolution

project is an alias for a repository. It is resolved within an org by matching the value against each repository's id, slug or name (GET /organizations/{org}/repositories); if nothing matches, the value is used verbatim as a repository id. The org comes from an explicit argument, then CAVS_ORG, then the caller's default org from GET /users/me.

Security

Following ../CONTRACT.md §2, this SDK:

  • never prints the token in repr, exceptions, or logs — it is redacted to e.g. cavs_sk_…abcd;
  • never logs presigned URLs or full request headers;
  • verifies TLS and honours CAVS_CA_BUNDLE; caps redirects at 5;
  • always sets connect + read timeouts;
  • verifies sha256 == oid on every download and refuses to write a mismatched file (ChecksumError), cleaning up the temp file;
  • guards against path traversal when expanding directories / archive members;
  • honours Retry-After and cleans up temp files on failure;
  • supports cancellation via a threading.Event (or any object with is_set()).

Uploads and downloads

Large files never travel through the control plane — they stream directly to object storage via presigned URLs (CONTRACT §5).

  • Upload: hash every file (streamed sha256, 64 KiB chunks) → open a session with an Idempotency-Key → authorize objects (the Hub reports which already exists, so dedup and resume are automatic) → PUT the missing bytes → complete each object → finalize (idempotent), which returns dedup stats.
  • Download: authorize → stream to a deterministic temp file while hashing → verify sha256 == oid → atomically rename into place.

Progress and cancellation:

import threading

cancel = threading.Event()
client.artifacts.upload(
    path="./big-dataset",
    project="datasets",
    name="imagenet",
    kind="dataset",
    version="2026.07.24",
    on_progress=lambda done, total: print(f"{done}/{total}"),
    cancel=cancel,
)

cavs:// URIs

from cavs import parse, format_uri

p = parse("cavs://acme-ai/vision-models/model/resnet50:1.4.0")
p.org, p.name, p.version        # 'acme-ai', 'resnet50', '1.4.0'
format_uri(p)                    # round-trips to the canonical form

Errors

All exceptions derive from cavs.CAVSError. The HTTP → exception mapping follows CONTRACT §8:

HTTP Exception
401 AuthenticationError
403 AuthorizationError
404 NotFoundError
409 ConflictError
413 / 402 QuotaExceededError
429 RateLimitError (honours Retry-After)
5xx / network TemporaryServiceError (retried, ≤4 attempts)
client-side checksum mismatch ChecksumError
upload / download transport UploadError / DownloadError
from cavs import CAVS, NotFoundError, RateLimitError

try:
    client.artifacts.get("does-not-exist")
except NotFoundError as e:
    print(e.code, e.status)
except RateLimitError as e:
    print("retry after", e.retry_after)

Development

cd python
python -m venv .venv && . .venv/bin/activate
pip install -e ".[dev]"
ruff check . && mypy src && pytest --cov=cavs --cov-fail-under=90

Tests mock httpx with respx — no network is used. See ../CONTRIBUTING.md and the docs in ../docs/.

License

Apache 2.0 — see ../LICENSE.

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

cavs-0.1.0.tar.gz (26.4 kB view details)

Uploaded Source

Built Distribution

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

cavs-0.1.0-py3-none-any.whl (25.5 kB view details)

Uploaded Python 3

File details

Details for the file cavs-0.1.0.tar.gz.

File metadata

  • Download URL: cavs-0.1.0.tar.gz
  • Upload date:
  • Size: 26.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for cavs-0.1.0.tar.gz
Algorithm Hash digest
SHA256 1827033830e476c62b33da7e81569d542612b0244c98c71375030c11169c8d81
MD5 75d4dce2498002044a059ba4c8536717
BLAKE2b-256 160ca63c2a126e39ded3f659ae08e08819adb3b75d326cf475a852f69425a7d0

See more details on using hashes here.

File details

Details for the file cavs-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: cavs-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 25.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for cavs-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6baf50092a9709e37b8feb7d4100b6aea9089593c55da31d7a08f8fe78e3fba7
MD5 6ba1885fb6c2edbcd7dedb0562a9afa6
BLAKE2b-256 216b04cda18c365f7de30b0e98996088b302f2ee740f6a30e7049b676d380585

See more details on using hashes here.

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