Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions packages/zarr-metadata/changes/4232.removal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
Unified the naming grammar for SCREAMING_SNAKE constants with the one used for
type names. A constant's name is now a purely syntactic transformation of the
name of the `Literal` type it manifests, so the format version is spelled
`ZARR_V2`/`ZARR_V3` and comes first, matching the `ZarrV2`/`ZarrV3` prefix on
the corresponding type:

- `ARRAY_METADATA_STORE_KEY_V2` → `ZARR_V2_ARRAY_METADATA_STORE_KEY`
- `ARRAY_METADATA_STORE_KEY_V3` → `ZARR_V3_ARRAY_METADATA_STORE_KEY`
- `ATTRIBUTES_STORE_KEY_V2` → `ZARR_V2_ATTRIBUTES_STORE_KEY`
- `GROUP_METADATA_STORE_KEY_V2` → `ZARR_V2_GROUP_METADATA_STORE_KEY`
- `GROUP_METADATA_STORE_KEY_V3` → `ZARR_V3_GROUP_METADATA_STORE_KEY`
- `CONSOLIDATED_METADATA_STORE_KEY_V2` → `ZARR_V2_CONSOLIDATED_METADATA_STORE_KEY`
- `ARRAY_ORDER_V2` → `ZARR_V2_ARRAY_ORDER`
- `ARRAY_DIMENSION_SEPARATOR_V2` → `ZARR_V2_ARRAY_DIMENSION_SEPARATOR`
- `CONSOLIDATED_METADATA_KEY_V3` → `ZARR_V3_CONSOLIDATED_METADATA_KEY`

The old names are removed, not aliased. This supersedes the 0.4.0 convention
under which type names put the format version first while constants put it
last; there is now one rule instead of two.

The last of those is the one rename the syntactic rule does not force:
`ZARR_V3_CONSOLIDATED_METADATA_KEY` manifests no `Literal` type, so it is
outside the rule and was renamed for consistency with its siblings.

Digit runs stay glued to the token they follow, so spec vocabulary is
preserved: `Uint8DataTypeName` pairs with `UINT8_DATA_TYPE_NAME` (not
`UINT_8_...`) and `Crc32cCodecName` with `CRC32C_CODEC_NAME`. No dtype, codec,
chunk-grid, or chunk-key-encoding constant changed name.

Constants that do not manifest a `Literal` type are outside the rule and are
unchanged: the `*_METADATA_*_KEYS_V2`/`_V3` key sets, the
`CANONICAL_*_HEX_FLOAT*` bit patterns, and `UNSET`.

`tests/test_public_api.py::test_constant_names_derive_from_their_type_names`
derives every constant name from the type it manifests and asserts they match,
so the two grammars cannot diverge again.

Store keys also moved to the modules that describe the documents they name,
matching the package's layering (the `v2`/`v3` modules describe the specs; the
`model` layer is built on top of them). `ZARR_V2_ATTRIBUTES_STORE_KEY` now
lives in `zarr_metadata.v2.attributes` beside the `.zattrs` type it names,
rather than in the array model; the other five moved likewise, and
`ZarrV2AttributesStoreKey` is no longer an array-specific concept.
`zarr_metadata.model` re-exports all six, so
`from zarr_metadata.model import ZARR_V2_ARRAY_METADATA_STORE_KEY` is
unaffected.

`CONSOLIDATED_METADATA_KEY_V3` moved to `zarr_metadata.v3.consolidated` and was
renamed to `ZARR_V3_CONSOLIDATED_METADATA_KEY` for consistency. It is not a
store key: unlike v2's `.zmetadata` file, v3 consolidated metadata is embedded
as an extension field inside the group's own `zarr.json`.

All seven keys and the six store-key `Literal` aliases are now also exported
from the top-level `zarr_metadata` namespace, alongside the document types and
the rest of the spec vocabulary, so `from zarr_metadata import
ZARR_V2_ARRAY_METADATA_STORE_KEY` works. The model layer's validators, parsers,
type guards, and metadata key sets remain `zarr_metadata.model` imports.
5 changes: 4 additions & 1 deletion packages/zarr-metadata/docs/api/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@ The package is organized to mirror the structure of the Zarr specifications:
[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
The document types, models, and spec vocabulary — including the store keys —
are re-exported at the top level, so
`from zarr_metadata import ZarrV3ArrayMetadataJSON` and
`from zarr_metadata.v3.array import ZarrV3ArrayMetadataJSON` are equivalent.
The model layer's validators, parsers, type guards, and metadata key sets are
imported from [`zarr_metadata.model`](model.md) directly.

## Common types

Expand Down
34 changes: 30 additions & 4 deletions packages/zarr-metadata/src/zarr_metadata/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,38 @@
from zarr_metadata._common import JSONValue, ZarrV3NamedConfigJSON
from zarr_metadata.model import (
UNSET,
ZARR_V2_ARRAY_METADATA_STORE_KEY,
ZARR_V2_ATTRIBUTES_STORE_KEY,
ZARR_V2_CONSOLIDATED_METADATA_STORE_KEY,
ZARR_V2_GROUP_METADATA_STORE_KEY,
ZARR_V3_ARRAY_METADATA_STORE_KEY,
ZARR_V3_CONSOLIDATED_METADATA_KEY,
ZARR_V3_GROUP_METADATA_STORE_KEY,
MetadataValidationError,
ProblemKind,
ValidationProblem,
ZarrV2ArrayMetadata,
ZarrV2ArrayMetadataPartial,
ZarrV2ArrayMetadataStoreKey,
ZarrV2AttributesStoreKey,
ZarrV2ConsolidatedMetadata,
ZarrV2ConsolidatedMetadataStoreKey,
ZarrV2GroupMetadata,
ZarrV2GroupMetadataPartial,
ZarrV2GroupMetadataStoreKey,
ZarrV3ArrayMetadata,
ZarrV3ArrayMetadataPartial,
ZarrV3ArrayMetadataStoreKey,
ZarrV3ConsolidatedMetadata,
ZarrV3GroupMetadata,
ZarrV3GroupMetadataPartial,
ZarrV3GroupMetadataStoreKey,
ZarrV3MetadataField,
ZarrV3NamedConfig,
)
from zarr_metadata.v2.array import (
ARRAY_DIMENSION_SEPARATOR_V2,
ARRAY_ORDER_V2,
ZARR_V2_ARRAY_DIMENSION_SEPARATOR,
ZARR_V2_ARRAY_ORDER,
ZarrV2ArrayDimensionSeparator,
ZarrV2ArrayMetadataJSON,
ZarrV2ArrayMetadataJSONPartial,
Expand Down Expand Up @@ -217,8 +230,6 @@


__all__ = [
"ARRAY_DIMENSION_SEPARATOR_V2",
"ARRAY_ORDER_V2",
"BLOSC_CNAME",
"BLOSC_CODEC_NAME",
"BLOSC_SHUFFLE",
Expand Down Expand Up @@ -260,6 +271,15 @@
"UNSET",
"V2_CHUNK_KEY_ENCODING_NAME",
"V2_CHUNK_KEY_ENCODING_SEPARATOR",
"ZARR_V2_ARRAY_DIMENSION_SEPARATOR",
"ZARR_V2_ARRAY_METADATA_STORE_KEY",
"ZARR_V2_ARRAY_ORDER",
"ZARR_V2_ATTRIBUTES_STORE_KEY",
"ZARR_V2_CONSOLIDATED_METADATA_STORE_KEY",
"ZARR_V2_GROUP_METADATA_STORE_KEY",
"ZARR_V3_ARRAY_METADATA_STORE_KEY",
"ZARR_V3_CONSOLIDATED_METADATA_KEY",
"ZARR_V3_GROUP_METADATA_STORE_KEY",
"ZSTD_CODEC_NAME",
"BloscCName",
"BloscCodecMetadata",
Expand Down Expand Up @@ -343,29 +363,35 @@
"ZarrV2ArrayMetadataJSON",
"ZarrV2ArrayMetadataJSONPartial",
"ZarrV2ArrayMetadataPartial",
"ZarrV2ArrayMetadataStoreKey",
"ZarrV2ArrayOrder",
"ZarrV2AttributesStoreKey",
"ZarrV2CodecMetadata",
"ZarrV2ConsolidatedMetadata",
"ZarrV2ConsolidatedMetadataJSON",
"ZarrV2ConsolidatedMetadataStoreKey",
"ZarrV2DataTypeMetadata",
"ZarrV2GroupMetadata",
"ZarrV2GroupMetadataJSON",
"ZarrV2GroupMetadataJSONPartial",
"ZarrV2GroupMetadataPartial",
"ZarrV2GroupMetadataStoreKey",
"ZarrV2ZArrayJSON",
"ZarrV2ZAttrsJSON",
"ZarrV2ZGroupJSON",
"ZarrV3ArrayMetadata",
"ZarrV3ArrayMetadataJSON",
"ZarrV3ArrayMetadataJSONPartial",
"ZarrV3ArrayMetadataPartial",
"ZarrV3ArrayMetadataStoreKey",
"ZarrV3ConsolidatedMetadata",
"ZarrV3ConsolidatedMetadataJSON",
"ZarrV3ExtensionField",
"ZarrV3GroupMetadata",
"ZarrV3GroupMetadataJSON",
"ZarrV3GroupMetadataJSONPartial",
"ZarrV3GroupMetadataPartial",
"ZarrV3GroupMetadataStoreKey",
"ZarrV3MetadataField",
"ZarrV3MetadataFieldJSON",
"ZarrV3NamedConfig",
Expand Down
56 changes: 36 additions & 20 deletions packages/zarr-metadata/src/zarr_metadata/model/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,33 +12,20 @@
"""

from zarr_metadata.model._array import (
ARRAY_METADATA_STORE_KEY_V2,
ARRAY_METADATA_STORE_KEY_V3,
ATTRIBUTES_STORE_KEY_V2,
ZarrV2ArrayMetadata,
ZarrV2ArrayMetadataPartial,
ZarrV2ArrayMetadataStoreKey,
ZarrV2AttributesStoreKey,
ZarrV3ArrayMetadata,
ZarrV3ArrayMetadataPartial,
ZarrV3ArrayMetadataStoreKey,
ZarrV3MetadataField,
ZarrV3NamedConfig,
)
from zarr_metadata.model._group import (
CONSOLIDATED_METADATA_KEY_V3,
CONSOLIDATED_METADATA_STORE_KEY_V2,
GROUP_METADATA_STORE_KEY_V2,
GROUP_METADATA_STORE_KEY_V3,
ZarrV2ConsolidatedMetadata,
ZarrV2ConsolidatedMetadataStoreKey,
ZarrV2GroupMetadata,
ZarrV2GroupMetadataPartial,
ZarrV2GroupMetadataStoreKey,
ZarrV3ConsolidatedMetadata,
ZarrV3GroupMetadata,
ZarrV3GroupMetadataPartial,
ZarrV3GroupMetadataStoreKey,
)
from zarr_metadata.model._sentinel import UNSET
from zarr_metadata.model._validation import (
Expand Down Expand Up @@ -73,23 +60,52 @@
validate_metadata_field_v3,
)

# Store keys are facts about the on-disk specs, so they are defined in the
# `v2`/`v3` modules that describe those documents. They are re-exported here
# because the model layer is where consumers reach for them.
from zarr_metadata.v2.array import (
ZARR_V2_ARRAY_METADATA_STORE_KEY,
ZarrV2ArrayMetadataStoreKey,
)
from zarr_metadata.v2.attributes import (
ZARR_V2_ATTRIBUTES_STORE_KEY,
ZarrV2AttributesStoreKey,
)
from zarr_metadata.v2.consolidated import (
ZARR_V2_CONSOLIDATED_METADATA_STORE_KEY,
ZarrV2ConsolidatedMetadataStoreKey,
)
from zarr_metadata.v2.group import (
ZARR_V2_GROUP_METADATA_STORE_KEY,
ZarrV2GroupMetadataStoreKey,
)
from zarr_metadata.v3.array import (
ZARR_V3_ARRAY_METADATA_STORE_KEY,
ZarrV3ArrayMetadataStoreKey,
)
from zarr_metadata.v3.consolidated import ZARR_V3_CONSOLIDATED_METADATA_KEY
from zarr_metadata.v3.group import (
ZARR_V3_GROUP_METADATA_STORE_KEY,
ZarrV3GroupMetadataStoreKey,
)

__all__ = [
"ARRAY_METADATA_OPTIONAL_KEYS_V3",
"ARRAY_METADATA_REQUIRED_KEYS_V2",
"ARRAY_METADATA_REQUIRED_KEYS_V3",
"ARRAY_METADATA_STANDARD_KEYS_V3",
"ARRAY_METADATA_STORE_KEY_V2",
"ARRAY_METADATA_STORE_KEY_V3",
"ATTRIBUTES_STORE_KEY_V2",
"CONSOLIDATED_METADATA_KEY_V3",
"CONSOLIDATED_METADATA_STORE_KEY_V2",
"GROUP_METADATA_OPTIONAL_KEYS_V3",
"GROUP_METADATA_REQUIRED_KEYS_V2",
"GROUP_METADATA_REQUIRED_KEYS_V3",
"GROUP_METADATA_STANDARD_KEYS_V3",
"GROUP_METADATA_STORE_KEY_V2",
"GROUP_METADATA_STORE_KEY_V3",
"UNSET",
"ZARR_V2_ARRAY_METADATA_STORE_KEY",
"ZARR_V2_ATTRIBUTES_STORE_KEY",
"ZARR_V2_CONSOLIDATED_METADATA_STORE_KEY",
"ZARR_V2_GROUP_METADATA_STORE_KEY",
"ZARR_V3_ARRAY_METADATA_STORE_KEY",
"ZARR_V3_CONSOLIDATED_METADATA_KEY",
"ZARR_V3_GROUP_METADATA_STORE_KEY",
"MetadataValidationError",
"ProblemKind",
"ValidationProblem",
Expand Down
36 changes: 18 additions & 18 deletions packages/zarr-metadata/src/zarr_metadata/model/_array.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import dataclasses
from collections.abc import Mapping
from dataclasses import dataclass, field
from typing import TYPE_CHECKING, Final, Literal, TypeAlias, cast
from typing import TYPE_CHECKING, Literal, TypeAlias, cast

from typing_extensions import TypedDict, Unpack

Expand All @@ -22,27 +22,27 @@
parse_array_metadata_v3,
parse_metadata_field_v3,
)
from zarr_metadata.v2.array import ZARR_V2_ARRAY_METADATA_STORE_KEY
from zarr_metadata.v2.attributes import ZARR_V2_ATTRIBUTES_STORE_KEY
from zarr_metadata.v3.array import ZARR_V3_ARRAY_METADATA_STORE_KEY

if TYPE_CHECKING:
from zarr_metadata._common import JSONValue, ZarrV3NamedConfigJSON
from zarr_metadata.v2.array import (
ZarrV2ArrayDimensionSeparator,
ZarrV2ArrayMetadataJSON,
ZarrV2ArrayMetadataStoreKey,
ZarrV2ArrayOrder,
ZarrV2DataTypeMetadata,
)
from zarr_metadata.v2.attributes import ZarrV2AttributesStoreKey
from zarr_metadata.v2.codec import ZarrV2CodecMetadata
from zarr_metadata.v3._common import ZarrV3MetadataFieldJSON
from zarr_metadata.v3.array import ZarrV3ArrayMetadataJSON, ZarrV3ExtensionField

ZarrV3ArrayMetadataStoreKey = Literal["zarr.json"]
ARRAY_METADATA_STORE_KEY_V3: Final[ZarrV3ArrayMetadataStoreKey] = "zarr.json"

ZarrV2ArrayMetadataStoreKey = Literal[".zarray"]
ARRAY_METADATA_STORE_KEY_V2: Final[ZarrV2ArrayMetadataStoreKey] = ".zarray"

ZarrV2AttributesStoreKey = Literal[".zattrs"]
ATTRIBUTES_STORE_KEY_V2: Final[ZarrV2AttributesStoreKey] = ".zattrs"
from zarr_metadata.v3.array import (
ZarrV3ArrayMetadataJSON,
ZarrV3ArrayMetadataStoreKey,
ZarrV3ExtensionField,
)


@dataclass(frozen=True, slots=True, kw_only=True)
Expand Down Expand Up @@ -319,12 +319,12 @@ def must_understand_fields(self) -> dict[str, ZarrV3ExtensionField]:

@classmethod
def from_key_value(cls, mapping: Mapping[str, bytes]) -> ZarrV3ArrayMetadata:
return cls.from_json(load_store_json(mapping, ARRAY_METADATA_STORE_KEY_V3))
return cls.from_json(load_store_json(mapping, ZARR_V3_ARRAY_METADATA_STORE_KEY))

def to_key_value(
self, *, indent: int | str | None = None
) -> Mapping[ZarrV3ArrayMetadataStoreKey, bytes]:
return {ARRAY_METADATA_STORE_KEY_V3: dump_store_json(self.to_json(), indent=indent)}
return {ZARR_V3_ARRAY_METADATA_STORE_KEY: dump_store_json(self.to_json(), indent=indent)}


class ZarrV2ArrayMetadataPartial(TypedDict, total=False):
Expand Down Expand Up @@ -464,7 +464,7 @@ def from_json(cls, data: object) -> ZarrV2ArrayMetadata:

@classmethod
def from_key_value(cls, mapping: Mapping[str, bytes]) -> ZarrV2ArrayMetadata:
zarray_raw = cast("object", load_store_json(mapping, ARRAY_METADATA_STORE_KEY_V2))
zarray_raw = cast("object", load_store_json(mapping, ZARR_V2_ARRAY_METADATA_STORE_KEY))
if not isinstance(zarray_raw, Mapping):
return cls.from_json(zarray_raw)
zarray = cast("Mapping[str, object]", zarray_raw)
Expand All @@ -478,8 +478,8 @@ def from_key_value(cls, mapping: Mapping[str, bytes]) -> ZarrV2ArrayMetadata:
)
]
)
if ATTRIBUTES_STORE_KEY_V2 in mapping:
zattrs = cast("object", load_store_json(mapping, ATTRIBUTES_STORE_KEY_V2))
if ZARR_V2_ATTRIBUTES_STORE_KEY in mapping:
zattrs = cast("object", load_store_json(mapping, ZARR_V2_ATTRIBUTES_STORE_KEY))
return cls.from_json({**zarray, "attributes": zattrs})
return cls.from_json(zarray)

Expand All @@ -491,8 +491,8 @@ def to_key_value(
# when attributes are set (even empty) — UNSET emits no file.
zarray = {k: v for k, v in self.to_json().items() if k != "attributes"}
out: dict[ZarrV2ArrayMetadataStoreKey | ZarrV2AttributesStoreKey, bytes] = {
ARRAY_METADATA_STORE_KEY_V2: dump_store_json(zarray, indent=indent)
ZARR_V2_ARRAY_METADATA_STORE_KEY: dump_store_json(zarray, indent=indent)
}
if self.attributes is not UNSET:
out[ATTRIBUTES_STORE_KEY_V2] = dump_store_json(self.attributes, indent=indent)
out[ZARR_V2_ATTRIBUTES_STORE_KEY] = dump_store_json(self.attributes, indent=indent)
return out
Loading
Loading