forked from zarr-developers/zarr-python
-
Notifications
You must be signed in to change notification settings - Fork 0
feat(zarr-metadata): composition rules layer, shape-exact codec guards, typed builders #296
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
d-v-b
wants to merge
45
commits into
main
Choose a base branch
from
claude/zarr-metadata-typeddict-builder-cd5f75
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 31 commits
Commits
Show all changes
45 commits
Select commit
Hold shift + click to select a range
8da1333
chore(deps): bump the actions group across 1 directory with 8 updates…
dependabot[bot] 659c734
Merge branch 'main' of https://github.com/d-v-b/zarr-python
d-v-b 51c994b
Merge branch 'main' of https://github.com/zarr-developers/zarr-python
d-v-b 7732db3
Merge branch 'main' of https://github.com/zarr-developers/zarr-python
d-v-b 913b41b
Merge branch 'main' of https://github.com/zarr-developers/zarr-python
d-v-b 117b7ba
Merge branch 'main' of github.com:d-v-b/zarr-python
d-v-b d4de75d
Merge branch 'main' of github.com:zarr-developers/zarr-python
d-v-b 86dabd5
Merge branch 'main' of github.com:zarr-developers/zarr-python
d-v-b a2e6002
Merge branch 'main' of https://github.com/d-v-b/zarr-python
d-v-b 1621e1d
Merge branch 'main' of https://github.com/zarr-developers/zarr-python
d-v-b db473cd
Merge branch 'main' of https://github.com/zarr-developers/zarr-python
d-v-b dca5641
Merge branch 'main' of https://github.com/d-v-b/zarr-python
d-v-b a399213
Merge branch 'main' of https://github.com/zarr-developers/zarr-python
d-v-b 9bfe855
fix: byte-order handling for structured dtypes in the bytes codec (#220)
d-v-b 16b4ff2
Merge branch 'main' of https://github.com/zarr-developers/zarr-python
d-v-b 273dd73
Merge branch 'main' of https://github.com/zarr-developers/zarr-python
d-v-b df56f7e
Merge branch 'main' of https://github.com/zarr-developers/zarr-python
d-v-b f73ef8c
Merge branch 'main' of https://github.com/zarr-developers/zarr-python
d-v-b 4fb538c
Merge branch 'main' of https://github.com/zarr-developers/zarr-python
d-v-b df480ae
Merge remote-tracking branch 'origin/main' into claude/zarr-metadata-…
d-v-b 1c13c6c
fix(zarr-metadata): make concrete v3 entity types assignable to ZarrV…
d-v-b e3e7328
feat(zarr-metadata): codec kind classification with TypeIs guards
d-v-b 43b0bb5
feat(zarr-metadata): ZarrV3ArrayMetadataBuilder with eager semantic r…
d-v-b 4531f31
fix(zarr-metadata): close adversarial-QA gaps in the v3 array builder
d-v-b f935586
feat(zarr-metadata): create_* factories for one-shot document constru…
d-v-b 51631c4
Merge remote-tracking branch 'origin/main' into claude/zarr-metadata-…
d-v-b d97b7bc
fix(zarr-metadata): close review findings in the builder layer
d-v-b 20b513d
fix(zarr-metadata): make the codec TypeIs guards shape-exact
d-v-b 044426b
refactor(zarr-metadata): promote composition rules to zarr_metadata.r…
d-v-b 011c088
feat(zarr-metadata): fill the v3 composition-rule inventory
d-v-b cb8f8e7
docs(zarr-metadata): document the rules and builder layers
d-v-b 27e3692
refactor(zarr-metadata)!: validation reports are tuples, not lists
d-v-b 5cc463f
refactor(zarr-metadata): remove Any from the test suite and ban it in…
d-v-b 8cf616b
feat(zarr-metadata): unknown configuration members get their own kind
d-v-b a1581e9
refactor(zarr-metadata): register rules at definition, own them per e…
d-v-b e6cc475
feat(zarr-metadata): add check_* returning a Valid | Invalid union
d-v-b 44ea2e2
feat(zarr-metadata): model extension points, provenance, and name can…
d-v-b 88809df
docs(zarr-metadata): state the shared-namespace assumption behind the…
d-v-b f1e3895
fix(zarr-metadata): scope entity shapes by extension point
d-v-b b1a84ef
fix(zarr-metadata): validate every modelled extension point
d-v-b 8042e72
docs(zarr-metadata): tighten API prose
d-v-b 93bfee4
fix(zarr-metadata): close the review findings on the extension-point …
d-v-b 6cc53a1
feat(zarr-metadata): propagate the array spec through the codec chain
d-v-b 850bc3f
feat(zarr-metadata): carry the fill value in ArraySpec, with UNKNOWN …
d-v-b 7dd7f3d
fix(zarr-metadata): enforce composition constraints
d-v-b File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
33 changes: 33 additions & 0 deletions
33
packages/zarr-metadata/changes/+array-v3-builder.feature.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| Added `zarr_metadata.builder`: incremental, validated construction of v3 | ||
| array metadata documents over the plain JSON TypedDict shapes. | ||
| `ZarrV3ArrayMetadataBuilder` accumulates a | ||
| `ZarrV3ArrayMetadataJSONPartial` and hands out evolved copies: | ||
| `evolve(**kwargs)` is the single fully-typed setter (unknown keys and | ||
| wrong value types are static errors), `evolve_extension` sets extension | ||
| fields, `without` unsets keys (absence is UNSET; a stored `None` is JSON | ||
| `null`, and the two never convert), per-field properties answer | ||
| `T | UNSET`, `build()` returns the validated complete document, and | ||
| `to_partial_json()` returns the fragment under an honest partial type — | ||
| there is no `build_unchecked`. Input arrays are materialized as tuples at | ||
| ingestion (so documents straight from `json.loads` normalize, builders | ||
| never share mutable state with callers, and equality is | ||
| list/tuple-spelling-insensitive). | ||
|
|
||
| Semantic rules live as data (`Rule`, keyed by the document keys they | ||
| depend on) and fire eagerly after every change, whenever their | ||
| dependencies are all present — so field order is unconstrained, coupled | ||
| fields are checked as soon as they coexist, and a conflict names both | ||
| fields plus the batch-`evolve` escape hatch. The initial rule set checks | ||
| fill_value against the data type (with range checks for ints and the | ||
| spec's special float spellings), codec pipeline kind ordering | ||
| (classified by name across every spelling, so two spellings of the same | ||
| pipeline always get the same verdict), known-name codec and chunk-grid | ||
| spellings (bare short-hand only where the concrete type permits it, | ||
| required configuration keys present — derived from the TypedDicts' | ||
| `__required_keys__`, never restated by hand), `dimension_names` length, | ||
| and `regular` chunk grid dimensionality. Rules never reject what they | ||
| cannot interpret: unknown data types, codecs, and configurations pass | ||
| through (extension openness) — but openness is for genuinely unknown | ||
| names only; a name this package defines is held to its canonical | ||
| spellings rather than passing as an unknowable extension. All problems | ||
| from a check are reported together in one `MetadataValidationError`. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| Added `zarr_metadata.v3.codec.kind`: codec kind classification. One | ||
| branded union per spec pipeline kind over the concrete codec types | ||
| (`ArrayArrayCodecMetadata`, `ArrayBytesCodecMetadata`, | ||
| `BytesBytesCodecMetadata`, plus `KnownCodecMetadata` and the paired | ||
| `*_CODEC_NAMES` constants), and `TypeIs` guards | ||
| (`is_array_array_codec`, `is_array_bytes_codec`, `is_bytes_bytes_codec`, | ||
| `is_known_codec`) that narrow a codec entry to the matching union. The | ||
| guards are **shape-exact**: `TypeIs` narrowing is two-sided, so a guard | ||
| answers `True` exactly when the value is an instance of a canonical | ||
| codec type — bare spellings only where the codec's spec permits them, | ||
| object forms deep-checked against their TypedDicts (key sets and | ||
| configuration value types, judged at the canonical data level with JSON | ||
| arrays as tuples and `int` meaning JSON integer, not boolean). Unknown | ||
| codec names answer `False` to every guard, so extension codecs classify | ||
| as "unknown kind" rather than being misassigned. The companion | ||
| `codec_kind_of_name` classifies by name alone, returning a `CodecKind` | ||
| literal or `None`, for ordering semantics where a known codec in an | ||
| invalid spelling must still rank as its kind. All names are re-exported | ||
| from `zarr_metadata.v3.codec`. |
31 changes: 31 additions & 0 deletions
31
packages/zarr-metadata/changes/+document-factories.feature.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| Added `create_*` factories in `zarr_metadata.builder` — one per public | ||
| document TypedDict (`create_zarr_v3_array_metadata_json`, | ||
| `create_zarr_v3_group_metadata_json`, `create_zarr_v3_consolidated_metadata_json`, | ||
| `create_zarr_v2_array_metadata_json`, `create_zarr_v2_group_metadata_json`, | ||
| `create_zarr_v2_z_array_json`, `create_zarr_v2_z_group_json`, | ||
| `create_zarr_v2_consolidated_metadata_json`), each taking | ||
| `**kwargs: Unpack[<TypedDict>]`. At literal-keyword call sites, unpacking | ||
| the total TypedDict makes a missing required key and a wrong value type | ||
| static errors (a `**`-splatted mapping bypasses that coverage — the | ||
| runtime pass exists for exactly those callers): each factory deep-copies | ||
| its inputs, materializes JSON arrays as tuples, runs the structural | ||
| validator and the composition rules, and raises one | ||
| `MetadataValidationError` carrying every problem. The strict on-disk | ||
| `.zarray`/`.zgroup` factories reject `attributes` at runtime, and the v2 | ||
| consolidated factory checks the `.zmetadata` envelope. The open v3 | ||
| array/group factories take an `extensions=` mapping for extension fields | ||
| (the hatch for type checkers without PEP 728 support); extension names | ||
| that shadow standard keys are rejected. | ||
|
|
||
| This encodes a package rule — every public *document* TypedDict gets a | ||
| factory — enforced by a drift test against the `DOCUMENT_FACTORIES` | ||
| registry, so a new document type cannot ship without one. The rule is | ||
| deliberately scoped to documents: entity TypedDicts (codec objects, | ||
| configurations, ...) are constructed with TypedDict constructor syntax, | ||
| which already enforces their shape statically, and no semantic rules | ||
| apply to an entity in isolation. | ||
|
|
||
| Prefer the factories for one-shot construction (the common case); | ||
| `ZarrV3ArrayMetadataBuilder` remains for staged assembly across program | ||
| points, where its eager rule firing and cross-call conflict attribution | ||
| apply. |
25 changes: 25 additions & 0 deletions
25
packages/zarr-metadata/changes/+entity-assignability.bugfix.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| Concrete v3 entity types are now assignable to the fields they describe. | ||
| Previously, none of the package's canonical codec / chunk-grid / | ||
| chunk-key-encoding / data-type types (e.g. `BloscCodecMetadata`, | ||
| `RegularChunkGridMetadata`) satisfied `ZarrV3MetadataFieldJSON`, so a | ||
| type checker rejected putting them into the very fields they document | ||
| (`codecs`, `chunk_grid`, `data_type`, ...). Three changes fix this: | ||
|
|
||
| - `ZarrV3NamedConfigJSON.name` and `.configuration` are now `ReadOnly` | ||
| (PEP 705), making them covariant so concrete `name: Literal[...]` and | ||
| required-`configuration` shapes are accepted. | ||
| - `ZarrV3NamedConfigJSON` is now `closed` (PEP 728): the spec's | ||
| named-configuration envelope has exactly `name` / `configuration` / | ||
| `must_understand`, and closing the type also makes it usable as a | ||
| `JSONValue` (needed for e.g. the `sharding_indexed` inner `codecs`). | ||
| - Every concrete `*Object` / `*Configuration` TypedDict is now `closed`, | ||
| and object forms declare `must_understand: NotRequired[bool]` (any v3 | ||
| metadata field may carry the extension member). | ||
|
|
||
| **Soft-breaking** for type-checking consumers: dicts with keys beyond the | ||
| declared shape no longer satisfy the closed types, and `name` / | ||
| `configuration` can no longer be mutated through `ZarrV3NamedConfigJSON`. | ||
| Both were previously accepted by type checkers but produced documents | ||
| outside the spec's shapes. `zarr_metadata.pydantic` serializers now | ||
| declare their return schema via the pydantic-facing shadow types, so | ||
| pydantic schema generation stays warning-free. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| Added `zarr_metadata.rules`: composition rules for full metadata | ||
| documents, promoting the rule engine out of the builder into a layer of | ||
| its own. The package now models metadata in three layers with one | ||
| contract each — `model` checks structure element by element, | ||
| `rules` judges composition across the document, and `builder` constructs | ||
| while applying both. | ||
|
|
||
| - **Rule sets**: `ZARR_V3_ARRAY_RULES` grows to twelve rules — fill | ||
| value vs. data type, codec pipeline kind ordering, known-name shapes, | ||
| dimension-name counts, chunk-grid values (positive extents) and | ||
| geometry (regular rank; rectilinear rank and per-dimension chunk-size | ||
| sums, RLE pairs included), transpose orders (self-permutation at any | ||
| depth, rank agreement with `shape`), and sharding (inner `codecs` and | ||
| `index_codecs` judged as pipelines recursively at every nesting depth; | ||
| inner chunk shapes positive, rank-matched, and evenly dividing the | ||
| enclosing chunk, recursively). New `ZARR_V2_ARRAY_RULES` | ||
| (chunks/shape rank agreement) and `ZARR_V3_GROUP_RULES` (inline | ||
| consolidated metadata recurses, judging each embedded child document | ||
| by its own rules at its path). | ||
| - **Read-side trios**: `validate_*` / `is_*` / `parse_*` for array and | ||
| group documents in both format versions mirror the model layer's | ||
| grammar with a stronger judgment — structure *and* composition, every | ||
| problem reported together, JSON arrays normalized to tuples before | ||
| judgment. The `is_*` functions deliberately return `bool` rather than | ||
| `TypeIs`: a composition-invalid document is still an instance of the | ||
| TypedDict, so only the structural layer can narrow honestly. | ||
| - **Boundary change**: two composition checks that lived in the | ||
| structural validator moved here — v3 `dimension_names` vs `shape` and | ||
| v2 `chunks` vs `shape` rank agreement. `zarr_metadata.model`'s | ||
| validators, parsers, and dataclasses now accept those documents (they | ||
| are lossless, structurally well-formed representations of what a store | ||
| may contain); use the `rules` trios to judge them. This also removes | ||
| the double report the overlap used to produce. | ||
| - **Strictness stance**, now documented on the package: `zarr_metadata` | ||
| models canonical documents and is deliberately stricter than any given | ||
| implementation; implementations coerce ambiguous input as they see fit | ||
| and then validate the canonical result. | ||
|
|
||
| Known follow-up: v2 fill-value/dtype consistency (NumPy dtype grammar) | ||
| has no rule yet. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| title: builder | ||
| --- | ||
|
|
||
| ::: zarr_metadata.builder |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| title: rules | ||
| --- | ||
|
|
||
| ::: zarr_metadata.rules |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
54 changes: 54 additions & 0 deletions
54
packages/zarr-metadata/src/zarr_metadata/builder/__init__.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| """Validated construction of Zarr metadata documents. | ||
|
|
||
| The construction layer is a consumer of the package's other two layers: | ||
| the model layer checks structure, `zarr_metadata.rules` judges | ||
| composition, and the surfaces here apply both while a document is being | ||
| put together. | ||
|
|
||
| Two construction surfaces over the plain JSON shapes defined in | ||
| `zarr_metadata.v2` / `zarr_metadata.v3`: | ||
|
|
||
| - **`create_*` factories** — one per public document TypedDict, taking | ||
| `**kwargs: Unpack[<TypedDict>]`. One-shot construction: at | ||
| literal-keyword call sites, required keys and value types are enforced | ||
| statically; the runtime pass normalizes, checks structure, and runs | ||
| the composition rules, raising one `MetadataValidationError` with | ||
| every problem. Prefer these when all fields are known at a single call | ||
| site — which is the common case. For validating documents you *read* | ||
| rather than construct, use the trios in `zarr_metadata.rules`. | ||
| - **`ZarrV3ArrayMetadataBuilder`** — incremental accumulation for staged | ||
| assembly across program points. Composition rules fire eagerly as | ||
| fields land, whenever their dependencies are all present, so field | ||
| order is unconstrained, problems surface at the `evolve` call that | ||
| completes them, and a cross-call conflict names both fields involved. | ||
| Completeness can only be checked at `build()` time, at runtime — the | ||
| price of accumulating through a partial type. Incremental building is | ||
| currently implemented for v3 arrays only, the document type with the | ||
| richest cross-field coupling. | ||
| """ | ||
|
|
||
| from zarr_metadata.builder._array_v3 import ZarrV3ArrayMetadataBuilder | ||
| from zarr_metadata.builder._create import ( | ||
| DOCUMENT_FACTORIES, | ||
| create_zarr_v2_array_metadata_json, | ||
| create_zarr_v2_consolidated_metadata_json, | ||
| create_zarr_v2_group_metadata_json, | ||
| create_zarr_v2_z_array_json, | ||
| create_zarr_v2_z_group_json, | ||
| create_zarr_v3_array_metadata_json, | ||
| create_zarr_v3_consolidated_metadata_json, | ||
| create_zarr_v3_group_metadata_json, | ||
| ) | ||
|
|
||
| __all__ = [ | ||
| "DOCUMENT_FACTORIES", | ||
| "ZarrV3ArrayMetadataBuilder", | ||
| "create_zarr_v2_array_metadata_json", | ||
| "create_zarr_v2_consolidated_metadata_json", | ||
| "create_zarr_v2_group_metadata_json", | ||
| "create_zarr_v2_z_array_json", | ||
| "create_zarr_v2_z_group_json", | ||
| "create_zarr_v3_array_metadata_json", | ||
| "create_zarr_v3_consolidated_metadata_json", | ||
| "create_zarr_v3_group_metadata_json", | ||
| ] | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
prefer create_zarr_v2_zarray_json and create_zarr_v2_zgroup_json. ensure that no other instances of "z_array" and "z_group" exist.