Skip to content

Commit 662d664

Browse files
committed
Parametrize Array with v2/v3 metadata
1 parent 24385ab commit 662d664

File tree

17 files changed

+139
-106
lines changed

17 files changed

+139
-106
lines changed

src/zarr/api/asynchronous.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import asyncio
44
import dataclasses
55
import warnings
6-
from typing import TYPE_CHECKING, Any, Literal, NotRequired, TypedDict, cast
6+
from typing import TYPE_CHECKING, Any, Literal, NotRequired, TypeAlias, TypedDict, cast
77

88
import numpy as np
99
import numpy.typing as npt
@@ -58,9 +58,12 @@
5858
from zarr.core.chunk_key_encodings import ChunkKeyEncoding
5959
from zarr.core.metadata.v2 import CompressorLikev2
6060
from zarr.storage import StoreLike
61+
from zarr.types import AnyArray
6162

6263
# TODO: this type could use some more thought
63-
ArrayLike = AsyncArray[ArrayV2Metadata] | AsyncArray[ArrayV3Metadata] | Array | npt.NDArray[Any]
64+
ArrayLike: TypeAlias = (
65+
AsyncArray[ArrayV2Metadata] | AsyncArray[ArrayV3Metadata] | AnyArray | npt.NDArray[Any]
66+
)
6467
PathLike = str
6568

6669
__all__ = [
@@ -590,7 +593,7 @@ async def tree(grp: AsyncGroup, expand: bool | None = None, level: int | None =
590593

591594

592595
async def array(
593-
data: npt.ArrayLike | Array, **kwargs: Any
596+
data: npt.ArrayLike | AnyArray, **kwargs: Any
594597
) -> AsyncArray[ArrayV2Metadata] | AsyncArray[ArrayV3Metadata]:
595598
"""Create an array filled with `data`.
596599

src/zarr/api/synchronous.py

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
)
4141
from zarr.core.dtype import ZDTypeLike
4242
from zarr.storage import StoreLike
43+
from zarr.types import AnyArray
4344

4445
__all__ = [
4546
"array",
@@ -177,7 +178,7 @@ def open(
177178
path: str | None = None,
178179
storage_options: dict[str, Any] | None = None,
179180
**kwargs: Any, # TODO: type kwargs as valid args to async_api.open
180-
) -> Array | Group:
181+
) -> AnyArray | Group:
181182
"""Open a group or array using file-mode-like semantics.
182183
183184
Parameters
@@ -375,7 +376,7 @@ def tree(grp: Group, expand: bool | None = None, level: int | None = None) -> An
375376

376377

377378
# TODO: add type annotations for kwargs
378-
def array(data: npt.ArrayLike | Array, **kwargs: Any) -> Array:
379+
def array(data: npt.ArrayLike | AnyArray, **kwargs: Any) -> AnyArray:
379380
"""Create an array filled with `data`.
380381
381382
Parameters
@@ -642,7 +643,7 @@ def create(
642643
storage_options: dict[str, Any] | None = None,
643644
config: ArrayConfigLike | None = None,
644645
**kwargs: Any,
645-
) -> Array:
646+
) -> AnyArray:
646647
"""Create an array.
647648
648649
Parameters
@@ -824,7 +825,7 @@ def create_array(
824825
overwrite: bool = False,
825826
config: ArrayConfigLike | None = None,
826827
write_data: bool = True,
827-
) -> Array:
828+
) -> AnyArray:
828829
"""Create an array.
829830
830831
This function wraps [zarr.core.array.create_array][].
@@ -973,7 +974,7 @@ def create_array(
973974
def from_array(
974975
store: StoreLike,
975976
*,
976-
data: Array | npt.ArrayLike,
977+
data: AnyArray | npt.ArrayLike,
977978
write_data: bool = True,
978979
name: str | None = None,
979980
chunks: Literal["auto", "keep"] | tuple[int, ...] = "keep",
@@ -990,7 +991,7 @@ def from_array(
990991
storage_options: dict[str, Any] | None = None,
991992
overwrite: bool = False,
992993
config: ArrayConfigLike | None = None,
993-
) -> Array:
994+
) -> AnyArray:
994995
"""Create an array from an existing array or array-like.
995996
996997
Parameters
@@ -1187,7 +1188,7 @@ def from_array(
11871188

11881189

11891190
# TODO: add type annotations for kwargs
1190-
def empty(shape: tuple[int, ...], **kwargs: Any) -> Array:
1191+
def empty(shape: tuple[int, ...], **kwargs: Any) -> AnyArray:
11911192
"""Create an empty array with the specified shape. The contents will be filled with the
11921193
array's fill value or zeros if no fill value is provided.
11931194
@@ -1214,7 +1215,7 @@ def empty(shape: tuple[int, ...], **kwargs: Any) -> Array:
12141215

12151216
# TODO: move ArrayLike to common module
12161217
# TODO: add type annotations for kwargs
1217-
def empty_like(a: ArrayLike, **kwargs: Any) -> Array:
1218+
def empty_like(a: ArrayLike, **kwargs: Any) -> AnyArray:
12181219
"""Create an empty array like another array. The contents will be filled with the
12191220
array's fill value or zeros if no fill value is provided.
12201221
@@ -1240,7 +1241,7 @@ def empty_like(a: ArrayLike, **kwargs: Any) -> Array:
12401241

12411242

12421243
# TODO: add type annotations for kwargs and fill_value
1243-
def full(shape: tuple[int, ...], fill_value: Any, **kwargs: Any) -> Array:
1244+
def full(shape: tuple[int, ...], fill_value: Any, **kwargs: Any) -> AnyArray:
12441245
"""Create an array with a default fill value.
12451246
12461247
Parameters
@@ -1262,7 +1263,7 @@ def full(shape: tuple[int, ...], fill_value: Any, **kwargs: Any) -> Array:
12621263

12631264
# TODO: move ArrayLike to common module
12641265
# TODO: add type annotations for kwargs
1265-
def full_like(a: ArrayLike, **kwargs: Any) -> Array:
1266+
def full_like(a: ArrayLike, **kwargs: Any) -> AnyArray:
12661267
"""Create a filled array like another array.
12671268
12681269
Parameters
@@ -1281,7 +1282,7 @@ def full_like(a: ArrayLike, **kwargs: Any) -> Array:
12811282

12821283

12831284
# TODO: add type annotations for kwargs
1284-
def ones(shape: tuple[int, ...], **kwargs: Any) -> Array:
1285+
def ones(shape: tuple[int, ...], **kwargs: Any) -> AnyArray:
12851286
"""Create an array with a fill value of one.
12861287
12871288
Parameters
@@ -1300,7 +1301,7 @@ def ones(shape: tuple[int, ...], **kwargs: Any) -> Array:
13001301

13011302

13021303
# TODO: add type annotations for kwargs
1303-
def ones_like(a: ArrayLike, **kwargs: Any) -> Array:
1304+
def ones_like(a: ArrayLike, **kwargs: Any) -> AnyArray:
13041305
"""Create an array of ones like another array.
13051306
13061307
Parameters
@@ -1327,7 +1328,7 @@ def open_array(
13271328
path: PathLike = "",
13281329
storage_options: dict[str, Any] | None = None,
13291330
**kwargs: Any,
1330-
) -> Array:
1331+
) -> AnyArray:
13311332
"""Open an array using file-mode-like semantics.
13321333
13331334
Parameters
@@ -1367,7 +1368,7 @@ def open_array(
13671368

13681369

13691370
# TODO: add type annotations for kwargs
1370-
def open_like(a: ArrayLike, path: str, **kwargs: Any) -> Array:
1371+
def open_like(a: ArrayLike, path: str, **kwargs: Any) -> AnyArray:
13711372
"""Open a persistent array like another array.
13721373
13731374
Parameters
@@ -1388,7 +1389,7 @@ def open_like(a: ArrayLike, path: str, **kwargs: Any) -> Array:
13881389

13891390

13901391
# TODO: add type annotations for kwargs
1391-
def zeros(shape: tuple[int, ...], **kwargs: Any) -> Array:
1392+
def zeros(shape: tuple[int, ...], **kwargs: Any) -> AnyArray:
13921393
"""Create an array with a fill value of zero.
13931394
13941395
Parameters
@@ -1407,7 +1408,7 @@ def zeros(shape: tuple[int, ...], **kwargs: Any) -> Array:
14071408

14081409

14091410
# TODO: add type annotations for kwargs
1410-
def zeros_like(a: ArrayLike, **kwargs: Any) -> Array:
1411+
def zeros_like(a: ArrayLike, **kwargs: Any) -> AnyArray:
14111412
"""Create an array of zeros like another array.
14121413
14131414
Parameters

src/zarr/core/array.py

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@
144144
from zarr.codecs.sharding import ShardingCodecIndexLocation
145145
from zarr.core.dtype.wrapper import TBaseDType, TBaseScalar
146146
from zarr.storage import StoreLike
147+
from zarr.types import AnyArray
147148

148149

149150
# Array and AsyncArray are defined in the base ``zarr`` namespace
@@ -1985,12 +1986,12 @@ def _info(
19851986

19861987
# TODO: Array can be a frozen data class again once property setters (e.g. shape) are removed
19871988
@dataclass(frozen=False)
1988-
class Array:
1989+
class Array(Generic[T_ArrayMetadata]):
19891990
"""
19901991
A Zarr array.
19911992
"""
19921993

1993-
_async_array: AsyncArray[ArrayV3Metadata] | AsyncArray[ArrayV2Metadata]
1994+
_async_array: AsyncArray[T_ArrayMetadata]
19941995

19951996
@classmethod
19961997
@deprecated("Use zarr.create_array instead.", category=ZarrDeprecationWarning)
@@ -2023,7 +2024,7 @@ def create(
20232024
# runtime
20242025
overwrite: bool = False,
20252026
config: ArrayConfigLike | None = None,
2026-
) -> Array:
2027+
) -> AnyArray:
20272028
"""Creates a new Array instance from an initialized store.
20282029
20292030
!!! warning "Deprecated"
@@ -2165,7 +2166,7 @@ def _create(
21652166
# runtime
21662167
overwrite: bool = False,
21672168
config: ArrayConfigLike | None = None,
2168-
) -> Array:
2169+
) -> AnyArray:
21692170
"""Creates a new Array instance from an initialized store.
21702171
Deprecated in favor of [`zarr.create_array`][].
21712172
"""
@@ -2190,14 +2191,14 @@ def _create(
21902191
config=config,
21912192
),
21922193
)
2193-
return cls(async_array)
2194+
return Array(async_array)
21942195

21952196
@classmethod
21962197
def from_dict(
21972198
cls,
21982199
store_path: StorePath,
21992200
data: dict[str, JSON],
2200-
) -> Array:
2201+
) -> AnyArray:
22012202
"""
22022203
Create a Zarr array from a dictionary.
22032204
@@ -2221,13 +2222,13 @@ def from_dict(
22212222
If the dictionary data is invalid or missing required fields for array creation.
22222223
"""
22232224
async_array = AsyncArray.from_dict(store_path=store_path, data=data)
2224-
return cls(async_array)
2225+
return Array(async_array)
22252226

22262227
@classmethod
22272228
def open(
22282229
cls,
22292230
store: StoreLike,
2230-
) -> Array:
2231+
) -> AnyArray:
22312232
"""Opens an existing Array from a store.
22322233
22332234
Parameters
@@ -2241,7 +2242,7 @@ def open(
22412242
Array opened from the store.
22422243
"""
22432244
async_array = sync(AsyncArray.open(store))
2244-
return cls(async_array)
2245+
return Array(async_array)
22452246

22462247
@property
22472248
def store(self) -> Store:
@@ -4077,7 +4078,7 @@ def append(self, data: npt.ArrayLike, axis: int = 0) -> tuple[int, ...]:
40774078
"""
40784079
return sync(self._async_array.append(data, axis=axis))
40794080

4080-
def update_attributes(self, new_attributes: dict[str, JSON]) -> Array:
4081+
def update_attributes(self, new_attributes: dict[str, JSON]) -> Self:
40814082
"""
40824083
Update the array's attributes.
40834084
@@ -4102,11 +4103,8 @@ def update_attributes(self, new_attributes: dict[str, JSON]) -> Array:
41024103
- The updated attributes will be merged with existing attributes, and any conflicts will be
41034104
overwritten by the new values.
41044105
"""
4105-
# TODO: remove this cast when type inference improves
41064106
new_array = sync(self._async_array.update_attributes(new_attributes))
4107-
# TODO: remove this cast when type inference improves
4108-
_new_array = cast("AsyncArray[ArrayV2Metadata] | AsyncArray[ArrayV3Metadata]", new_array)
4109-
return type(self)(_new_array)
4107+
return type(self)(new_array)
41104108

41114109
def __repr__(self) -> str:
41124110
return f"<Array {self.store_path} shape={self.shape} dtype={self.dtype}>"
@@ -4228,7 +4226,7 @@ class ShardsConfigParam(TypedDict):
42284226
async def from_array(
42294227
store: StoreLike,
42304228
*,
4231-
data: Array | npt.ArrayLike,
4229+
data: AnyArray | npt.ArrayLike,
42324230
write_data: bool = True,
42334231
name: str | None = None,
42344232
chunks: Literal["auto", "keep"] | tuple[int, ...] = "keep",
@@ -4468,7 +4466,7 @@ async def from_array(
44684466
if isinstance(data, Array):
44694467

44704468
async def _copy_array_region(
4471-
chunk_coords: tuple[int, ...] | slice, _data: Array
4469+
chunk_coords: tuple[int, ...] | slice, _data: AnyArray
44724470
) -> None:
44734471
arr = await _data._async_array.getitem(chunk_coords)
44744472
await result.setitem(chunk_coords, arr)
@@ -4896,7 +4894,7 @@ async def create_array(
48964894

48974895

48984896
def _parse_keep_array_attr(
4899-
data: Array | npt.ArrayLike,
4897+
data: AnyArray | npt.ArrayLike,
49004898
chunks: Literal["auto", "keep"] | tuple[int, ...],
49014899
shards: ShardsLike | None | Literal["keep"],
49024900
filters: FiltersLike | Literal["keep"],
@@ -5275,7 +5273,7 @@ def _parse_data_params(
52755273

52765274

52775275
def _iter_chunk_coords(
5278-
array: Array | AsyncArray[Any],
5276+
array: AnyArray | AsyncArray[Any],
52795277
*,
52805278
origin: Sequence[int] | None = None,
52815279
selection_shape: Sequence[int] | None = None,
@@ -5306,7 +5304,7 @@ def _iter_chunk_coords(
53065304

53075305

53085306
def _iter_shard_coords(
5309-
array: Array | AsyncArray[Any],
5307+
array: AnyArray | AsyncArray[Any],
53105308
*,
53115309
origin: Sequence[int] | None = None,
53125310
selection_shape: Sequence[int] | None = None,
@@ -5337,7 +5335,7 @@ def _iter_shard_coords(
53375335

53385336

53395337
def _iter_shard_keys(
5340-
array: Array | AsyncArray[Any],
5338+
array: AnyArray | AsyncArray[Any],
53415339
*,
53425340
origin: Sequence[int] | None = None,
53435341
selection_shape: Sequence[int] | None = None,
@@ -5366,7 +5364,7 @@ def _iter_shard_keys(
53665364

53675365

53685366
def _iter_shard_regions(
5369-
array: Array | AsyncArray[Any],
5367+
array: AnyArray | AsyncArray[Any],
53705368
*,
53715369
origin: Sequence[int] | None = None,
53725370
selection_shape: Sequence[int] | None = None,
@@ -5401,7 +5399,7 @@ def _iter_shard_regions(
54015399

54025400

54035401
def _iter_chunk_regions(
5404-
array: Array | AsyncArray[Any],
5402+
array: AnyArray | AsyncArray[Any],
54055403
*,
54065404
origin: Sequence[int] | None = None,
54075405
selection_shape: Sequence[int] | None = None,

src/zarr/core/attributes.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@
88
if TYPE_CHECKING:
99
from collections.abc import Iterator
1010

11-
from zarr.core.array import Array
1211
from zarr.core.group import Group
12+
from zarr.types import AnyArray
1313

1414

1515
class Attributes(MutableMapping[str, JSON]):
16-
def __init__(self, obj: Array | Group) -> None:
16+
def __init__(self, obj: AnyArray | Group) -> None:
1717
# key=".zattrs", read_only=False, cache=True, synchronizer=None
1818
self._obj = obj
1919

0 commit comments

Comments
 (0)