Metadata-Version: 2.4
Name: caeli-data
Version: 0.2.0
Summary: Python client of the Caeli data repository API (data.caeli.space): load tables, publish rasters, read the catalogue
Author-email: "Caeli B.V." <tim@caeli.nl>
License: Proprietary. Copyright Caeli B.V. The library is free to install; the data repository it talks to needs an API key from Caeli.
Project-URL: Homepage, https://data.caeli.space
Project-URL: Catalogue, https://catalog.caeli.space
Keywords: caeli,air quality,STAC,Iceberg,data repository
Classifier: Programming Language :: Python :: 3
Classifier: License :: Other/Proprietary License
Classifier: Operating System :: OS Independent
Classifier: Topic :: Scientific/Engineering :: Atmospheric Science
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: httpx>=0.27
Requires-Dist: pyarrow>=14
Provides-Extra: aws
Requires-Dist: boto3>=1.26; extra == "aws"

# caeli-data

The Python client of the Caeli data repository API (https://data.caeli.space). One door for every producer and reader
of datasets: the inventory platform, pipelines and colleagues all use this library; nothing writes to the tables or the
buckets directly.

    pip install caeli-data            # caeli-data[aws] also brings boto3, for Repository.from_secret

    from caeli_data import Repository, TableRejected, IngestFailed

    repo = Repository()               # CAELI_API_URL (default https://data.caeli.space) and CAELI_API_KEY
    repo.whoami()                     # {"name": "tim", "role": "admin", ...}

    # a prepared Parquet file with any regions and months in it: split per partition region and month, every part loaded
    jobs = repo.load_file("prepared.parquet", "cdse-sentinel-5p-l2-no2", software={"my-pipeline": "1.0"}, source_ref="download 4711")
    print(jobs[0]["message"])         # "200000 rows appended in cdse_sentinel_5p_l2_no2, ... item N_EU__2026-09__v1 now ..."

    # a pandas DataFrame straight in: columns ordered and cast to the registered schema, the helper column idx_month dropped
    jobs = repo.load_dataframe(df, "cdse-sentinel-5p-l2-no2", software={"my-pipeline": "1.0"})

A complete month delivered again is a new version of that month: `mode="replace", reason="re-import of 2026-09"`.
A service takes its key from Secrets Manager: `Repository.from_secret("caeli/data-platform/api-key-inventory-platform")`.

The rules a table file must meet are in Caeli_data_repository_conventions (section 6); the library checks them before
uploading and says which rule a file breaks (`TableRejected`). `IngestFailed` means the platform failed; the same file
sent again is the same job, never a double load. Python 3.9 and later.

Rasters, the read side (catalogue, versions, downloads) and the command line follow in the next versions.
