Conversation
…s its specification says "Chunk sizes must be greater than zero" (https://github.com/zarr-developers/zarr-specs/blob/fc7dd9c9beb5a50b87f9b08b00bf50fc0048482f/docs/v3/chunk-grids/regular-grid/index.rst#L40), along a dimension of length 0 too. `RegularChunkGridConfiguration` bounded its lengths with `Ge(0)`, and its shape rules took a 0 on an empty dimension, reading the core specification's "The chunk shape elements are non-zero when the corresponding dimensions of the arrays have non-zero length" as allowing it. That sentence says less than the grid's own. The bound is now `Ge(1)`, so a 0 is an `invalid_value` at its place wherever it is, and the shape rules check only that the grid has the array's dimensionality. `create_default` already wrote 1 there. BREAKING CHANGE: a regular grid with a chunk length of 0 on a dimension of length 0, as zarr-python 3.0 and 3.1 wrote one, is now refused. Assisted-by: ClaudeCode:claude-opus-5-5
… and a zarr.json As pydantic's `TypeAdapter(...).json_schema()` and zod's `toJSONSchema` write theirs, in draft 2020-12: - `json_schema(shape)`, in `zarr_metadata.typed_json`, writes a TypedDict as `check` reads it. A bound is JSON Schema's keyword for it, the stricter where a type and its `NewType` both say one, and a `Doc` the `description`. Each TypedDict and type alias is written once, in `$defs`, under its name. - `field_json_schema(kind, context)`, in `zarr_metadata.v3.definition`, writes a field of one kind as a scope reads it: each definition's field, and a name none of them is written with, with any configuration. Raw bits' name is matched to its end, so a validator that matches patterns as Python does takes no final newline for it. - `node_metadata_json_schema_v3(context=...)`, in `zarr_metadata.model`, writes a `zarr.json`: its fill value held to the data type it names, and a group's consolidated metadata holding documents. `Schemas` writes each shape, asking a caller's `SchemaLeaf` first, as the checker asks a `Leaf`, and hands back a schema sharing nothing. A schema says what the types say and not what the rules say, so every JSON document the package finds nothing wrong with, the schema accepts. Property tests hold the typed_json schema to the checker's reference, bounds in layers to what `check` holds a value to, and fields and documents changed in one or two places to soundness. JSON Schema takes `1.0` for an integer. Only a `Doc` is a description, as in zod: the package's docstrings are written for Python's readers. The six field aliases move to `v3._common`, so `ZarrV3ArrayMetadataJSON` says what each extension point is: `data_type: DataTypeField`, `codecs: tuple[CodecField, ...]`. To a type checker and to `check` they are the JSON they were, and the model's tables of extension points are read off the TypedDict. `shape` holds integers of at least 0, which `check` now holds it to. A data type whose `fill_value` holds a metadata field is refused when it is built, since the checker reads a fill value as a value and a schema would write it as a field. Assisted-by: ClaudeCode:claude-opus-5-5
This branch has not been deployed
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
🤖 AI text below 🤖
JSON Schemas of what the package reads, draft 2020-12, as pydantic's
TypeAdapter(...).json_schema()and zod'stoJSONSchemawrite theirs.node_metadata_json_schema_v3(context=...), inzarr_metadata.model,is a
zarr.json's, an array's or a group's, for an editor or avalidator in another language: each extension point a field as its
scope reads it -- a configuration as its definition's TypedDict says,
bounds and all, or a name nothing in the scope claims, with any
configuration -- the fill value what the data type it names takes, and
a group's consolidated metadata the documents it holds.
field_json_schema(kind, context), inzarr_metadata.v3.definition, isone field's, and
json_schema(shape), inzarr_metadata.typed_json,any TypedDict's, as
checkreads it. What the rules say of memberstogether is not in a schema, so a document it accepts may still have a
problem; a JSON document the validators accept, it accepts. JSON Schema
takes
1.0for an integer, where the package wants1. A v3 arraydocument's extension points are annotated with the field aliases --
data_type: DataTypeField,codecs: tuple[CodecField, ...]-- whichare the JSON a metadata field is, so a type checker and
checkreadthem as before; its
shapeholds integers of at least 0, whichchecknow holds it to. A data type whose
fill_valueholds a metadata fieldis refused when it is built: a fill value is a value of its data type.
The
regularchunk grid refuses a chunk length of 0, along a dimensionof length 0 too, as its specification says: "Chunk sizes must be greater
than zero".
RegularChunkGridConfiguration.chunk_shapeistuple[Annotated[int, Ge(1)], ...], so a 0 is aninvalid_valueat itsplace, with the bound in its
ctx. The package had read the corespecification's "The chunk shape elements are non-zero when the
corresponding dimensions of the arrays have non-zero length" as allowing
0 on an empty dimension, as zarr-python 3.0 and 3.1 wrote it; that
sentence says less than the grid's own, not something else.
Three functions, each beside the reader it describes
json_schema(shape),zarr_metadata.typed_jsoncheckreads itcheckfield_json_schema(kind, context),zarr_metadata.v3.definitionresolvenode_metadata_json_schema_v3(context=...),zarr_metadata.modelzarr.jsonvalidate_node_metadata_v3What a schema holds
A field in a scope is one of three things:
const, its configuration's TypedDict in$defs,must_understand: trueif present, and the bare name when no configuration is required;rand digits, matched to the end of the name, with nothing configured beside it;A shard's
index_codecstakes codecs of static size, and names nothing claims.A
zarr.jsonholds its fill value to the data type it names, with oneif/thenper data type in scope:"int8"makes the fill value an integer in [-128, 127]. A group'sconsolidated_metadataholds array and group documents, or isnull.Not in any schema: the rules. Those include one dimension name per dimension, a grid that fits the shape, the pipeline's order, each codec against its chunk, blosc's
typesizeagainstshuffle, and a hex fill value's width. So a schema is sound rather than exact.Layout. Each TypedDict and type alias goes in
$defsunder its name (GzipCodecConfiguration,CodecField,ZarrV3ArrayMetadataJSON), numbered on a clash. The root is written in place unless something refers to it. No part of a returned schema is shared with another.Changes that come with it
v3._common, andZarrV3ArrayMetadataJSONand its Partial annotate their extension points with them. The model's tables of extension points are now read off that TypedDict, so one declaration says which member is which kind.shapeistuple[Annotated[int, Ge(0)], ...].fill_valueholds a field alias is refused when built. The checker reads a fill value as a value, and a schema would write it as a field.What changes for a caller
chunk_shape: [0, 4]overshape: [0, 4]invalid_valueatchunk_shape.0,ctx{"ge": 1}expected a chunk length >= 1 for a dimension of length 128, got 0expected an integer >= 1, got 0check(doc, ZarrV3ArrayMetadataJSON)with a negative dimensioninvalid_valueat("shape", i)typeddict_keys(ZarrV3ArrayMetadataJSON).members["data_type"]str | ZarrV3NamedConfigJSONDataTypeField, an alias of itDataTypeDefinition(..., fill_value=tuple[CodecField, ...])TypeErrorSpec correction
The regular-grid commit follows a correction at review. The agent had justified a test change by saying a regular grid takes a chunk length of 0 on an empty dimension. The grid's own page says otherwise: "Chunk sizes must be greater than zero" (
chunk-grids/regular-grid/index.rstL40, since zarr-specs f538382). The README had listed following the core sentence as a choice the package made; that choice is gone.create_defaultalready wrote 1 there.Verification
1.0as1: 300 examples in CI, 10,000 locally.Annotated,NewTypeand type aliases are written ascheckholds a value to them.json, then judged in core, core-and-extensions and an empty scope.typesize(6,564 fields), a grid that doesn't fit its shape (1,267 documents), pipeline order, index codecendian, fill value rules, andzarr_format: 3.0, which JSON Schema takes for 3.RecursionErroron 34 deeply nested document–scope pairs, as feat(zarr-metadata): with_problems groups a read's problems by field, and canonical_of spells a field read already #377 does;jsonschemaruns out of stack on 50 deep documents.$defs.jsonschemavalidates a typical document in 0.56 ms;validate_node_metadata_v3takes 0.04 ms.The zarr-extensions registry, cross-checked
The copy is the one vscode-zarr vendors, at 4da7b37a, checked over the corpus fields for the 32 names both define.
must_understand, at every name;"int8","crc32c","default","v2","scale_offset";{"name": "int8", "configuration": {}};codecs.rectilinear;must_understand: false;level: 99, a dynamic index codec, a struct field'sscale_factor: 0.Nothing was filed upstream.
Scenario re-runs
The recordings are updated in the untracked copy on this branch's worktree.
valid_reshape_zero_length_dimension.jsonnow chunks its empty dimension by 1, as the spec asks, and reads again.Reviews
4443.feature.3.mdthat described the old zero-length rule (dropped);checkholding a document'sshapeto its bound (added).Schemas.definedleft a reserved entry behind when writing it failed. It now gives the reservation up; a test pins it.$, which a Python validator also matches before a final newline. So{"name": "r16\n", "configuration": {"x": 1}}, which names nothing, was refused. It now ends in(?![\s\S]), and table rows pin it; the mutation tests rarely reach that case on their own.to_json()'s tuples. It now says JSON as a parser gives it.NewTypewere merged by overwriting. They now take the stricter, with a property test.written_name, one declaration of how a document names a definition;isinstancebecoming acast;Choices worth a look
Doconly, as in zod, not from docstrings, as in pydantic, because the package's docstrings are written for Python readers. Nothing in the package carries aDocyet, so its own schemas have no descriptions.$defs/ZarrV3ArrayMetadataJSONor$defs/ZarrV3GroupMetadataJSON.JSONSchemajoins the public naming grammar's standalone vocabulary, besideJSONValue.Left out
consolidated_metadataonZarrV3GroupMetadataJSON. The spec now names this member. Declaring it would remove_groupandadditional_reserved_keys, but needs the consolidated TypedDict to move intogroup.py, and changes a public document type._pydantic_schema.py.generate_schemas.pyreads the private_pydantic_schematoday.contains/maxContains;Docs on the document TypedDicts.Stack
Stacked on #377 (
feat/zarr-metadata-field-problems), itself on #376 → #374 → #373 → #372 → #371 → #370. Merge after #377. Fragments:378.feature.mdand378.bugfix.md; this PR also drops the now-untrue zero-length clauses from371.doc.mdand4443.feature.3.md. Two commits: the grid fix first, then the schemas.🤖 Generated with Claude Code