Skip to main content

xarray-annotated

PyPI version Python versions CI Docs License: MIT

xarray-annotated enables run-time validation of xarray.DataArray properties declared in function signatures via typing.Annotated.

The main idea is that annotations serve as a single source of truth for

  • structural schema (dims, coords, dtype),
  • physical units,
  • frequency (and phase) of a time axis,

from which

  • static checkers and run-time validation can derive expected properties,
  • documentation can be generated automatically,
  • automated tools (coding agents) receive steering.

For validating and automatically converting physical units we lean on the excellent pint and pint-xarray. (cf-xarray is an optional dependency for CF/UDUNITS unit strings.)

For full user documentation please visit https://jmarshrossney.github.io/xarray-annotated/.

Installation

Either using uv (recommended) or pip:

uv add xarray-annotated
# or
pip install xarray-annotated

CF-convention / UDUNITS unit strings (e.g. "umol m-2 s-1") need the optional cf extra, which pulls in cf-xarray.

uv add "xarray-annotated[cf]"
# or
pip install "xarray-annotated[cf]"

A short example

Here is a function that converts barometric pressure to altitude. It assumes a unit (pascals) and says so in the docstring but doesn't check or enforce it.

import xarray as xr


def altitude(p: xr.DataArray) -> xr.DataArray:
    """Barometric altitude. Assumes p is in Pa."""
    return 44330.0 * (1.0 - (p / 101325.0) ** 0.1903)


p = xr.DataArray([1013.0, 1000.0], dims=["time"], attrs={"units": "hPa"})
altitude(p)
<xarray.DataArray (time: 2)> Size: 16B
array([25876.55998663, 25921.86206292])
Dimensions without coordinates: time
Attributes:
    units:    hPa

The input units are wrong (hPa vs Pa) but the onus is on the user to check, and in reality we all know that such bugs can go unnoticed for a terrifyingly long time. The returned altitude is numerically wrong and carries a completely bogus hPa units in attrs.

Here we use xarray-annotated to declare expected properties in the signature and enforce them at run-time with minimal boilerplate (just decorators).

from typing import Annotated
import xarray as xr
from xarray_annotated.schema import declare_schema, Dims
from xarray_annotated.units import declare_units, Unit


@declare_units
@declare_schema
def altitude(
    p: Annotated[xr.DataArray, Dims("time"), Unit("Pa")],
) -> Annotated[xr.DataArray, Dims("time"), Unit("m")]:
    """Barometric altitude."""
    return 44330.0 * (1.0 - (p / 101325.0) ** 0.1903)


p = xr.DataArray([1013.0, 1000.0], dims=["time"], attrs={"units": "hPa"})
altitude(p)
<xarray.DataArray (time: 2)> Size: 16B
array([  2.08162886, 110.90398059])
Dimensions without coordinates: time
Attributes:
    units:    m

Now the outputs are physical and carry the correct units attribute. The hPa input was converted to Pa before the body ran, and the result was stamped with the unit the signature promised. The docstring no longer needs to say "assumes Pa", because the signature does --- and unlike the docstring, it is actually enforced.

If we had handed the function an array whose units were dimensionally wrong, or with an extra dimension, this would have failed gracefully:

altitude(xr.DataArray([1.0, 2.0], dims=["time"], attrs={"units": "kg"}))
# DimensionalityError: Cannot convert from 'kilogram' ([mass])
#   to 'pascal' ([mass] / [length] / [time] ** 2)

altitude(xr.DataArray([[1013.0, 1000.0]], dims=["run", "time"], attrs={"units": "hPa"}))
# SchemaError: [altitude] 'p' dims mismatch: expected ('time',) in any order, got ('run', 'time')

Contributing

uv sync   # install the package + dev dependencies into .venv
just      # lint, typecheck, test, build docs

See the justfile for individual targets (just lint, just test, just test-cov, ...).

A .pre-commit-config.yaml is included to run the same linting (ruff) and type-checking (pyright) steps on every commit. Install the hooks with:

uv run pre-commit install

Contributions are welcome --- open an issue or pull request on GitHub.

Metadata

Release files for xarray-annotated 0.6.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for xarray-annotated 0.6.0
File Size Uploaded Provenance
xarray_annotated-0.6.0.tar.gz 43.8 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for xarray-annotated 0.6.0
File Interpreter ABI Platform
xarray_annotated-0.6.0-py3-none-any.whl Python 3 none any Details

Total release size: 99.6 kB

Release files / xarray_annotated-0.6.0.tar.gz

Download URL xarray_annotated-0.6.0.tar.gz
Size 43.8 kB
Tags Source
SHA-256 checksum
How to use checksums
0ecf243deb956a5e6b7b0a9c8cc537651e069d4b0460fd198509bcee3d1af7d0
BLAKE2b-256 checksum
How to use checksums
18e9e416f4cc2cb7541fbf801b6e19c74ed84c4fa150417205235dff2a4f161d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / xarray_annotated-0.6.0-py3-none-any.whl

Download URL xarray_annotated-0.6.0-py3-none-any.whl
Size 55.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7d68c7b81185ac012539eec1f5dcdb7c026cefaae6526ed05929efd874851626
BLAKE2b-256 checksum
How to use checksums
a270e6467c9c202388ba172a4432bec47029345f216806e6753e540e3407f1a9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for xarray-annotated 0.6.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.6.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page