Skip to content

Commit fbe2e39

Browse files
committed
Parametrize Array with v2/v3 metadata
1 parent d0c3b7f commit fbe2e39

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__ = [
@@ -602,7 +605,7 @@ async def tree(grp: AsyncGroup, expand: bool | None = None, level: int | None =
602605

603606

604607
async def array(
605-
data: npt.ArrayLike | Array, **kwargs: Any
608+
data: npt.ArrayLike | AnyArray, **kwargs: Any
606609
) -> AsyncArray[ArrayV2Metadata] | AsyncArray[ArrayV3Metadata]:
607610
"""Create an array filled with `data`.
608611

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",
@@ -181,7 +182,7 @@ def open(
181182
path: str | None = None,
182183
storage_options: dict[str, Any] | None = None,
183184
**kwargs: Any, # TODO: type kwargs as valid args to async_api.open
184-
) -> Array | Group:
185+
) -> AnyArray | Group:
185186
"""Open a group or array using file-mode-like semantics.
186187
187188
Parameters
@@ -387,7 +388,7 @@ def tree(grp: Group, expand: bool | None = None, level: int | None = None) -> An
387388

388389

389390
# TODO: add type annotations for kwargs
390-
def array(data: npt.ArrayLike | Array, **kwargs: Any) -> Array:
391+
def array(data: npt.ArrayLike | AnyArray, **kwargs: Any) -> AnyArray:
391392
"""Create an array filled with `data`.
392393
393394
Parameters
@@ -652,7 +653,7 @@ def create(
652653
storage_options: dict[str, Any] | None = None,
653654
config: ArrayConfigLike | None = None,
654655
**kwargs: Any,
655-
) -> Array:
656+
) -> AnyArray:
656657
"""Create an array.
657658
658659
Parameters
@@ -836,7 +837,7 @@ def create_array(
836837
overwrite: bool = False,
837838
config: ArrayConfigLike | None = None,
838839
write_data: bool = True,
839-
) -> Array:
840+
) -> AnyArray:
840841
"""Create an array.
841842
842843
This function wraps [zarr.core.array.create_array][].
@@ -989,7 +990,7 @@ def create_array(
989990
def from_array(
990991
store: StoreLike,
991992
*,
992-
data: Array | npt.ArrayLike,
993+
data: AnyArray | npt.ArrayLike,
993994
write_data: bool = True,
994995
name: str | None = None,
995996
chunks: Literal["auto", "keep"] | tuple[int, ...] = "keep",
@@ -1006,7 +1007,7 @@ def from_array(
10061007
storage_options: dict[str, Any] | None = None,
10071008
overwrite: bool = False,
10081009
config: ArrayConfigLike | None = None,
1009-
) -> Array:
1010+
) -> AnyArray:
10101011
"""Create an array from an existing array or array-like.
10111012
10121013
Parameters
@@ -1220,7 +1221,7 @@ def from_array(
12201221

12211222

12221223
# TODO: add type annotations for kwargs
1223-
def empty(shape: tuple[int, ...], **kwargs: Any) -> Array:
1224+
def empty(shape: tuple[int, ...], **kwargs: Any) -> AnyArray:
12241225
"""Create an empty array with the specified shape. The contents will be filled with the
12251226
array's fill value or zeros if no fill value is provided.
12261227
@@ -1247,7 +1248,7 @@ def empty(shape: tuple[int, ...], **kwargs: Any) -> Array:
12471248

12481249
# TODO: move ArrayLike to common module
12491250
# TODO: add type annotations for kwargs
1250-
def empty_like(a: ArrayLike, **kwargs: Any) -> Array:
1251+
def empty_like(a: ArrayLike, **kwargs: Any) -> AnyArray:
12511252
"""Create an empty array like another array. The contents will be filled with the
12521253
array's fill value or zeros if no fill value is provided.
12531254
@@ -1273,7 +1274,7 @@ def empty_like(a: ArrayLike, **kwargs: Any) -> Array:
12731274

12741275

12751276
# TODO: add type annotations for kwargs and fill_value
1276-
def full(shape: tuple[int, ...], fill_value: Any, **kwargs: Any) -> Array:
1277+
def full(shape: tuple[int, ...], fill_value: Any, **kwargs: Any) -> AnyArray:
12771278
"""Create an array with a default fill value.
12781279
12791280
Parameters
@@ -1295,7 +1296,7 @@ def full(shape: tuple[int, ...], fill_value: Any, **kwargs: Any) -> Array:
12951296

12961297
# TODO: move ArrayLike to common module
12971298
# TODO: add type annotations for kwargs
1298-
def full_like(a: ArrayLike, **kwargs: Any) -> Array:
1299+
def full_like(a: ArrayLike, **kwargs: Any) -> AnyArray:
12991300
"""Create a filled array like another array.
13001301
13011302
Parameters
@@ -1314,7 +1315,7 @@ def full_like(a: ArrayLike, **kwargs: Any) -> Array:
13141315

13151316

13161317
# TODO: add type annotations for kwargs
1317-
def ones(shape: tuple[int, ...], **kwargs: Any) -> Array:
1318+
def ones(shape: tuple[int, ...], **kwargs: Any) -> AnyArray:
13181319
"""Create an array with a fill value of one.
13191320
13201321
Parameters
@@ -1333,7 +1334,7 @@ def ones(shape: tuple[int, ...], **kwargs: Any) -> Array:
13331334

13341335

13351336
# TODO: add type annotations for kwargs
1336-
def ones_like(a: ArrayLike, **kwargs: Any) -> Array:
1337+
def ones_like(a: ArrayLike, **kwargs: Any) -> AnyArray:
13371338
"""Create an array of ones like another array.
13381339
13391340
Parameters
@@ -1360,7 +1361,7 @@ def open_array(
13601361
path: PathLike = "",
13611362
storage_options: dict[str, Any] | None = None,
13621363
**kwargs: Any,
1363-
) -> Array:
1364+
) -> AnyArray:
13641365
"""Open an array using file-mode-like semantics.
13651366
13661367
Parameters
@@ -1402,7 +1403,7 @@ def open_array(
14021403

14031404

14041405
# TODO: add type annotations for kwargs
1405-
def open_like(a: ArrayLike, path: str, **kwargs: Any) -> Array:
1406+
def open_like(a: ArrayLike, path: str, **kwargs: Any) -> AnyArray:
14061407
"""Open a persistent array like another array.
14071408
14081409
Parameters
@@ -1423,7 +1424,7 @@ def open_like(a: ArrayLike, path: str, **kwargs: Any) -> Array:
14231424

14241425

14251426
# TODO: add type annotations for kwargs
1426-
def zeros(shape: tuple[int, ...], **kwargs: Any) -> Array:
1427+
def zeros(shape: tuple[int, ...], **kwargs: Any) -> AnyArray:
14271428
"""Create an array with a fill value of zero.
14281429
14291430
Parameters
@@ -1442,7 +1443,7 @@ def zeros(shape: tuple[int, ...], **kwargs: Any) -> Array:
14421443

14431444

14441445
# TODO: add type annotations for kwargs
1445-
def zeros_like(a: ArrayLike, **kwargs: Any) -> Array:
1446+
def zeros_like(a: ArrayLike, **kwargs: Any) -> AnyArray:
14461447
"""Create an array of zeros like another array.
14471448
14481449
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
@@ -2032,12 +2033,12 @@ def _info(
20322033

20332034
# TODO: Array can be a frozen data class again once property setters (e.g. shape) are removed
20342035
@dataclass(frozen=False)
2035-
class Array:
2036+
class Array(Generic[T_ArrayMetadata]):
20362037
"""
20372038
A Zarr array.
20382039
"""
20392040

2040-
_async_array: AsyncArray[ArrayV3Metadata] | AsyncArray[ArrayV2Metadata]
2041+
_async_array: AsyncArray[T_ArrayMetadata]
20412042

20422043
@classmethod
20432044
@deprecated("Use zarr.create_array instead.", category=ZarrDeprecationWarning)
@@ -2070,7 +2071,7 @@ def create(
20702071
# runtime
20712072
overwrite: bool = False,
20722073
config: ArrayConfigLike | None = None,
2073-
) -> Array:
2074+
) -> AnyArray:
20742075
"""Creates a new Array instance from an initialized store.
20752076
20762077
!!! warning "Deprecated"
@@ -2214,7 +2215,7 @@ def _create(
22142215
# runtime
22152216
overwrite: bool = False,
22162217
config: ArrayConfigLike | None = None,
2217-
) -> Array:
2218+
) -> AnyArray:
22182219
"""Creates a new Array instance from an initialized store.
22192220
Deprecated in favor of [`zarr.create_array`][].
22202221
"""
@@ -2239,14 +2240,14 @@ def _create(
22392240
config=config,
22402241
),
22412242
)
2242-
return cls(async_array)
2243+
return Array(async_array)
22432244

22442245
@classmethod
22452246
def from_dict(
22462247
cls,
22472248
store_path: StorePath,
22482249
data: dict[str, JSON],
2249-
) -> Array:
2250+
) -> AnyArray:
22502251
"""
22512252
Create a Zarr array from a dictionary.
22522253
@@ -2270,13 +2271,13 @@ def from_dict(
22702271
If the dictionary data is invalid or missing required fields for array creation.
22712272
"""
22722273
async_array = AsyncArray.from_dict(store_path=store_path, data=data)
2273-
return cls(async_array)
2274+
return Array(async_array)
22742275

22752276
@classmethod
22762277
def open(
22772278
cls,
22782279
store: StoreLike,
2279-
) -> Array:
2280+
) -> AnyArray:
22802281
"""Opens an existing Array from a store.
22812282
22822283
Parameters
@@ -2292,7 +2293,7 @@ def open(
22922293
Array opened from the store.
22932294
"""
22942295
async_array = sync(AsyncArray.open(store))
2295-
return cls(async_array)
2296+
return Array(async_array)
22962297

22972298
@property
22982299
def store(self) -> Store:
@@ -4128,7 +4129,7 @@ def append(self, data: npt.ArrayLike, axis: int = 0) -> tuple[int, ...]:
41284129
"""
41294130
return sync(self._async_array.append(data, axis=axis))
41304131

4131-
def update_attributes(self, new_attributes: dict[str, JSON]) -> Array:
4132+
def update_attributes(self, new_attributes: dict[str, JSON]) -> Self:
41324133
"""
41334134
Update the array's attributes.
41344135
@@ -4153,11 +4154,8 @@ def update_attributes(self, new_attributes: dict[str, JSON]) -> Array:
41534154
- The updated attributes will be merged with existing attributes, and any conflicts will be
41544155
overwritten by the new values.
41554156
"""
4156-
# TODO: remove this cast when type inference improves
41574157
new_array = sync(self._async_array.update_attributes(new_attributes))
4158-
# TODO: remove this cast when type inference improves
4159-
_new_array = cast("AsyncArray[ArrayV2Metadata] | AsyncArray[ArrayV3Metadata]", new_array)
4160-
return type(self)(_new_array)
4158+
return type(self)(new_array)
41614159

41624160
def __repr__(self) -> str:
41634161
return f"<Array {self.store_path} shape={self.shape} dtype={self.dtype}>"
@@ -4279,7 +4277,7 @@ class ShardsConfigParam(TypedDict):
42794277
async def from_array(
42804278
store: StoreLike,
42814279
*,
4282-
data: Array | npt.ArrayLike,
4280+
data: AnyArray | npt.ArrayLike,
42834281
write_data: bool = True,
42844282
name: str | None = None,
42854283
chunks: Literal["auto", "keep"] | tuple[int, ...] = "keep",
@@ -4521,7 +4519,7 @@ async def from_array(
45214519
if isinstance(data, Array):
45224520

45234521
async def _copy_array_region(
4524-
chunk_coords: tuple[int, ...] | slice, _data: Array
4522+
chunk_coords: tuple[int, ...] | slice, _data: AnyArray
45254523
) -> None:
45264524
arr = await _data._async_array.getitem(chunk_coords)
45274525
await result.setitem(chunk_coords, arr)
@@ -4951,7 +4949,7 @@ async def create_array(
49514949

49524950

49534951
def _parse_keep_array_attr(
4954-
data: Array | npt.ArrayLike,
4952+
data: AnyArray | npt.ArrayLike,
49554953
chunks: Literal["auto", "keep"] | tuple[int, ...],
49564954
shards: ShardsLike | None | Literal["keep"],
49574955
filters: FiltersLike | Literal["keep"],
@@ -5330,7 +5328,7 @@ def _parse_data_params(
53305328

53315329

53325330
def _iter_chunk_coords(
5333-
array: Array | AsyncArray[Any],
5331+
array: AnyArray | AsyncArray[Any],
53345332
*,
53355333
origin: Sequence[int] | None = None,
53365334
selection_shape: Sequence[int] | None = None,
@@ -5361,7 +5359,7 @@ def _iter_chunk_coords(
53615359

53625360

53635361
def _iter_shard_coords(
5364-
array: Array | AsyncArray[Any],
5362+
array: AnyArray | AsyncArray[Any],
53655363
*,
53665364
origin: Sequence[int] | None = None,
53675365
selection_shape: Sequence[int] | None = None,
@@ -5392,7 +5390,7 @@ def _iter_shard_coords(
53925390

53935391

53945392
def _iter_shard_keys(
5395-
array: Array | AsyncArray[Any],
5393+
array: AnyArray | AsyncArray[Any],
53965394
*,
53975395
origin: Sequence[int] | None = None,
53985396
selection_shape: Sequence[int] | None = None,
@@ -5421,7 +5419,7 @@ def _iter_shard_keys(
54215419

54225420

54235421
def _iter_shard_regions(
5424-
array: Array | AsyncArray[Any],
5422+
array: AnyArray | AsyncArray[Any],
54255423
*,
54265424
origin: Sequence[int] | None = None,
54275425
selection_shape: Sequence[int] | None = None,
@@ -5456,7 +5454,7 @@ def _iter_shard_regions(
54565454

54575455

54585456
def _iter_chunk_regions(
5459-
array: Array | AsyncArray[Any],
5457+
array: AnyArray | AsyncArray[Any],
54605458
*,
54615459
origin: Sequence[int] | None = None,
54625460
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)