diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 75ef0face8..474d109c80 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -37,6 +37,7 @@ repos: - obstore>=0.5.1 # Tests - pytest + - hypothesis - repo: https://github.com/scientific-python/cookie rev: 2025.01.22 hooks: diff --git a/changes/3045.bugfix.rst b/changes/3045.bugfix.rst new file mode 100644 index 0000000000..a3886717a7 --- /dev/null +++ b/changes/3045.bugfix.rst @@ -0,0 +1 @@ +Fixed the typing of ``dimension_names`` arguments throughout so that it now accepts iterables that contain `None` alongside `str`. diff --git a/pyproject.toml b/pyproject.toml index 9244a9ec0b..1c534f7927 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -356,6 +356,7 @@ enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"] [[tool.mypy.overrides]] module = [ "tests.package_with_entrypoint.*", + "zarr.testing.stateful", "tests.test_codecs.test_transpose", "tests.test_config" ] @@ -365,7 +366,6 @@ strict = false # and fix the errors [[tool.mypy.overrides]] module = [ - "zarr.testing.stateful", # lots of hypothesis decorator errors "tests.test_codecs.test_codecs", "tests.test_metadata.*", "tests.test_store.*", diff --git a/src/zarr/api/asynchronous.py b/src/zarr/api/asynchronous.py index 9b8b43a517..ac143f6dea 100644 --- a/src/zarr/api/asynchronous.py +++ b/src/zarr/api/asynchronous.py @@ -16,6 +16,7 @@ JSON, AccessModeLiteral, ChunkCoords, + DimensionNames, MemoryOrder, ZarrFormat, _default_zarr_format, @@ -865,7 +866,7 @@ async def create( | None ) = None, codecs: Iterable[Codec | dict[str, JSON]] | None = None, - dimension_names: Iterable[str] | None = None, + dimension_names: DimensionNames = None, storage_options: dict[str, Any] | None = None, config: ArrayConfigLike | None = None, **kwargs: Any, diff --git a/src/zarr/api/synchronous.py b/src/zarr/api/synchronous.py index 4c577936cd..5662f5c247 100644 --- a/src/zarr/api/synchronous.py +++ b/src/zarr/api/synchronous.py @@ -33,6 +33,7 @@ JSON, AccessModeLiteral, ChunkCoords, + DimensionNames, MemoryOrder, ShapeLike, ZarrFormat, @@ -626,7 +627,7 @@ def create( | None ) = None, codecs: Iterable[Codec | dict[str, JSON]] | None = None, - dimension_names: Iterable[str] | None = None, + dimension_names: DimensionNames = None, storage_options: dict[str, Any] | None = None, config: ArrayConfigLike | None = None, **kwargs: Any, @@ -761,7 +762,7 @@ def create_array( zarr_format: ZarrFormat | None = 3, attributes: dict[str, JSON] | None = None, chunk_key_encoding: ChunkKeyEncodingLike | None = None, - dimension_names: Iterable[str] | None = None, + dimension_names: DimensionNames = None, storage_options: dict[str, Any] | None = None, overwrite: bool = False, config: ArrayConfigLike | None = None, @@ -926,7 +927,7 @@ def from_array( zarr_format: ZarrFormat | None = None, attributes: dict[str, JSON] | None = None, chunk_key_encoding: ChunkKeyEncodingLike | None = None, - dimension_names: Iterable[str] | None = None, + dimension_names: DimensionNames = None, storage_options: dict[str, Any] | None = None, overwrite: bool = False, config: ArrayConfigLike | None = None, diff --git a/src/zarr/core/array.py b/src/zarr/core/array.py index b0e8b03cd7..c6217a3d93 100644 --- a/src/zarr/core/array.py +++ b/src/zarr/core/array.py @@ -54,6 +54,7 @@ ZARRAY_JSON, ZATTRS_JSON, ChunkCoords, + DimensionNames, MemoryOrder, ShapeLike, ZarrFormat, @@ -330,7 +331,7 @@ async def create( | None ) = None, codecs: Iterable[Codec | dict[str, JSON]] | None = None, - dimension_names: Iterable[str] | None = None, + dimension_names: DimensionNames = None, # runtime overwrite: bool = False, data: npt.ArrayLike | None = None, @@ -358,7 +359,7 @@ async def create( | None ) = None, codecs: Iterable[Codec | dict[str, JSON]] | None = None, - dimension_names: Iterable[str] | None = None, + dimension_names: DimensionNames = None, # runtime overwrite: bool = False, data: npt.ArrayLike | None = None, @@ -386,7 +387,7 @@ async def create( | None ) = None, codecs: Iterable[Codec | dict[str, JSON]] | None = None, - dimension_names: Iterable[str] | None = None, + dimension_names: DimensionNames = None, # v2 only chunks: ShapeLike | None = None, dimension_separator: Literal[".", "/"] | None = None, @@ -421,7 +422,7 @@ async def create( | None ) = None, codecs: Iterable[Codec | dict[str, JSON]] | None = None, - dimension_names: Iterable[str] | None = None, + dimension_names: DimensionNames = None, # v2 only chunks: ShapeLike | None = None, dimension_separator: Literal[".", "/"] | None = None, @@ -473,7 +474,7 @@ async def create( These defaults can be changed by modifying the value of ``array.v3_default_filters``, ``array.v3_default_serializer`` and ``array.v3_default_compressors`` in :mod:`zarr.core.config`. - dimension_names : Iterable[str], optional + dimension_names : Iterable[str | None], optional The names of the dimensions (default is None). Zarr format 3 only. Zarr format 2 arrays should not use this parameter. chunks : ShapeLike, optional @@ -562,7 +563,7 @@ async def _create( | None ) = None, codecs: Iterable[Codec | dict[str, JSON]] | None = None, - dimension_names: Iterable[str] | None = None, + dimension_names: DimensionNames = None, # v2 only chunks: ShapeLike | None = None, dimension_separator: Literal[".", "/"] | None = None, @@ -672,7 +673,7 @@ def _create_metadata_v3( fill_value: Any | None = None, chunk_key_encoding: ChunkKeyEncodingLike | None = None, codecs: Iterable[Codec | dict[str, JSON]] | None = None, - dimension_names: Iterable[str] | None = None, + dimension_names: DimensionNames = None, attributes: dict[str, JSON] | None = None, ) -> ArrayV3Metadata: """ @@ -723,7 +724,7 @@ async def _create_v3( | None ) = None, codecs: Iterable[Codec | dict[str, JSON]] | None = None, - dimension_names: Iterable[str] | None = None, + dimension_names: DimensionNames = None, attributes: dict[str, JSON] | None = None, overwrite: bool = False, ) -> AsyncArray[ArrayV3Metadata]: @@ -1743,7 +1744,7 @@ def create( | None ) = None, codecs: Iterable[Codec | dict[str, JSON]] | None = None, - dimension_names: Iterable[str] | None = None, + dimension_names: DimensionNames = None, # v2 only chunks: ChunkCoords | None = None, dimension_separator: Literal[".", "/"] | None = None, @@ -1788,7 +1789,7 @@ def create( These defaults can be changed by modifying the value of ``array.v3_default_filters``, ``array.v3_default_serializer`` and ``array.v3_default_compressors`` in :mod:`zarr.core.config`. - dimension_names : Iterable[str], optional + dimension_names : Iterable[str | None], optional The names of the dimensions (default is None). Zarr format 3 only. Zarr format 2 arrays should not use this parameter. chunks : ChunkCoords, optional @@ -1872,7 +1873,7 @@ def _create( | None ) = None, codecs: Iterable[Codec | dict[str, JSON]] | None = None, - dimension_names: Iterable[str] | None = None, + dimension_names: DimensionNames = None, # v2 only chunks: ChunkCoords | None = None, dimension_separator: Literal[".", "/"] | None = None, @@ -3821,7 +3822,7 @@ async def from_array( zarr_format: ZarrFormat | None = None, attributes: dict[str, JSON] | None = None, chunk_key_encoding: ChunkKeyEncodingLike | None = None, - dimension_names: Iterable[str] | None = None, + dimension_names: DimensionNames = None, storage_options: dict[str, Any] | None = None, overwrite: bool = False, config: ArrayConfig | ArrayConfigLike | None = None, @@ -3929,7 +3930,7 @@ async def from_array( For Zarr format 2, the default is ``{"name": "v2", "separator": "."}}``. If not specified and the data array has the same zarr format as the target array, the chunk key encoding of the data array is used. - dimension_names : Iterable[str], optional + dimension_names : Iterable[str | None], optional The names of the dimensions (default is None). Zarr format 3 only. Zarr format 2 arrays should not use this parameter. If not specified, defaults to the dimension names of the data array. @@ -4083,7 +4084,7 @@ async def init_array( zarr_format: ZarrFormat | None = 3, attributes: dict[str, JSON] | None = None, chunk_key_encoding: ChunkKeyEncodingLike | None = None, - dimension_names: Iterable[str] | None = None, + dimension_names: DimensionNames = None, overwrite: bool = False, config: ArrayConfigLike | None, ) -> AsyncArray[ArrayV3Metadata] | AsyncArray[ArrayV2Metadata]: @@ -4298,7 +4299,7 @@ async def create_array( zarr_format: ZarrFormat | None = 3, attributes: dict[str, JSON] | None = None, chunk_key_encoding: ChunkKeyEncodingLike | None = None, - dimension_names: Iterable[str] | None = None, + dimension_names: DimensionNames = None, storage_options: dict[str, Any] | None = None, overwrite: bool = False, config: ArrayConfigLike | None = None, @@ -4477,7 +4478,7 @@ def _parse_keep_array_attr( order: MemoryOrder | None, zarr_format: ZarrFormat | None, chunk_key_encoding: ChunkKeyEncodingLike | None, - dimension_names: Iterable[str] | None, + dimension_names: DimensionNames, ) -> tuple[ ChunkCoords | Literal["auto"], ShardsLike | None, @@ -4488,7 +4489,7 @@ def _parse_keep_array_attr( MemoryOrder | None, ZarrFormat, ChunkKeyEncodingLike | None, - Iterable[str] | None, + DimensionNames, ]: if isinstance(data, Array): if chunks == "keep": diff --git a/src/zarr/core/common.py b/src/zarr/core/common.py index 3308ca3247..a670834206 100644 --- a/src/zarr/core/common.py +++ b/src/zarr/core/common.py @@ -40,6 +40,7 @@ JSON = str | int | float | Mapping[str, "JSON"] | Sequence["JSON"] | None MemoryOrder = Literal["C", "F"] AccessModeLiteral = Literal["r", "r+", "a", "w", "w-"] +DimensionNames = Iterable[str | None] | None def product(tup: ChunkCoords) -> int: diff --git a/src/zarr/core/group.py b/src/zarr/core/group.py index 3f4f15b9e9..5c470e29ca 100644 --- a/src/zarr/core/group.py +++ b/src/zarr/core/group.py @@ -43,6 +43,7 @@ ZGROUP_JSON, ZMETADATA_V2_JSON, ChunkCoords, + DimensionNames, NodeType, ShapeLike, ZarrFormat, @@ -1006,7 +1007,7 @@ async def create_array( order: MemoryOrder | None = None, attributes: dict[str, JSON] | None = None, chunk_key_encoding: ChunkKeyEncodingLike | None = None, - dimension_names: Iterable[str] | None = None, + dimension_names: DimensionNames = None, storage_options: dict[str, Any] | None = None, overwrite: bool = False, config: ArrayConfig | ArrayConfigLike | None = None, @@ -2381,7 +2382,7 @@ def create_array( order: MemoryOrder | None = "C", attributes: dict[str, JSON] | None = None, chunk_key_encoding: ChunkKeyEncodingLike | None = None, - dimension_names: Iterable[str] | None = None, + dimension_names: DimensionNames = None, storage_options: dict[str, Any] | None = None, overwrite: bool = False, config: ArrayConfig | ArrayConfigLike | None = None, @@ -2775,7 +2776,7 @@ def array( order: MemoryOrder | None = "C", attributes: dict[str, JSON] | None = None, chunk_key_encoding: ChunkKeyEncodingLike | None = None, - dimension_names: Iterable[str] | None = None, + dimension_names: DimensionNames = None, storage_options: dict[str, Any] | None = None, overwrite: bool = False, config: ArrayConfig | ArrayConfigLike | None = None, diff --git a/src/zarr/core/metadata/v3.py b/src/zarr/core/metadata/v3.py index 9154762648..63f6515e44 100644 --- a/src/zarr/core/metadata/v3.py +++ b/src/zarr/core/metadata/v3.py @@ -32,6 +32,7 @@ JSON, ZARR_JSON, ChunkCoords, + DimensionNames, parse_named_configuration, parse_shapelike, ) @@ -242,7 +243,7 @@ class ArrayV3Metadata(Metadata): fill_value: Any codecs: tuple[Codec, ...] attributes: dict[str, Any] = field(default_factory=dict) - dimension_names: tuple[str, ...] | None = None + dimension_names: tuple[str | None, ...] | None = None zarr_format: Literal[3] = field(default=3, init=False) node_type: Literal["array"] = field(default="array", init=False) storage_transformers: tuple[dict[str, JSON], ...] @@ -257,7 +258,7 @@ def __init__( fill_value: Any, codecs: Iterable[Codec | dict[str, JSON]], attributes: dict[str, JSON] | None, - dimension_names: Iterable[str] | None, + dimension_names: DimensionNames, storage_transformers: Iterable[dict[str, JSON]] | None = None, ) -> None: """ diff --git a/src/zarr/testing/stateful.py b/src/zarr/testing/stateful.py index ede83201ae..acc5f63f19 100644 --- a/src/zarr/testing/stateful.py +++ b/src/zarr/testing/stateful.py @@ -326,8 +326,8 @@ def init_store(self) -> None: self.store.clear() @rule(key=zarr_keys(), data=st.binary(min_size=0, max_size=MAX_BINARY_SIZE)) - def set(self, key: str, data: DataObject) -> None: - note(f"(set) Setting {key!r} with {data}") + def set(self, key: str, data: bytes) -> None: + note(f"(set) Setting {key!r} with {data!r}") assert not self.store.read_only data_buf = cpu.Buffer.from_bytes(data) self.store.set(key, data_buf) diff --git a/src/zarr/testing/strategies.py b/src/zarr/testing/strategies.py index 663d46034d..3b10592ec0 100644 --- a/src/zarr/testing/strategies.py +++ b/src/zarr/testing/strategies.py @@ -1,10 +1,12 @@ import math import sys +from collections.abc import Callable, Mapping from typing import Any, Literal import hypothesis.extra.numpy as npst import hypothesis.strategies as st import numpy as np +import numpy.typing as npt from hypothesis import event from hypothesis.strategies import SearchStrategy @@ -14,7 +16,7 @@ from zarr.core.array import Array from zarr.core.chunk_grids import RegularChunkGrid from zarr.core.chunk_key_encodings import DefaultChunkKeyEncoding -from zarr.core.common import ZarrFormat +from zarr.core.common import JSON, ZarrFormat from zarr.core.metadata import ArrayV2Metadata, ArrayV3Metadata from zarr.core.sync import sync from zarr.storage import MemoryStore, StoreLike @@ -30,17 +32,17 @@ ) -@st.composite # type: ignore[misc] -def keys(draw: st.DrawFn, *, max_num_nodes: int | None = None) -> Any: +@st.composite +def keys(draw: st.DrawFn, *, max_num_nodes: int | None = None) -> str: return draw(st.lists(node_names, min_size=1, max_size=max_num_nodes).map("/".join)) -@st.composite # type: ignore[misc] -def paths(draw: st.DrawFn, *, max_num_nodes: int | None = None) -> Any: +@st.composite +def paths(draw: st.DrawFn, *, max_num_nodes: int | None = None) -> str: return draw(st.just("/") | keys(max_num_nodes=max_num_nodes)) -def v3_dtypes() -> st.SearchStrategy[np.dtype]: +def v3_dtypes() -> st.SearchStrategy[np.dtype[Any]]: return ( npst.boolean_dtypes() | npst.integer_dtypes(endianness="=") @@ -54,7 +56,7 @@ def v3_dtypes() -> st.SearchStrategy[np.dtype]: ) -def v2_dtypes() -> st.SearchStrategy[np.dtype]: +def v2_dtypes() -> st.SearchStrategy[np.dtype[Any]]: return ( npst.boolean_dtypes() | npst.integer_dtypes(endianness="=") @@ -107,7 +109,9 @@ def clear_store(x: Store) -> Store: .filter(lambda name: name.lower() != "zarr.json") ) array_names = node_names -attrs = st.none() | st.dictionaries(_attr_keys, _attr_values) +attrs: st.SearchStrategy[Mapping[str, JSON] | None] = st.none() | st.dictionaries( + _attr_keys, _attr_values +) # st.builds will only call a new store constructor for different keyword arguments # i.e. stores.examples() will always return the same object per Store class. # So we map a clear to reset the store. @@ -118,19 +122,19 @@ def clear_store(x: Store) -> Store: array_shapes = npst.array_shapes(max_dims=4, min_side=3) | npst.array_shapes(max_dims=4, min_side=0) -@st.composite # type: ignore[misc] +@st.composite def dimension_names(draw: st.DrawFn, *, ndim: int | None = None) -> list[None | str] | None: simple_text = st.text(zarr_key_chars, min_size=0) - return draw(st.none() | st.lists(st.none() | simple_text, min_size=ndim, max_size=ndim)) # type: ignore[no-any-return] + return draw(st.none() | st.lists(st.none() | simple_text, min_size=ndim, max_size=ndim)) # type: ignore[arg-type] -@st.composite # type: ignore[misc] +@st.composite def array_metadata( draw: st.DrawFn, *, - array_shapes: st.SearchStrategy[tuple[int, ...]] = npst.array_shapes, + array_shapes: Callable[..., st.SearchStrategy[tuple[int, ...]]] = npst.array_shapes, zarr_formats: st.SearchStrategy[Literal[2, 3]] = zarr_formats, - attributes: st.SearchStrategy[dict[str, Any]] = attrs, + attributes: SearchStrategy[Mapping[str, JSON] | None] = attrs, ) -> ArrayV2Metadata | ArrayV3Metadata: zarr_format = draw(zarr_formats) # separator = draw(st.sampled_from(['/', '\\'])) @@ -146,7 +150,7 @@ def array_metadata( dtype=dtype, fill_value=fill_value, order=draw(st.sampled_from(["C", "F"])), - attributes=draw(attributes), + attributes=draw(attributes), # type: ignore[arg-type] dimension_separator=draw(st.sampled_from([".", "/"])), filters=None, compressor=None, @@ -157,7 +161,7 @@ def array_metadata( data_type=dtype, chunk_grid=RegularChunkGrid(chunk_shape=chunk_shape), fill_value=fill_value, - attributes=draw(attributes), + attributes=draw(attributes), # type: ignore[arg-type] dimension_names=draw(dimension_names(ndim=ndim)), chunk_key_encoding=DefaultChunkKeyEncoding(separator="/"), # FIXME codecs=[BytesCodec()], @@ -165,14 +169,14 @@ def array_metadata( ) -@st.composite # type: ignore[misc] +@st.composite def numpy_arrays( draw: st.DrawFn, *, shapes: st.SearchStrategy[tuple[int, ...]] = array_shapes, dtype: np.dtype[Any] | None = None, - zarr_formats: st.SearchStrategy[ZarrFormat] | None = zarr_formats, -) -> Any: + zarr_formats: st.SearchStrategy[ZarrFormat] = zarr_formats, +) -> npt.NDArray[Any]: """ Generate numpy arrays that can be saved in the provided Zarr format. """ @@ -186,7 +190,7 @@ def numpy_arrays( return draw(npst.arrays(dtype=dtype, shape=shapes)) -@st.composite # type: ignore[misc] +@st.composite def chunk_shapes(draw: st.DrawFn, *, shape: tuple[int, ...]) -> tuple[int, ...]: # We want this strategy to shrink towards arrays with smaller number of chunks # 1. st.integers() shrinks towards smaller values. So we use that to generate number of chunks @@ -208,7 +212,7 @@ def chunk_shapes(draw: st.DrawFn, *, shape: tuple[int, ...]) -> tuple[int, ...]: return chunks -@st.composite # type: ignore[misc] +@st.composite def shard_shapes( draw: st.DrawFn, *, shape: tuple[int, ...], chunk_shape: tuple[int, ...] ) -> tuple[int, ...]: @@ -220,9 +224,11 @@ def shard_shapes( return tuple(m * c for m, c in zip(multiples, chunk_shape, strict=True)) -@st.composite # type: ignore[misc] +@st.composite def np_array_and_chunks( - draw: st.DrawFn, *, arrays: st.SearchStrategy[np.ndarray] = numpy_arrays + draw: st.DrawFn, + *, + arrays: st.SearchStrategy[npt.NDArray[Any]] = numpy_arrays(), # noqa: B008 ) -> tuple[np.ndarray, tuple[int, ...]]: # type: ignore[type-arg] """A hypothesis strategy to generate small sized random arrays. @@ -232,14 +238,14 @@ def np_array_and_chunks( return (array, draw(chunk_shapes(shape=array.shape))) -@st.composite # type: ignore[misc] +@st.composite def arrays( draw: st.DrawFn, *, shapes: st.SearchStrategy[tuple[int, ...]] = array_shapes, compressors: st.SearchStrategy = compressors, stores: st.SearchStrategy[StoreLike] = stores, - paths: st.SearchStrategy[str | None] = paths(), # noqa: B008 + paths: st.SearchStrategy[str] = paths(), # noqa: B008 array_names: st.SearchStrategy = array_names, arrays: st.SearchStrategy | None = None, attrs: st.SearchStrategy = attrs, @@ -296,7 +302,7 @@ def arrays( return a -@st.composite # type: ignore[misc] +@st.composite def simple_arrays( draw: st.DrawFn, *, @@ -317,7 +323,7 @@ def is_negative_slice(idx: Any) -> bool: return isinstance(idx, slice) and idx.step is not None and idx.step < 0 -@st.composite # type: ignore[misc] +@st.composite def end_slices(draw: st.DrawFn, *, shape: tuple[int]) -> Any: """ A strategy that slices ranges that include the last chunk. @@ -332,14 +338,28 @@ def end_slices(draw: st.DrawFn, *, shape: tuple[int]) -> Any: return tuple(slicers) -@st.composite # type: ignore[misc] -def basic_indices(draw: st.DrawFn, *, shape: tuple[int], **kwargs: Any) -> Any: +@st.composite +def basic_indices( + draw: st.DrawFn, + *, + shape: tuple[int], + min_dims: int = 0, + max_dims: int | None = None, + allow_newaxis: bool = False, + allow_ellipsis: bool = True, +) -> Any: """Basic indices without unsupported negative slices.""" - strategy = npst.basic_indices(shape=shape, **kwargs).filter( + strategy = npst.basic_indices( + shape=shape, + min_dims=min_dims, + max_dims=max_dims, + allow_newaxis=allow_newaxis, + allow_ellipsis=allow_ellipsis, + ).filter( lambda idxr: ( not ( is_negative_slice(idxr) - or (isinstance(idxr, tuple) and any(is_negative_slice(idx) for idx in idxr)) + or (isinstance(idxr, tuple) and any(is_negative_slice(idx) for idx in idxr)) # type: ignore[redundant-expr] ) ) ) @@ -348,7 +368,7 @@ def basic_indices(draw: st.DrawFn, *, shape: tuple[int], **kwargs: Any) -> Any: return draw(strategy) -@st.composite # type: ignore[misc] +@st.composite def orthogonal_indices( draw: st.DrawFn, *, shape: tuple[int] ) -> tuple[tuple[np.ndarray[Any, Any], ...], tuple[np.ndarray[Any, Any], ...]]: @@ -386,8 +406,8 @@ def orthogonal_indices( def key_ranges( - keys: SearchStrategy = node_names, max_size: int = sys.maxsize -) -> SearchStrategy[list[int]]: + keys: SearchStrategy[str] = node_names, max_size: int = sys.maxsize +) -> SearchStrategy[list[tuple[str, RangeByteRequest]]]: """ Function to generate key_ranges strategy for get_partial_values() returns list strategy w/ form:: diff --git a/tests/conftest.py b/tests/conftest.py index 74a140c5c7..948d3cd055 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -18,7 +18,7 @@ _parse_chunk_key_encoding, ) from zarr.core.chunk_grids import RegularChunkGrid, _auto_partition -from zarr.core.common import JSON, parse_dtype, parse_shapelike +from zarr.core.common import JSON, DimensionNames, parse_dtype, parse_shapelike from zarr.core.config import config as zarr_config from zarr.core.metadata.v2 import ArrayV2Metadata from zarr.core.metadata.v3 import ArrayV3Metadata @@ -26,7 +26,7 @@ from zarr.storage import FsspecStore, LocalStore, MemoryStore, StorePath, ZipStore if TYPE_CHECKING: - from collections.abc import Generator, Iterable + from collections.abc import Generator from typing import Any, Literal from _pytest.compat import LEGACY_PATH @@ -255,7 +255,7 @@ def create_array_metadata( zarr_format: ZarrFormat, attributes: dict[str, JSON] | None = None, chunk_key_encoding: ChunkKeyEncoding | ChunkKeyEncodingLike | None = None, - dimension_names: Iterable[str] | None = None, + dimension_names: DimensionNames = None, ) -> ArrayV2Metadata | ArrayV3Metadata: """ Create array metadata @@ -388,7 +388,7 @@ def meta_from_array( zarr_format: ZarrFormat = 3, attributes: dict[str, JSON] | None = None, chunk_key_encoding: ChunkKeyEncoding | ChunkKeyEncodingLike | None = None, - dimension_names: Iterable[str] | None = None, + dimension_names: DimensionNames = None, ) -> ArrayV3Metadata | ArrayV2Metadata: """ Create array metadata from an array