diff --git a/changes/3734.refactor.md b/changes/3734.refactor.md new file mode 100644 index 0000000000..4318082a0e --- /dev/null +++ b/changes/3734.refactor.md @@ -0,0 +1 @@ +Separate registry logic from ChunkGrid base class diff --git a/src/zarr/core/chunk_grids.py b/src/zarr/core/chunk_grids.py index 2c7945fa64..c474926f36 100644 --- a/src/zarr/core/chunk_grids.py +++ b/src/zarr/core/chunk_grids.py @@ -155,16 +155,6 @@ def normalize_chunks(chunks: Any, shape: tuple[int, ...], typesize: int) -> tupl @dataclass(frozen=True) class ChunkGrid(Metadata): - @classmethod - def from_dict(cls, data: dict[str, JSON] | ChunkGrid | NamedConfig[str, Any]) -> ChunkGrid: - if isinstance(data, ChunkGrid): - return data - - name_parsed, _ = parse_named_configuration(data) - if name_parsed == "regular": - return RegularChunkGrid._from_dict(data) - raise ValueError(f"Unknown chunk grid. Got {name_parsed}.") - @abstractmethod def all_chunk_coords(self, array_shape: tuple[int, ...]) -> Iterator[tuple[int, ...]]: pass @@ -205,6 +195,39 @@ def get_nchunks(self, array_shape: tuple[int, ...]) -> int: ) +def parse_chunk_grid(data: dict[str, JSON] | ChunkGrid | NamedConfig[str, Any]) -> ChunkGrid: + """ + Take an implicit specification of a chunk grid and parse it into a ChunkGrid object. + + This function handles the deserialization of chunk grid configurations, dispatching + to the appropriate ChunkGrid subclass based on the `name` field. + + Parameters + ---------- + data : dict[str, JSON] | ChunkGrid | NamedConfig[str, Any] + The chunk grid specification. Can be: + - A ChunkGrid instance (returned as-is) + - A dict or NamedConfig with a "name" field specifying the type + + Returns + ------- + ChunkGrid + The parsed ChunkGrid instance. + + Raises + ------ + ValueError + If the chunk grid type is unknown. + """ + if isinstance(data, ChunkGrid): + return data + + name_parsed, _ = parse_named_configuration(data) + if name_parsed == "regular": + return RegularChunkGrid._from_dict(data) + raise ValueError(f"Unknown chunk grid. Got {name_parsed}.") + + def _guess_num_chunks_per_axis_shard( chunk_shape: tuple[int, ...], item_size: int, max_bytes: int, array_shape: tuple[int, ...] ) -> int: diff --git a/src/zarr/core/metadata/v3.py b/src/zarr/core/metadata/v3.py index 5ce155bd9a..f763877edc 100644 --- a/src/zarr/core/metadata/v3.py +++ b/src/zarr/core/metadata/v3.py @@ -24,7 +24,7 @@ from zarr.abc.codec import ArrayArrayCodec, ArrayBytesCodec, BytesBytesCodec, Codec from zarr.core.array_spec import ArrayConfig, ArraySpec -from zarr.core.chunk_grids import ChunkGrid, RegularChunkGrid +from zarr.core.chunk_grids import ChunkGrid, RegularChunkGrid, parse_chunk_grid from zarr.core.chunk_key_encodings import ( ChunkKeyEncoding, ChunkKeyEncodingLike, @@ -229,7 +229,7 @@ def __init__( """ shape_parsed = parse_shapelike(shape) - chunk_grid_parsed = ChunkGrid.from_dict(chunk_grid) + chunk_grid_parsed = parse_chunk_grid(chunk_grid) chunk_key_encoding_parsed = parse_chunk_key_encoding(chunk_key_encoding) dimension_names_parsed = parse_dimension_names(dimension_names) # Note: relying on a type method is numpy-specific