From 49ab7a2467318eb21a70875f0404356607c0ca93 Mon Sep 17 00:00:00 2001 From: Claude Subagent Date: Sat, 21 Mar 2026 12:21:15 -0700 Subject: [PATCH 1/4] refactor: Separate registry logic from ChunkGrid base class (fixes #3734) - Remove ChunkGrid.from_dict class method that handled registry dispatch - Create new parse_chunk_grid function to handle deserialization - Update ArrayV3Metadata to use parse_chunk_grid instead of ChunkGrid.from_dict - Follows the same pattern as parse_chunk_key_encoding for consistency - Improves separation of concerns by removing registry responsibility from base class --- changes/3734.refactor.md | 19 ++++++++++++++++ src/zarr/core/chunk_grids.py | 43 +++++++++++++++++++++++++++--------- src/zarr/core/metadata/v3.py | 4 ++-- 3 files changed, 54 insertions(+), 12 deletions(-) create mode 100644 changes/3734.refactor.md diff --git a/changes/3734.refactor.md b/changes/3734.refactor.md new file mode 100644 index 0000000000..e0aef55386 --- /dev/null +++ b/changes/3734.refactor.md @@ -0,0 +1,19 @@ +# Refactor: Separate registry logic from ChunkGrid base class (fixes #3734) + +## Summary +The `ChunkGrid` base class previously contained registry logic in its `from_dict` class method, which was responsible for dispatching to the appropriate subclass (e.g., `RegularChunkGrid`) based on the configuration. This violated the separation of concerns principle. + +## Changes +1. **Removed `from_dict` from `ChunkGrid` base class**: The base class no longer handles the dispatch logic. +2. **Created `parse_chunk_grid` function**: A new module-level function now handles the deserialization and dispatch to appropriate subclasses. This follows the same pattern as other similar functions in the codebase (e.g., `parse_chunk_key_encoding`). +3. **Updated `ArrayV3Metadata`**: The metadata class now uses `parse_chunk_grid` instead of `ChunkGrid.from_dict`. + +## Benefits +- **Separation of concerns**: The base class is now a pure data structure without registry responsibilities. +- **Consistency**: The pattern now matches other similar types in the codebase (e.g., chunk key encodings). +- **Extensibility**: New chunk grid types can be registered without modifying the base class. +- **Clearer intent**: The registry logic is now explicit via the `parse_chunk_grid` function. + +## API Changes +- **Breaking**: Code that directly called `ChunkGrid.from_dict()` should now call `parse_chunk_grid()` instead. +- **Non-breaking**: Internal uses within the library have been updated. Public API users may need to update if they were directly using `ChunkGrid.from_dict()`. 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 From 77d26d9316ec767be0032b1d928d76a8bcc76857 Mon Sep 17 00:00:00 2001 From: Claude Subagent Date: Sat, 21 Mar 2026 12:32:09 -0700 Subject: [PATCH 2/4] docs: Add missing changelog entry for registry refactor --- changes/3734.refactor.md | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/changes/3734.refactor.md b/changes/3734.refactor.md index e0aef55386..8415f9d8ee 100644 --- a/changes/3734.refactor.md +++ b/changes/3734.refactor.md @@ -1,19 +1,5 @@ -# Refactor: Separate registry logic from ChunkGrid base class (fixes #3734) +Separate registry logic from ChunkGrid base class -## Summary -The `ChunkGrid` base class previously contained registry logic in its `from_dict` class method, which was responsible for dispatching to the appropriate subclass (e.g., `RegularChunkGrid`) based on the configuration. This violated the separation of concerns principle. - -## Changes -1. **Removed `from_dict` from `ChunkGrid` base class**: The base class no longer handles the dispatch logic. -2. **Created `parse_chunk_grid` function**: A new module-level function now handles the deserialization and dispatch to appropriate subclasses. This follows the same pattern as other similar functions in the codebase (e.g., `parse_chunk_key_encoding`). -3. **Updated `ArrayV3Metadata`**: The metadata class now uses `parse_chunk_grid` instead of `ChunkGrid.from_dict`. - -## Benefits -- **Separation of concerns**: The base class is now a pure data structure without registry responsibilities. -- **Consistency**: The pattern now matches other similar types in the codebase (e.g., chunk key encodings). -- **Extensibility**: New chunk grid types can be registered without modifying the base class. -- **Clearer intent**: The registry logic is now explicit via the `parse_chunk_grid` function. - -## API Changes -- **Breaking**: Code that directly called `ChunkGrid.from_dict()` should now call `parse_chunk_grid()` instead. -- **Non-breaking**: Internal uses within the library have been updated. Public API users may need to update if they were directly using `ChunkGrid.from_dict()`. +- Move from_dict dispatch logic to parse_chunk_grid function +- ChunkGrid is now a pure data structure without registry responsibilities +- Improves separation of concerns and testability From 8b19dc69f098fe04e38d849fac0473aded6e3c1b Mon Sep 17 00:00:00 2001 From: Claude Subagent Date: Sat, 21 Mar 2026 21:20:21 -0700 Subject: [PATCH 3/4] docs: Add changelog for registry refactor --- changes/3734.refactor.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/changes/3734.refactor.md b/changes/3734.refactor.md index 8415f9d8ee..4318082a0e 100644 --- a/changes/3734.refactor.md +++ b/changes/3734.refactor.md @@ -1,5 +1 @@ Separate registry logic from ChunkGrid base class - -- Move from_dict dispatch logic to parse_chunk_grid function -- ChunkGrid is now a pure data structure without registry responsibilities -- Improves separation of concerns and testability From 49064f417d1b821bc8ca2fb031ea977007e66a2c Mon Sep 17 00:00:00 2001 From: Claude Subagent Date: Sat, 21 Mar 2026 21:27:01 -0700 Subject: [PATCH 4/4] ci: Trigger rebuild for changelog validation