From 560bb9289673ee6b8c6c3aa5c1aa33593a069a23 Mon Sep 17 00:00:00 2001 From: Davis Vann Bennett Date: Wed, 29 Jul 2026 18:05:38 +0200 Subject: [PATCH 1/7] docs(zarr-metadata): add API reference to the docs site Add mkdocstrings pages for every public zarr_metadata module (model, pydantic, v2, and v3 with its chunk_grid, chunk_key_encoding, codec, and data_type subpackages) under a new zarr-metadata group in the API Reference nav. griffe documents the package statically from packages/zarr-metadata/src, so the docs build environment does not need the package installed. Point the package's Documentation URL at the rendered reference instead of the README. Assisted-by: ClaudeCode:claude-fable-5 --- docs/api/zarr_metadata/index.md | 59 +++++++++++++++++++ docs/api/zarr_metadata/model.md | 5 ++ docs/api/zarr_metadata/pydantic.md | 5 ++ docs/api/zarr_metadata/v2.md | 17 ++++++ docs/api/zarr_metadata/v3/chunk_grid.md | 11 ++++ .../zarr_metadata/v3/chunk_key_encoding.md | 11 ++++ docs/api/zarr_metadata/v3/codec.md | 25 ++++++++ docs/api/zarr_metadata/v3/data_type.md | 45 ++++++++++++++ docs/api/zarr_metadata/v3/index.md | 15 +++++ mkdocs.yml | 14 ++++- packages/zarr-metadata/pyproject.toml | 2 +- 11 files changed, 207 insertions(+), 2 deletions(-) create mode 100644 docs/api/zarr_metadata/index.md create mode 100644 docs/api/zarr_metadata/model.md create mode 100644 docs/api/zarr_metadata/pydantic.md create mode 100644 docs/api/zarr_metadata/v2.md create mode 100644 docs/api/zarr_metadata/v3/chunk_grid.md create mode 100644 docs/api/zarr_metadata/v3/chunk_key_encoding.md create mode 100644 docs/api/zarr_metadata/v3/codec.md create mode 100644 docs/api/zarr_metadata/v3/data_type.md create mode 100644 docs/api/zarr_metadata/v3/index.md diff --git a/docs/api/zarr_metadata/index.md b/docs/api/zarr_metadata/index.md new file mode 100644 index 0000000000..1f91daa6b0 --- /dev/null +++ b/docs/api/zarr_metadata/index.md @@ -0,0 +1,59 @@ +--- +title: zarr-metadata +--- + +# `zarr-metadata` + +Spec-defined metadata types, models, and validators for Zarr v2 and v3. + +`zarr-metadata` is a standalone package developed in the +[zarr-python repository](https://github.com/zarr-developers/zarr-python/tree/main/packages/zarr-metadata) +and released separately from `zarr` itself. Install it with: + +``` +pip install zarr-metadata +``` + +The package has two layers and an optional integration: + +- **Typed JSON shapes** ([`zarr_metadata.v2`](v2.md) and + [`zarr_metadata.v3`](v3/index.md)): `TypedDict` definitions and `Literal` + aliases for the JSON documents specified by the + [Zarr v2](https://zarr-specs.readthedocs.io/en/latest/v2/v2.0.html) and + [Zarr v3](https://zarr-specs.readthedocs.io/en/latest/v3/core/index.html) + specifications, plus types for + [zarr-extensions](https://github.com/zarr-developers/zarr-extensions/) and a + few widely-used-but-unspecified entities (e.g. consolidated metadata). +- **Document models** ([`zarr_metadata.model`](model.md)): canonical + frozen-dataclass models of whole metadata documents, with structural + validators, loc-aware parsers, and store-key (de)serialization. +- **Optional Pydantic integration** ([`zarr_metadata.pydantic`](pydantic.md), + requires Pydantic 2.13 or newer): each model as a Pydantic field type that + validates raw documents through the same strict parser. + +Every public name is also re-exported at the top level, so +`from zarr_metadata import ZarrV3ArrayMetadataJSON` and +`from zarr_metadata.v3.array import ZarrV3ArrayMetadataJSON` are equivalent. + +The `TypedDict` definitions describe the static JSON shape of Zarr metadata +for type checkers. For strict, loc-aware runtime validation of JSON loaded +from a store, use the model parsers: + +```python exec="false" reason="zarr-metadata is not installed in the docs build environment" +import json +from zarr_metadata.model import ZarrV3ArrayMetadata + +with open("zarr.json", "rb") as f: + raw = json.load(f) + +metadata = ZarrV3ArrayMetadata.from_json(raw) +``` + +## Common types + +A few cross-cutting aliases are exported only from the top-level +`zarr_metadata` namespace: + +::: zarr_metadata.JSONValue + +::: zarr_metadata.ZarrV3NamedConfigJSON diff --git a/docs/api/zarr_metadata/model.md b/docs/api/zarr_metadata/model.md new file mode 100644 index 0000000000..c82ba98f2d --- /dev/null +++ b/docs/api/zarr_metadata/model.md @@ -0,0 +1,5 @@ +--- +title: model +--- + +::: zarr_metadata.model diff --git a/docs/api/zarr_metadata/pydantic.md b/docs/api/zarr_metadata/pydantic.md new file mode 100644 index 0000000000..edecb416a7 --- /dev/null +++ b/docs/api/zarr_metadata/pydantic.md @@ -0,0 +1,5 @@ +--- +title: pydantic +--- + +::: zarr_metadata.pydantic diff --git a/docs/api/zarr_metadata/v2.md b/docs/api/zarr_metadata/v2.md new file mode 100644 index 0000000000..2fe5b6ec56 --- /dev/null +++ b/docs/api/zarr_metadata/v2.md @@ -0,0 +1,17 @@ +--- +title: v2 +--- + +::: zarr_metadata.v2 + options: + members: false + +::: zarr_metadata.v2.array + +::: zarr_metadata.v2.group + +::: zarr_metadata.v2.attributes + +::: zarr_metadata.v2.codec + +::: zarr_metadata.v2.consolidated diff --git a/docs/api/zarr_metadata/v3/chunk_grid.md b/docs/api/zarr_metadata/v3/chunk_grid.md new file mode 100644 index 0000000000..724b1c9d8d --- /dev/null +++ b/docs/api/zarr_metadata/v3/chunk_grid.md @@ -0,0 +1,11 @@ +--- +title: chunk_grid +--- + +::: zarr_metadata.v3.chunk_grid + options: + members: false + +::: zarr_metadata.v3.chunk_grid.regular + +::: zarr_metadata.v3.chunk_grid.rectilinear diff --git a/docs/api/zarr_metadata/v3/chunk_key_encoding.md b/docs/api/zarr_metadata/v3/chunk_key_encoding.md new file mode 100644 index 0000000000..bb063deb25 --- /dev/null +++ b/docs/api/zarr_metadata/v3/chunk_key_encoding.md @@ -0,0 +1,11 @@ +--- +title: chunk_key_encoding +--- + +::: zarr_metadata.v3.chunk_key_encoding + options: + members: false + +::: zarr_metadata.v3.chunk_key_encoding.default + +::: zarr_metadata.v3.chunk_key_encoding.v2 diff --git a/docs/api/zarr_metadata/v3/codec.md b/docs/api/zarr_metadata/v3/codec.md new file mode 100644 index 0000000000..cb96d2c7d5 --- /dev/null +++ b/docs/api/zarr_metadata/v3/codec.md @@ -0,0 +1,25 @@ +--- +title: codec +--- + +::: zarr_metadata.v3.codec + options: + members: false + +::: zarr_metadata.v3.codec.blosc + +::: zarr_metadata.v3.codec.bytes + +::: zarr_metadata.v3.codec.cast_value + +::: zarr_metadata.v3.codec.crc32c + +::: zarr_metadata.v3.codec.gzip + +::: zarr_metadata.v3.codec.scale_offset + +::: zarr_metadata.v3.codec.sharding_indexed + +::: zarr_metadata.v3.codec.transpose + +::: zarr_metadata.v3.codec.zstd diff --git a/docs/api/zarr_metadata/v3/data_type.md b/docs/api/zarr_metadata/v3/data_type.md new file mode 100644 index 0000000000..f482c33201 --- /dev/null +++ b/docs/api/zarr_metadata/v3/data_type.md @@ -0,0 +1,45 @@ +--- +title: data_type +--- + +::: zarr_metadata.v3.data_type + options: + members: false + +::: zarr_metadata.v3.data_type.bool + +::: zarr_metadata.v3.data_type.int8 + +::: zarr_metadata.v3.data_type.int16 + +::: zarr_metadata.v3.data_type.int32 + +::: zarr_metadata.v3.data_type.int64 + +::: zarr_metadata.v3.data_type.uint8 + +::: zarr_metadata.v3.data_type.uint16 + +::: zarr_metadata.v3.data_type.uint32 + +::: zarr_metadata.v3.data_type.uint64 + +::: zarr_metadata.v3.data_type.float16 + +::: zarr_metadata.v3.data_type.float32 + +::: zarr_metadata.v3.data_type.float64 + +::: zarr_metadata.v3.data_type.complex64 + +::: zarr_metadata.v3.data_type.complex128 + +::: zarr_metadata.v3.data_type.raw + +::: zarr_metadata.v3.data_type.bytes + +::: zarr_metadata.v3.data_type.string + +::: zarr_metadata.v3.data_type.numpy_datetime64 + +::: zarr_metadata.v3.data_type.numpy_timedelta64 diff --git a/docs/api/zarr_metadata/v3/index.md b/docs/api/zarr_metadata/v3/index.md new file mode 100644 index 0000000000..f20267d372 --- /dev/null +++ b/docs/api/zarr_metadata/v3/index.md @@ -0,0 +1,15 @@ +--- +title: v3 +--- + +::: zarr_metadata.v3 + options: + members: false + +::: zarr_metadata.v3.ZarrV3MetadataFieldJSON + +::: zarr_metadata.v3.array + +::: zarr_metadata.v3.group + +::: zarr_metadata.v3.consolidated diff --git a/mkdocs.yml b/mkdocs.yml index 46bfc1764c..40077e0883 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -92,6 +92,17 @@ nav: - ' zarr.testing.utils': api/zarr/testing/utils.md - ' zarr.zeros': api/zarr/functions/zeros.md - ' zarr.zeros_like': api/zarr/functions/zeros_like.md + - zarr-metadata: + - api/zarr_metadata/index.md + - ' zarr_metadata.model': api/zarr_metadata/model.md + - ' zarr_metadata.pydantic': api/zarr_metadata/pydantic.md + - ' zarr_metadata.v2': api/zarr_metadata/v2.md + - ' zarr_metadata.v3': + - api/zarr_metadata/v3/index.md + - ' zarr_metadata.v3.chunk_grid': api/zarr_metadata/v3/chunk_grid.md + - ' zarr_metadata.v3.chunk_key_encoding': api/zarr_metadata/v3/chunk_key_encoding.md + - ' zarr_metadata.v3.codec': api/zarr_metadata/v3/codec.md + - ' zarr_metadata.v3.data_type': api/zarr_metadata/v3/data_type.md - release-notes.md - contributing.md hooks: @@ -99,6 +110,7 @@ hooks: watch: - src/zarr + - packages/zarr-metadata/src - docs theme: @@ -158,7 +170,7 @@ plugins: enable_inventory: true handlers: python: - paths: [src/zarr] + paths: [src/zarr, packages/zarr-metadata/src] options: allow_inspection: true docstring_section_style: list diff --git a/packages/zarr-metadata/pyproject.toml b/packages/zarr-metadata/pyproject.toml index edc4b696a6..4e31643670 100644 --- a/packages/zarr-metadata/pyproject.toml +++ b/packages/zarr-metadata/pyproject.toml @@ -44,7 +44,7 @@ Homepage = "https://github.com/zarr-developers/zarr-python" Source = "https://github.com/zarr-developers/zarr-python/tree/main/packages/zarr-metadata" Issues = "https://github.com/zarr-developers/zarr-python/issues" Changelog = "https://github.com/zarr-developers/zarr-python/blob/main/packages/zarr-metadata/CHANGELOG.md" -Documentation = "https://github.com/zarr-developers/zarr-python/blob/main/packages/zarr-metadata/README.md" +Documentation = "https://zarr.readthedocs.io/en/latest/api/zarr_metadata/" [dependency-groups] test = ["pytest", "pydantic>=2.13", "jsonschema"] From 00e42896b8c3377b4cd0701d7d3160394e118fab Mon Sep 17 00:00:00 2001 From: Davis Vann Bennett Date: Wed, 29 Jul 2026 18:05:50 +0200 Subject: [PATCH 2/7] chore(zarr-metadata): add justfile with package-scoped dev recipes Recipes mirror the zarr-metadata CI jobs (pytest, ruff, pyright pinned to the version CI uses, on CI's python) plus changelog-draft and docs-serve conveniences. Recipes run from the package directory regardless of where just is invoked, and remain reachable from the repo root as 'just packages/zarr-metadata/'; a future root justfile can namespace them with a 'mod' declaration. Assisted-by: ClaudeCode:claude-fable-5 --- packages/zarr-metadata/README.md | 15 ++++++++++++++ packages/zarr-metadata/justfile | 34 ++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 packages/zarr-metadata/justfile diff --git a/packages/zarr-metadata/README.md b/packages/zarr-metadata/README.md index 69b80d7332..f8a34063b8 100644 --- a/packages/zarr-metadata/README.md +++ b/packages/zarr-metadata/README.md @@ -82,6 +82,21 @@ store I/O. The models begin and end at the metadata documents themselves — `from_key_value` / `to_key_value` map documents to store keys and bytes, and everything past that belongs to consumer libraries. +## Developing + +Package-scoped development commands live in the [`justfile`](./justfile) +(requires [just](https://github.com/casey/just)): + +``` +just test # run the test suite (extra args go to pytest) +just lint # ruff, same invocation as CI +just typecheck # pyright, pinned to the version CI uses +just check # all of the above +``` + +Run them from this directory, or from anywhere in the repository as +`just packages/zarr-metadata/`. + ## Releasing The package version is derived from git tags by `hatch-vcs`. Tags must diff --git a/packages/zarr-metadata/justfile b/packages/zarr-metadata/justfile new file mode 100644 index 0000000000..73d3108161 --- /dev/null +++ b/packages/zarr-metadata/justfile @@ -0,0 +1,34 @@ +# Development verbs for the zarr-metadata package. Recipes run with this +# directory as the working directory regardless of where `just` is invoked. + +# List available recipes +default: + @just --list + +# Run the test suite; extra args are passed to pytest +test *args: + uv run --group test pytest tests {{ args }} + +# Lint with the same invocation CI uses +lint: + uvx ruff check . + +# Pinned to the last pyright that types PEP 661 sentinels in class attributes +# correctly; 1.1.405+ regressed (microsoft/pyright#11115). Unpin when fixed. +pyright_version := "1.1.404" + +# Type-check the package sources. CI runs pyright on python 3.11; the pinned +# pyright predates 3.14, whose stdlib it cannot parse, so match CI's python. +typecheck: + uv run --python 3.11 --group test --with 'pyright=={{ pyright_version }}' pyright src + +# Run everything CI runs for this package +check: lint typecheck test + +# Preview the changelog that the next release would generate +changelog-draft: + uvx towncrier build --draft --version Unreleased + +# Serve the zarr-python docs site, which includes this package's API reference +docs-serve: + cd ../.. && DISABLE_MKDOCS_2_WARNING=true uv run --group docs mkdocs serve From 3b9c0d9cecd3b99425beee70a6247fd307f4172a Mon Sep 17 00:00:00 2001 From: Davis Vann Bennett Date: Wed, 29 Jul 2026 18:18:20 +0200 Subject: [PATCH 3/7] chore(zarr-metadata): make docs-serve robust to a busy port With no argument, docs-serve now binds port 8000 if free and otherwise falls back to an ephemeral free port. An explicitly requested port is used as-is so a conflict fails loudly. Assisted-by: ClaudeCode:claude-fable-5 --- packages/zarr-metadata/justfile | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/packages/zarr-metadata/justfile b/packages/zarr-metadata/justfile index 73d3108161..1f2769ed97 100644 --- a/packages/zarr-metadata/justfile +++ b/packages/zarr-metadata/justfile @@ -29,6 +29,26 @@ check: lint typecheck test changelog-draft: uvx towncrier build --draft --version Unreleased -# Serve the zarr-python docs site, which includes this package's API reference -docs-serve: - cd ../.. && DISABLE_MKDOCS_2_WARNING=true uv run --group docs mkdocs serve +# Serve the zarr-python docs site, which includes this package's API reference. +# With no argument, uses port 8000 if free, otherwise an ephemeral free port; +# an explicitly requested port is used as-is so a conflict fails loudly. +docs-serve port="": + #!/usr/bin/env bash + set -euo pipefail + cd ../.. + port="{{ port }}" + if [ -z "$port" ]; then + port=$(uv run --group docs python -c ' + import socket + s = socket.socket() + try: + s.bind(("127.0.0.1", 8000)) + except OSError: + s.close() + s = socket.socket() + s.bind(("127.0.0.1", 0)) + print(s.getsockname()[1]) + s.close() + ') + fi + exec env DISABLE_MKDOCS_2_WARNING=true uv run --group docs mkdocs serve -a "localhost:$port" From ecef99af41262d255f33f50a0fc3845d2ab153bb Mon Sep 17 00:00:00 2001 From: Davis Vann Bennett Date: Wed, 29 Jul 2026 18:30:44 +0200 Subject: [PATCH 4/7] chore(zarr-metadata): point docs-serve at the package docs, fix cleanup Print the zarr-metadata API reference URL once the server accepts connections, since mkdocs's own 'Serving on' line points at the zarr-python site root. Run the server in its own process group so stopping the recipe kills the whole uv->mkdocs tree instead of leaving an orphaned server holding the port. Assisted-by: ClaudeCode:claude-fable-5 --- packages/zarr-metadata/justfile | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/packages/zarr-metadata/justfile b/packages/zarr-metadata/justfile index 1f2769ed97..cc5c7843f3 100644 --- a/packages/zarr-metadata/justfile +++ b/packages/zarr-metadata/justfile @@ -51,4 +51,19 @@ docs-serve port="": s.close() ') fi - exec env DISABLE_MKDOCS_2_WARNING=true uv run --group docs mkdocs serve -a "localhost:$port" + # Job control gives the server its own process group, so the trap can kill + # the whole uv->mkdocs tree, not just the uv wrapper. + set -m + env DISABLE_MKDOCS_2_WARNING=true uv run --group docs mkdocs serve -a "localhost:$port" & + server=$! + trap 'kill -- "-$server" 2>/dev/null' INT TERM EXIT + # mkdocs's own "Serving on" line points at the site root, which is the + # zarr-python landing page; print this package's corner of the site once + # the server is accepting connections. + while kill -0 "$server" 2>/dev/null && ! (exec 3<>"/dev/tcp/127.0.0.1/$port") 2>/dev/null; do + sleep 1 + done + if kill -0 "$server" 2>/dev/null; then + echo "zarr-metadata API reference: http://localhost:$port/api/zarr_metadata/" + fi + wait "$server" From 2a7ecacb1ea23c6b07f5c1862bea54d03442eefd Mon Sep 17 00:00:00 2001 From: Davis Vann Bennett Date: Wed, 29 Jul 2026 18:46:34 +0200 Subject: [PATCH 5/7] docs(zarr-metadata): make the package docs a standalone site Move the zarr-metadata API reference out of the zarr-python site into a self-contained mkdocs site under packages/zarr-metadata (own mkdocs.yml, landing page, and .readthedocs.yaml for a dedicated RTD project), so the package presents as a separate project with docs versioned by its own zarr_metadata-v* release tags rather than zarr-python's. The zarr-python API Reference nav now links out to the standalone site instead of embedding the pages. The package gains a pinned docs dependency group, a docs build job in its CI workflow, and docs-check / docs-serve justfile recipes targeting the package site. Assisted-by: ClaudeCode:claude-fable-5 --- .github/workflows/zarr-metadata.yml | 24 +++- docs/api/zarr_metadata/index.md | 59 ---------- mkdocs.yml | 15 +-- packages/zarr-metadata/.readthedocs.yaml | 20 ++++ packages/zarr-metadata/README.md | 4 + packages/zarr-metadata/docs/api/index.md | 31 ++++++ .../zarr-metadata/docs/api}/model.md | 0 .../zarr-metadata/docs/api}/pydantic.md | 0 .../zarr-metadata/docs/api}/v2.md | 0 .../zarr-metadata/docs/api}/v3/chunk_grid.md | 0 .../docs/api}/v3/chunk_key_encoding.md | 0 .../zarr-metadata/docs/api}/v3/codec.md | 0 .../zarr-metadata/docs/api}/v3/data_type.md | 0 .../zarr-metadata/docs/api}/v3/index.md | 0 packages/zarr-metadata/docs/index.md | 97 +++++++++++++++++ packages/zarr-metadata/justfile | 31 ++---- packages/zarr-metadata/mkdocs.yml | 103 ++++++++++++++++++ packages/zarr-metadata/pyproject.toml | 13 ++- 18 files changed, 302 insertions(+), 95 deletions(-) delete mode 100644 docs/api/zarr_metadata/index.md create mode 100644 packages/zarr-metadata/.readthedocs.yaml create mode 100644 packages/zarr-metadata/docs/api/index.md rename {docs/api/zarr_metadata => packages/zarr-metadata/docs/api}/model.md (100%) rename {docs/api/zarr_metadata => packages/zarr-metadata/docs/api}/pydantic.md (100%) rename {docs/api/zarr_metadata => packages/zarr-metadata/docs/api}/v2.md (100%) rename {docs/api/zarr_metadata => packages/zarr-metadata/docs/api}/v3/chunk_grid.md (100%) rename {docs/api/zarr_metadata => packages/zarr-metadata/docs/api}/v3/chunk_key_encoding.md (100%) rename {docs/api/zarr_metadata => packages/zarr-metadata/docs/api}/v3/codec.md (100%) rename {docs/api/zarr_metadata => packages/zarr-metadata/docs/api}/v3/data_type.md (100%) rename {docs/api/zarr_metadata => packages/zarr-metadata/docs/api}/v3/index.md (100%) create mode 100644 packages/zarr-metadata/docs/index.md create mode 100644 packages/zarr-metadata/mkdocs.yml diff --git a/.github/workflows/zarr-metadata.yml b/.github/workflows/zarr-metadata.yml index df7d96cc1c..91609f82fa 100644 --- a/.github/workflows/zarr-metadata.yml +++ b/.github/workflows/zarr-metadata.yml @@ -87,9 +87,31 @@ jobs: # Unpin when the fix lands. run: uv run --group test --with 'pyright==1.1.404' pyright src + docs: + name: docs + runs-on: ubuntu-latest + defaults: + run: + shell: bash + working-directory: packages/zarr-metadata + steps: + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + - name: Install uv + uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2 + with: + enable-cache: true + - name: Sync docs dependency group + run: uv sync --group docs + - name: Build docs + run: uv run --group docs mkdocs build --strict + env: + DISABLE_MKDOCS_2_WARNING: "true" + zarr-metadata-complete: name: zarr-metadata complete - needs: [test, ruff, pyright] + needs: [test, ruff, pyright, docs] if: always() runs-on: ubuntu-latest steps: diff --git a/docs/api/zarr_metadata/index.md b/docs/api/zarr_metadata/index.md deleted file mode 100644 index 1f91daa6b0..0000000000 --- a/docs/api/zarr_metadata/index.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: zarr-metadata ---- - -# `zarr-metadata` - -Spec-defined metadata types, models, and validators for Zarr v2 and v3. - -`zarr-metadata` is a standalone package developed in the -[zarr-python repository](https://github.com/zarr-developers/zarr-python/tree/main/packages/zarr-metadata) -and released separately from `zarr` itself. Install it with: - -``` -pip install zarr-metadata -``` - -The package has two layers and an optional integration: - -- **Typed JSON shapes** ([`zarr_metadata.v2`](v2.md) and - [`zarr_metadata.v3`](v3/index.md)): `TypedDict` definitions and `Literal` - aliases for the JSON documents specified by the - [Zarr v2](https://zarr-specs.readthedocs.io/en/latest/v2/v2.0.html) and - [Zarr v3](https://zarr-specs.readthedocs.io/en/latest/v3/core/index.html) - specifications, plus types for - [zarr-extensions](https://github.com/zarr-developers/zarr-extensions/) and a - few widely-used-but-unspecified entities (e.g. consolidated metadata). -- **Document models** ([`zarr_metadata.model`](model.md)): canonical - frozen-dataclass models of whole metadata documents, with structural - validators, loc-aware parsers, and store-key (de)serialization. -- **Optional Pydantic integration** ([`zarr_metadata.pydantic`](pydantic.md), - requires Pydantic 2.13 or newer): each model as a Pydantic field type that - validates raw documents through the same strict parser. - -Every public name is also re-exported at the top level, so -`from zarr_metadata import ZarrV3ArrayMetadataJSON` and -`from zarr_metadata.v3.array import ZarrV3ArrayMetadataJSON` are equivalent. - -The `TypedDict` definitions describe the static JSON shape of Zarr metadata -for type checkers. For strict, loc-aware runtime validation of JSON loaded -from a store, use the model parsers: - -```python exec="false" reason="zarr-metadata is not installed in the docs build environment" -import json -from zarr_metadata.model import ZarrV3ArrayMetadata - -with open("zarr.json", "rb") as f: - raw = json.load(f) - -metadata = ZarrV3ArrayMetadata.from_json(raw) -``` - -## Common types - -A few cross-cutting aliases are exported only from the top-level -`zarr_metadata` namespace: - -::: zarr_metadata.JSONValue - -::: zarr_metadata.ZarrV3NamedConfigJSON diff --git a/mkdocs.yml b/mkdocs.yml index 40077e0883..87aaf23430 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -92,17 +92,7 @@ nav: - ' zarr.testing.utils': api/zarr/testing/utils.md - ' zarr.zeros': api/zarr/functions/zeros.md - ' zarr.zeros_like': api/zarr/functions/zeros_like.md - - zarr-metadata: - - api/zarr_metadata/index.md - - ' zarr_metadata.model': api/zarr_metadata/model.md - - ' zarr_metadata.pydantic': api/zarr_metadata/pydantic.md - - ' zarr_metadata.v2': api/zarr_metadata/v2.md - - ' zarr_metadata.v3': - - api/zarr_metadata/v3/index.md - - ' zarr_metadata.v3.chunk_grid': api/zarr_metadata/v3/chunk_grid.md - - ' zarr_metadata.v3.chunk_key_encoding': api/zarr_metadata/v3/chunk_key_encoding.md - - ' zarr_metadata.v3.codec': api/zarr_metadata/v3/codec.md - - ' zarr_metadata.v3.data_type': api/zarr_metadata/v3/data_type.md + - 'zarr-metadata ↪': https://zarr-metadata.readthedocs.io/ - release-notes.md - contributing.md hooks: @@ -110,7 +100,6 @@ hooks: watch: - src/zarr - - packages/zarr-metadata/src - docs theme: @@ -170,7 +159,7 @@ plugins: enable_inventory: true handlers: python: - paths: [src/zarr, packages/zarr-metadata/src] + paths: [src/zarr] options: allow_inspection: true docstring_section_style: list diff --git a/packages/zarr-metadata/.readthedocs.yaml b/packages/zarr-metadata/.readthedocs.yaml new file mode 100644 index 0000000000..b89846f570 --- /dev/null +++ b/packages/zarr-metadata/.readthedocs.yaml @@ -0,0 +1,20 @@ +# Read the Docs configuration for the zarr-metadata docs site, separate from +# the zarr-python site configured by the repo-root .readthedocs.yaml. The RTD +# project for zarr-metadata must set its configuration-file path to +# packages/zarr-metadata/.readthedocs.yaml. +version: 2 + +build: + os: ubuntu-22.04 + tools: + python: "3.12" + jobs: + install: + - pip install --upgrade pip + - pip install ./packages/zarr-metadata --group packages/zarr-metadata/pyproject.toml:docs + build: + html: + - mkdocs build --strict -f packages/zarr-metadata/mkdocs.yml --site-dir $READTHEDOCS_OUTPUT/html + +mkdocs: + configuration: packages/zarr-metadata/mkdocs.yml diff --git a/packages/zarr-metadata/README.md b/packages/zarr-metadata/README.md index f8a34063b8..6b6b172aec 100644 --- a/packages/zarr-metadata/README.md +++ b/packages/zarr-metadata/README.md @@ -2,6 +2,8 @@ Python types, models, and validators for Zarr v2 and v3 metadata. +Documentation: + ## What this is Two layers and an optional integration: @@ -91,7 +93,9 @@ Package-scoped development commands live in the [`justfile`](./justfile) just test # run the test suite (extra args go to pytest) just lint # ruff, same invocation as CI just typecheck # pyright, pinned to the version CI uses +just docs-check # strict build of the docs site just check # all of the above +just docs-serve # serve the docs site locally ``` Run them from this directory, or from anywhere in the repository as diff --git a/packages/zarr-metadata/docs/api/index.md b/packages/zarr-metadata/docs/api/index.md new file mode 100644 index 0000000000..2aa39ab161 --- /dev/null +++ b/packages/zarr-metadata/docs/api/index.md @@ -0,0 +1,31 @@ +--- +title: API reference +--- + +# API reference + +The package is organized to mirror the structure of the Zarr specifications: + +- [`zarr_metadata.model`](model.md) — frozen-dataclass document models, + structural validators, loc-aware parsers, and the `UNSET` sentinel +- [`zarr_metadata.pydantic`](pydantic.md) — optional Pydantic field types + over the models +- [`zarr_metadata.v2`](v2.md) — `TypedDict` shapes for Zarr v2 documents + (`.zarray`, `.zgroup`, `.zattrs`, `.zmetadata`) +- [`zarr_metadata.v3`](v3/index.md) — `TypedDict` shapes for Zarr v3 + documents, with subpackages for [chunk grids](v3/chunk_grid.md), + [chunk key encodings](v3/chunk_key_encoding.md), [codecs](v3/codec.md), + and [data types](v3/data_type.md) + +Every public name is also re-exported at the top level, so +`from zarr_metadata import ZarrV3ArrayMetadataJSON` and +`from zarr_metadata.v3.array import ZarrV3ArrayMetadataJSON` are equivalent. + +## Common types + +A few cross-cutting aliases are exported only from the top-level +`zarr_metadata` namespace: + +::: zarr_metadata.JSONValue + +::: zarr_metadata.ZarrV3NamedConfigJSON diff --git a/docs/api/zarr_metadata/model.md b/packages/zarr-metadata/docs/api/model.md similarity index 100% rename from docs/api/zarr_metadata/model.md rename to packages/zarr-metadata/docs/api/model.md diff --git a/docs/api/zarr_metadata/pydantic.md b/packages/zarr-metadata/docs/api/pydantic.md similarity index 100% rename from docs/api/zarr_metadata/pydantic.md rename to packages/zarr-metadata/docs/api/pydantic.md diff --git a/docs/api/zarr_metadata/v2.md b/packages/zarr-metadata/docs/api/v2.md similarity index 100% rename from docs/api/zarr_metadata/v2.md rename to packages/zarr-metadata/docs/api/v2.md diff --git a/docs/api/zarr_metadata/v3/chunk_grid.md b/packages/zarr-metadata/docs/api/v3/chunk_grid.md similarity index 100% rename from docs/api/zarr_metadata/v3/chunk_grid.md rename to packages/zarr-metadata/docs/api/v3/chunk_grid.md diff --git a/docs/api/zarr_metadata/v3/chunk_key_encoding.md b/packages/zarr-metadata/docs/api/v3/chunk_key_encoding.md similarity index 100% rename from docs/api/zarr_metadata/v3/chunk_key_encoding.md rename to packages/zarr-metadata/docs/api/v3/chunk_key_encoding.md diff --git a/docs/api/zarr_metadata/v3/codec.md b/packages/zarr-metadata/docs/api/v3/codec.md similarity index 100% rename from docs/api/zarr_metadata/v3/codec.md rename to packages/zarr-metadata/docs/api/v3/codec.md diff --git a/docs/api/zarr_metadata/v3/data_type.md b/packages/zarr-metadata/docs/api/v3/data_type.md similarity index 100% rename from docs/api/zarr_metadata/v3/data_type.md rename to packages/zarr-metadata/docs/api/v3/data_type.md diff --git a/docs/api/zarr_metadata/v3/index.md b/packages/zarr-metadata/docs/api/v3/index.md similarity index 100% rename from docs/api/zarr_metadata/v3/index.md rename to packages/zarr-metadata/docs/api/v3/index.md diff --git a/packages/zarr-metadata/docs/index.md b/packages/zarr-metadata/docs/index.md new file mode 100644 index 0000000000..3a6bd2f07f --- /dev/null +++ b/packages/zarr-metadata/docs/index.md @@ -0,0 +1,97 @@ +--- +title: zarr-metadata +--- + +# zarr-metadata + +Spec-defined metadata types, models, and validators for Zarr v2 and v3. + +`zarr-metadata` is developed in the +[zarr-python repository](https://github.com/zarr-developers/zarr-python/tree/main/packages/zarr-metadata) +and released independently of `zarr` itself. Install it with: + +``` +pip install zarr-metadata +``` + +## What this is + +Two layers and an optional integration: + +- **Typed JSON shapes** ([`zarr_metadata.v2`](api/v2.md) and + [`zarr_metadata.v3`](api/v3/index.md)): `TypedDict` definitions and + `Literal` aliases for the JSON documents specified by the + [Zarr v2](https://zarr-specs.readthedocs.io/en/latest/v2/v2.0.html) and + [Zarr v3](https://zarr-specs.readthedocs.io/en/latest/v3/core/index.html) + specifications, plus types for + [zarr-extensions](https://github.com/zarr-developers/zarr-extensions/) and a + few widely-used-but-unspecified entities (e.g. consolidated metadata). +- **Document models** ([`zarr_metadata.model`](api/model.md)): canonical + frozen-dataclass models of whole metadata documents, with structural + validators, loc-aware parsers, and store-key (de)serialization. A document + produced by `to_json` shares no mutable state with the model that produced + it. +- **Optional Pydantic integration** ([`zarr_metadata.pydantic`](api/pydantic.md), + requires Pydantic 2.13 or newer): each model as a Pydantic field type that + validates raw documents through the same strict parser. + +## What this is for + +The public `TypedDict` definitions describe the static JSON shape of Zarr +metadata. For strict, loc-aware validation of JSON loaded from disk, use the +model parser: + +```python +import json +from zarr_metadata.model import ZarrV3ArrayMetadata + +with open("zarr.json", "rb") as f: + raw = json.load(f) + +metadata = ZarrV3ArrayMetadata.from_json(raw) +``` + +The optional Pydantic integration delegates raw input to the same strict +parser and returns the same normalized model class: + +```python +from pydantic import TypeAdapter +import zarr_metadata.pydantic as zmp + +metadata = TypeAdapter(zmp.ZarrV3ArrayMetadata).validate_python(raw) +encoded = metadata.to_key_value()["zarr.json"] +``` + +A bare `TypeAdapter` over a public document `TypedDict` is a coercive shape +adapter, not a Zarr conformance validator; it may coerce values or discard +members that the strict model parser rejects. + +## Validation boundary + +The model validators enforce the declared document structure and a small set +of context-free consistency rules, including fixed format literals, finite +JSON numbers, non-negative dimensions, non-empty v3 codec pipelines, and one +`dimension_names` entry per array dimension. They do not interpret extension +names or configurations, resolve codec pipelines, or decide whether a data +type, chunk grid, codec, or storage transformer is supported. Those decisions +belong to consumer implementations. + +## Scope + +At minimum, this library supports what Zarr-Python needs: the complete +Zarr v2 and v3 specs, consolidated metadata, and a subset of the metadata +defined in `zarr-extensions`. We are generally open to contributions that +add types, models, or structural validation for Zarr metadata with a +published spec. + +Runtime array behavior is out of scope: nothing here encodes or decodes +chunks, resolves codec or data type names to implementations, or performs +store I/O. The models begin and end at the metadata documents themselves — +`from_key_value` / `to_key_value` map documents to store keys and bytes, +and everything past that belongs to consumer libraries. + +## Reference + +- [API reference](api/index.md) +- [Changelog](https://github.com/zarr-developers/zarr-python/blob/main/packages/zarr-metadata/CHANGELOG.md) +- [License (MIT)](https://github.com/zarr-developers/zarr-python/blob/main/packages/zarr-metadata/LICENSE.txt) diff --git a/packages/zarr-metadata/justfile b/packages/zarr-metadata/justfile index cc5c7843f3..0f1861ed7d 100644 --- a/packages/zarr-metadata/justfile +++ b/packages/zarr-metadata/justfile @@ -17,25 +17,29 @@ lint: # correctly; 1.1.405+ regressed (microsoft/pyright#11115). Unpin when fixed. pyright_version := "1.1.404" -# Type-check the package sources. CI runs pyright on python 3.11; the pinned -# pyright predates 3.14, whose stdlib it cannot parse, so match CI's python. +# CI runs pyright on python 3.11; the pinned pyright predates 3.14, whose +# stdlib it cannot parse, so pin the interpreter to match CI. +# Type-check the package sources typecheck: uv run --python 3.11 --group test --with 'pyright=={{ pyright_version }}' pyright src # Run everything CI runs for this package -check: lint typecheck test +check: lint typecheck test docs-check # Preview the changelog that the next release would generate changelog-draft: uvx towncrier build --draft --version Unreleased -# Serve the zarr-python docs site, which includes this package's API reference. +# Build this package's documentation site, warnings as errors +docs-check: + env DISABLE_MKDOCS_2_WARNING=true uv run --group docs mkdocs build --strict + # With no argument, uses port 8000 if free, otherwise an ephemeral free port; # an explicitly requested port is used as-is so a conflict fails loudly. +# Serve this package's documentation site docs-serve port="": #!/usr/bin/env bash set -euo pipefail - cd ../.. port="{{ port }}" if [ -z "$port" ]; then port=$(uv run --group docs python -c ' @@ -51,19 +55,4 @@ docs-serve port="": s.close() ') fi - # Job control gives the server its own process group, so the trap can kill - # the whole uv->mkdocs tree, not just the uv wrapper. - set -m - env DISABLE_MKDOCS_2_WARNING=true uv run --group docs mkdocs serve -a "localhost:$port" & - server=$! - trap 'kill -- "-$server" 2>/dev/null' INT TERM EXIT - # mkdocs's own "Serving on" line points at the site root, which is the - # zarr-python landing page; print this package's corner of the site once - # the server is accepting connections. - while kill -0 "$server" 2>/dev/null && ! (exec 3<>"/dev/tcp/127.0.0.1/$port") 2>/dev/null; do - sleep 1 - done - if kill -0 "$server" 2>/dev/null; then - echo "zarr-metadata API reference: http://localhost:$port/api/zarr_metadata/" - fi - wait "$server" + exec env DISABLE_MKDOCS_2_WARNING=true uv run --group docs mkdocs serve -a "localhost:$port" diff --git a/packages/zarr-metadata/mkdocs.yml b/packages/zarr-metadata/mkdocs.yml new file mode 100644 index 0000000000..40912d6251 --- /dev/null +++ b/packages/zarr-metadata/mkdocs.yml @@ -0,0 +1,103 @@ +site_name: zarr-metadata +repo_name: zarr-developers/zarr-python +repo_url: https://github.com/zarr-developers/zarr-python +edit_uri: edit/main/packages/zarr-metadata/docs/ +site_description: Spec-defined metadata types, models, and validators for Zarr v2 and v3. +site_author: Davis Bennett +site_url: !ENV [READTHEDOCS_CANONICAL_URL, 'https://zarr-metadata.readthedocs.io/'] +docs_dir: docs +use_directory_urls: true + +nav: + - index.md + - API Reference: + - api/index.md + - ' zarr_metadata.model': api/model.md + - ' zarr_metadata.pydantic': api/pydantic.md + - ' zarr_metadata.v2': api/v2.md + - ' zarr_metadata.v3': + - api/v3/index.md + - ' zarr_metadata.v3.chunk_grid': api/v3/chunk_grid.md + - ' zarr_metadata.v3.chunk_key_encoding': api/v3/chunk_key_encoding.md + - ' zarr_metadata.v3.codec': api/v3/codec.md + - ' zarr_metadata.v3.data_type': api/v3/data_type.md + - Changelog: https://github.com/zarr-developers/zarr-python/blob/main/packages/zarr-metadata/CHANGELOG.md + +watch: + - src + +theme: + language: en + name: material + + palette: + # Light mode + - media: "(prefers-color-scheme: light)" + scheme: default + toggle: + icon: material/brightness-7 + name: Switch to dark mode + + # Dark mode + - media: "(prefers-color-scheme: dark)" + scheme: slate + toggle: + icon: material/brightness-4 + name: Switch to light mode + + font: + text: Roboto + code: Roboto Mono + + features: + - content.code.annotate + - content.code.copy + - navigation.indexes + - navigation.instant + - navigation.tracking + - search.suggest + - search.share + +plugins: + - autorefs + - search + - mkdocstrings: + enable_inventory: true + handlers: + python: + paths: [src] + options: + allow_inspection: true + docstring_section_style: list + docstring_style: numpy + inherited_members: true + line_length: 60 + separate_signature: true + show_root_heading: true + show_signature_annotations: true + show_source: true + show_symbol_type_toc: true + signature_crossrefs: true + show_if_no_docstring: true + extensions: + - griffe_inherited_docstrings + + inventories: + - https://docs.python.org/3/objects.inv + - https://zarr.readthedocs.io/en/stable/objects.inv + +markdown_extensions: + - admonition + - attr_list + - def_list + - footnotes + - md_in_html + - pymdownx.details + - pymdownx.superfences + - toc: + permalink: true + - pymdownx.highlight: + anchor_linenums: true + line_spans: __span + pygments_lang_class: true + - pymdownx.inlinehilite diff --git a/packages/zarr-metadata/pyproject.toml b/packages/zarr-metadata/pyproject.toml index 4e31643670..6e97d26409 100644 --- a/packages/zarr-metadata/pyproject.toml +++ b/packages/zarr-metadata/pyproject.toml @@ -44,10 +44,21 @@ Homepage = "https://github.com/zarr-developers/zarr-python" Source = "https://github.com/zarr-developers/zarr-python/tree/main/packages/zarr-metadata" Issues = "https://github.com/zarr-developers/zarr-python/issues" Changelog = "https://github.com/zarr-developers/zarr-python/blob/main/packages/zarr-metadata/CHANGELOG.md" -Documentation = "https://zarr.readthedocs.io/en/latest/api/zarr_metadata/" +Documentation = "https://zarr-metadata.readthedocs.io/" [dependency-groups] test = ["pytest", "pydantic>=2.13", "jsonschema"] +docs = [ + # Pins match the zarr-python docs environment in the repo-root + # pyproject.toml so the two sites render with the same toolchain. + "mkdocs-material==9.7.6", + "mkdocs==1.6.1", + "mkdocstrings==1.0.4", + "mkdocstrings-python==2.0.5", + "griffe-inherited-docstrings==1.1.3", + # mkdocstrings uses ruff to format rendered signatures + "ruff==0.15.20", +] [tool.hatch.version] source = "vcs" From 1c3b74359476b64236007ddf89b2dbc21ff4ecf9 Mon Sep 17 00:00:00 2001 From: Davis Vann Bennett Date: Wed, 29 Jul 2026 18:55:25 +0200 Subject: [PATCH 6/7] update index.md --- packages/zarr-metadata/docs/index.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/zarr-metadata/docs/index.md b/packages/zarr-metadata/docs/index.md index 3a6bd2f07f..2004f2dc54 100644 --- a/packages/zarr-metadata/docs/index.md +++ b/packages/zarr-metadata/docs/index.md @@ -4,7 +4,7 @@ title: zarr-metadata # zarr-metadata -Spec-defined metadata types, models, and validators for Zarr v2 and v3. +Basic tools for modelling Zarr metadata, with minimal dependencies. `zarr-metadata` is developed in the [zarr-python repository](https://github.com/zarr-developers/zarr-python/tree/main/packages/zarr-metadata) @@ -14,9 +14,14 @@ and released independently of `zarr` itself. Install it with: pip install zarr-metadata ``` +## Who needs this + +This library might be useful to you if your software interacts with Zarr metadata documents. + ## What this is -Two layers and an optional integration: +This library is *not* a full Zarr implementation. Instead, it's a collection of data structures and routines that +closely model the content of the Zarr specifications, such as: - **Typed JSON shapes** ([`zarr_metadata.v2`](api/v2.md) and [`zarr_metadata.v3`](api/v3/index.md)): `TypedDict` definitions and From 9c804f5d3e2b7e0619a701918f5eb84cc6d77695 Mon Sep 17 00:00:00 2001 From: Davis Vann Bennett Date: Wed, 29 Jul 2026 19:11:18 +0200 Subject: [PATCH 7/7] ci(zarr-metadata): delegate workflow steps to the justfile The workflow duplicated every command the justfile defines; jobs now run 'just test/lint/typecheck/docs-check' so the justfile is the single source of truth for the package's verbs. CI keeps only its own concerns: the python matrix sync for pytest, and uv caching. The pyright job's python/sync steps are dropped because the typecheck recipe pins the interpreter and pyright version itself. Assisted-by: ClaudeCode:claude-fable-5 --- .github/workflows/zarr-metadata.yml | 31 +++++++++++++++-------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/.github/workflows/zarr-metadata.yml b/.github/workflows/zarr-metadata.yml index 91609f82fa..b5f56dd508 100644 --- a/.github/workflows/zarr-metadata.yml +++ b/.github/workflows/zarr-metadata.yml @@ -1,5 +1,8 @@ name: zarr-metadata +# Job steps delegate to packages/zarr-metadata/justfile, the single source of +# truth for this package's verbs; CI owns only the python matrix and caching. + on: push: branches: [main] @@ -39,12 +42,14 @@ jobs: uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2 with: enable-cache: true + - name: Install just + uses: extractions/setup-just@53165ef7e734c5c07cb06b3c8e7b647c5aa16db3 # v4 - name: Set up Python ${{ matrix.python-version }} run: uv python install ${{ matrix.python-version }} - name: Sync test dependency group run: uv sync --group test --python ${{ matrix.python-version }} - name: Run pytest - run: uv run --group test pytest tests + run: just test ruff: name: ruff @@ -59,8 +64,10 @@ jobs: persist-credentials: false - name: Install uv uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2 + - name: Install just + uses: extractions/setup-just@53165ef7e734c5c07cb06b3c8e7b647c5aa16db3 # v4 - name: Run ruff - run: uvx ruff check . + run: just lint pyright: name: pyright @@ -77,15 +84,11 @@ jobs: uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2 with: enable-cache: true - - name: Set up Python - run: uv python install 3.11 - - name: Sync test dependency group - run: uv sync --group test --python 3.11 + - name: Install just + uses: extractions/setup-just@53165ef7e734c5c07cb06b3c8e7b647c5aa16db3 # v4 - name: Run pyright - # Pinned to the last version that types PEP 661 sentinels in class - # attributes correctly; 1.1.405+ regressed (microsoft/pyright#11115). - # Unpin when the fix lands. - run: uv run --group test --with 'pyright==1.1.404' pyright src + # The pyright version and interpreter pins live in the justfile. + run: just typecheck docs: name: docs @@ -102,12 +105,10 @@ jobs: uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2 with: enable-cache: true - - name: Sync docs dependency group - run: uv sync --group docs + - name: Install just + uses: extractions/setup-just@53165ef7e734c5c07cb06b3c8e7b647c5aa16db3 # v4 - name: Build docs - run: uv run --group docs mkdocs build --strict - env: - DISABLE_MKDOCS_2_WARNING: "true" + run: just docs-check zarr-metadata-complete: name: zarr-metadata complete