Metadata-Version: 2.4
Name: sdmxlib-rest
Version: 0.1.0
Summary: Generic SDMX-REST HTTP surface over a sdmxlib FederatedCatalog
Keywords: sdmx,sdmx-rest,fastapi,statistical-data,api
Author: gabrielgellner
Author-email: gabrielgellner <gabrielgellner@gmail.com>
License-Expression: Apache-2.0
License-File: LICENSE
Classifier: Development Status :: 4 - Beta
Classifier: Framework :: FastAPI
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Information Analysis
Requires-Dist: sdmxlib>=0.48.0
Requires-Dist: attrs>=24
Requires-Dist: fastapi>=0.115
Requires-Dist: starlette>=0.40
Requires-Dist: duckdb>=1.1
Requires-Dist: polars>=1.39
Requires-Dist: pyarrow>=18
Requires-Dist: orjson>=3.11
Requires-Dist: loguru>=0.7
Requires-Dist: isal>=1.8.0
Requires-Dist: zipstream-ng>=1.9.2
Requires-Python: >=3.13
Project-URL: Homepage, https://gitlab.com/pinax-suite/sdmxlib-rest
Project-URL: Repository, https://gitlab.com/pinax-suite/sdmxlib-rest
Project-URL: Issue Tracker, https://gitlab.com/pinax-suite/sdmxlib-rest/-/issues
Project-URL: Changelog, https://gitlab.com/pinax-suite/sdmxlib-rest/-/blob/main/CHANGELOG.md
Description-Content-Type: text/markdown

# sdmxlib-rest

A generic [SDMX-REST](https://github.com/sdmx-twg/sdmx-rest) HTTP surface over a
[sdmxlib](https://gitlab.com/pinax-suite/sdmxlib) `FederatedCatalog`.

It owns the parts of an SDMX-REST service that are the same everywhere — URL
grammar, content negotiation, localisation, streaming, response assembly — and
leaves everything catalog-specific to the consumer, behind explicit seams.

```python
from sdmxlib_rest.app import RestSettings, create_app, library_routers
from sdmxlib_rest.runtime import CatalogRuntime

runtime = CatalogRuntime(MyCatalogProvider())
app = create_app(
    runtime,
    RestSettings(title="my-sdmx-api", version="1.0.0"),
    routers=list(library_routers()),
)
```

That serves the structure, metadata and availability planes. Serving data is the
consumer's job — see *Why there is no data route* below.

## What you supply

Everything catalog-shaped is a Protocol on `CatalogRuntime`, each with a no-op
default. A bare consumer implements only the first one.

| Seam | Purpose | Default |
|---|---|---|
| `CatalogProvider` | how the catalog is opened | **required** |
| `SpliceRegistry` | post-serialise JSON transforms | empty |
| `StructureCache` | cache rendered structure responses | never caches |
| `AvailabilityCache` | cache rendered availability responses | never caches |
| `MetadataStore` | reference-metadata lookups | returns nothing |
| `ComponentFilterShaper` | rewrite a parsed filter before SQL | identity |
| `MessageAnnotator` | pre-serialise message annotation | no-op |

The defaults are all *inert*, not *broken*: a consumer that installs none of
them gets a correct service, just one that recomputes more than it needs to.

## What `create_app` gives you

Routes are the easy part. The assembly is what's worth not rewriting:

- **The middleware stack, in the one order that works.** The chain has real
  adjacency constraints — the ETag has to hash uncompressed bytes, so it runs
  inside compression; `?lang=` has to rewrite the header before the ETag layer
  reads it; CORS has to be outermost or preflights fall through to a 404 that
  browsers report as a CORS failure. Each constraint is documented at
  `_install_middleware`.
- **Runtime sharing across mounts**, so a service exposing several surfaces
  (a canonical one plus compatibility variants) opens the catalog once.
- **A multi-spec docs page**, which has to be hand-rolled because FastAPI's
  helper emits a single-spec page and Swagger UI renders nothing when given
  both `url` and `urls`.

## Why there is no data route

The library owns data-plane *helpers* — key and query-parameter parsing,
projection, paging headers, binding-driven SQL fragments, and the
arrow→CSV/parquet encoders, all under `sdmxlib_rest.data`. It does not own the
`/data` route itself.

That is deliberate. Orchestration is where response caching, partition pushdown
and vendor extensions live, and every catalog shapes those differently — one
catalog's hierarchy descent and partition-pruning tricks are noise to the next.
A second consumer gets the hard, fiddly parts and writes its own handler around
them.

## Status

Extracted from a production SDMX-REST service and versioned independently from
`0.1.0`. The seam set is settled; the `create_app` signature may still move
before `1.0`.

## Licence

Apache-2.0.
