Skip to content

Commit 10d062f

Browse files
committed
Merge remote-tracking branch 'upstream/v3' into user/tom/feature/consolidated-metadata
2 parents ba4fb47 + 30e2bc3 commit 10d062f

File tree

589 files changed

+350
-29290
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

589 files changed

+350
-29290
lines changed

.github/workflows/releases.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ jobs:
5555
with:
5656
name: releases
5757
path: dist
58-
- uses: pypa/[email protected].1
58+
- uses: pypa/[email protected].2
5959
with:
6060
user: __token__
6161
password: ${{ secrets.pypi_password }}

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ default_language_version:
77
python: python3
88
repos:
99
- repo: https://github.com/astral-sh/ruff-pre-commit
10-
rev: v0.6.5
10+
rev: v0.6.7
1111
hooks:
1212
- id: ruff
1313
args: ["--fix", "--show-fixes"]

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@ filterwarnings = [
274274
"ignore:PY_SSIZE_T_CLEAN will be required.*:DeprecationWarning",
275275
"ignore:The loop argument is deprecated since Python 3.8.*:DeprecationWarning",
276276
"ignore:Creating a zarr.buffer.gpu.*:UserWarning",
277+
"ignore:Duplicate name:UserWarning", # from ZipFile
277278
]
278279
markers = [
279280
"gpu: mark a test as requiring CuPy and GPU"

src/zarr/core/array_spec.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
from dataclasses import dataclass
44
from typing import TYPE_CHECKING, Any, Literal
55

6-
from zarr.core.common import parse_dtype, parse_fill_value, parse_order, parse_shapelike
6+
import numpy as np
77

8-
if TYPE_CHECKING:
9-
import numpy as np
8+
from zarr.core.common import parse_fill_value, parse_order, parse_shapelike
109

10+
if TYPE_CHECKING:
1111
from zarr.core.buffer import BufferPrototype
1212
from zarr.core.common import ChunkCoords
1313

@@ -29,7 +29,7 @@ def __init__(
2929
prototype: BufferPrototype,
3030
) -> None:
3131
shape_parsed = parse_shapelike(shape)
32-
dtype_parsed = parse_dtype(dtype)
32+
dtype_parsed = np.dtype(dtype)
3333
fill_value_parsed = parse_fill_value(fill_value)
3434
order_parsed = parse_order(order)
3535

src/zarr/core/attributes.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,6 @@ def put(self, d: dict[str, JSON]) -> None:
5151
{'a': 3, 'c': 4}
5252
"""
5353
self._obj = self._obj.update_attributes(d)
54+
55+
def asdict(self) -> dict[str, JSON]:
56+
return dict(self._obj.metadata.attributes)

src/zarr/core/common.py

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,9 @@
1616
overload,
1717
)
1818

19-
import numcodecs
20-
2119
if TYPE_CHECKING:
2220
from collections.abc import Awaitable, Callable, Iterator
2321

24-
import numpy as np
25-
import numpy.typing as npt
2622

2723
ZARR_JSON = "zarr.json"
2824
ZARRAY_JSON = ".zarray"
@@ -158,11 +154,6 @@ def parse_shapelike(data: int | Iterable[int]) -> tuple[int, ...]:
158154
return data_tuple
159155

160156

161-
def parse_dtype(data: npt.DTypeLike) -> np.dtype[Any]:
162-
# todo: real validation
163-
return np.dtype(data)
164-
165-
166157
def parse_fill_value(data: Any) -> Any:
167158
# todo: real validation
168159
return data
@@ -172,33 +163,3 @@ def parse_order(data: Any) -> Literal["C", "F"]:
172163
if data in ("C", "F"):
173164
return cast(Literal["C", "F"], data)
174165
raise ValueError(f"Expected one of ('C', 'F'), got {data} instead.")
175-
176-
177-
def _json_convert(o: object) -> Any:
178-
if isinstance(o, np.dtype):
179-
return str(o)
180-
if np.isscalar(o):
181-
out: Any
182-
if hasattr(o, "dtype") and o.dtype.kind == "M" and hasattr(o, "view"):
183-
# https://github.com/zarr-developers/zarr-python/issues/2119
184-
# `.item()` on a datetime type might or might not return an
185-
# integer, depending on the value.
186-
# Explicitly cast to an int first, and then grab .item()
187-
out = o.view("i8").item()
188-
else:
189-
# convert numpy scalar to python type, and pass
190-
# python types through
191-
out = getattr(o, "item", lambda: o)()
192-
if isinstance(out, complex):
193-
# python complex types are not JSON serializable, so we use the
194-
# serialization defined in the zarr v3 spec
195-
return [out.real, out.imag]
196-
return out
197-
if isinstance(o, Enum):
198-
return o.name
199-
# this serializes numcodecs compressors
200-
# todo: implement to_dict for codecs
201-
elif isinstance(o, numcodecs.abc.Codec):
202-
config: dict[str, Any] = o.get_config()
203-
return config
204-
raise TypeError

src/zarr/core/group.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66
import logging
77
from collections import defaultdict
88
from dataclasses import asdict, dataclass, field, replace
9+
from enum import Enum
910
from typing import TYPE_CHECKING, Literal, cast, overload
1011

12+
import numcodecs.abc
1113
import numpy as np
1214
import numpy.typing as npt
1315
from typing_extensions import deprecated
@@ -28,7 +30,6 @@
2830
ChunkCoords,
2931
ShapeLike,
3032
ZarrFormat,
31-
_json_convert,
3233
parse_shapelike,
3334
)
3435
from zarr.core.config import config
@@ -86,6 +87,36 @@ def _parse_async_node(node: AsyncArray | AsyncGroup) -> Array | Group:
8687
raise TypeError(f"Unknown node type, got {type(node)}")
8788

8889

90+
def _json_convert(o: object) -> Any:
91+
if isinstance(o, np.dtype):
92+
return str(o)
93+
if np.isscalar(o):
94+
out: Any
95+
if hasattr(o, "dtype") and o.dtype.kind == "M" and hasattr(o, "view"):
96+
# https://github.com/zarr-developers/zarr-python/issues/2119
97+
# `.item()` on a datetime type might or might not return an
98+
# integer, depending on the value.
99+
# Explicitly cast to an int first, and then grab .item()
100+
out = o.view("i8").item()
101+
else:
102+
# convert numpy scalar to python type, and pass
103+
# python types through
104+
out = getattr(o, "item", lambda: o)()
105+
if isinstance(out, complex):
106+
# python complex types are not JSON serializable, so we use the
107+
# serialization defined in the zarr v3 spec
108+
return [out.real, out.imag]
109+
return out
110+
if isinstance(o, Enum):
111+
return o.name
112+
# this serializes numcodecs compressors
113+
# todo: implement to_dict for codecs
114+
elif isinstance(o, numcodecs.abc.Codec):
115+
config: dict[str, Any] = o.get_config()
116+
return config
117+
raise TypeError
118+
119+
89120
@dataclass(frozen=True)
90121
class ConsolidatedMetadata:
91122
"""

src/zarr/core/metadata/v2.py

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from __future__ import annotations
22

33
from collections.abc import Iterable
4+
from enum import Enum
45
from typing import TYPE_CHECKING
56

67
if TYPE_CHECKING:
@@ -21,7 +22,7 @@
2122
from zarr.core.array_spec import ArraySpec
2223
from zarr.core.chunk_grids import RegularChunkGrid
2324
from zarr.core.chunk_key_encodings import parse_separator
24-
from zarr.core.common import ZARRAY_JSON, ZATTRS_JSON, parse_dtype, parse_shapelike
25+
from zarr.core.common import ZARRAY_JSON, ZATTRS_JSON, parse_shapelike
2526
from zarr.core.config import config, parse_indexing_order
2627
from zarr.core.metadata.common import ArrayMetadata, parse_attributes
2728

@@ -100,9 +101,24 @@ def _json_convert(
100101
else:
101102
return o.descr
102103
if np.isscalar(o):
103-
# convert numpy scalar to python type, and pass
104-
# python types through
105-
return getattr(o, "item", lambda: o)()
104+
out: Any
105+
if hasattr(o, "dtype") and o.dtype.kind == "M" and hasattr(o, "view"):
106+
# https://github.com/zarr-developers/zarr-python/issues/2119
107+
# `.item()` on a datetime type might or might not return an
108+
# integer, depending on the value.
109+
# Explicitly cast to an int first, and then grab .item()
110+
out = o.view("i8").item()
111+
else:
112+
# convert numpy scalar to python type, and pass
113+
# python types through
114+
out = getattr(o, "item", lambda: o)()
115+
if isinstance(out, complex):
116+
# python complex types are not JSON serializable, so we use the
117+
# serialization defined in the zarr v3 spec
118+
return [out.real, out.imag]
119+
return out
120+
if isinstance(o, Enum):
121+
return o.name
106122
raise TypeError
107123

108124
zarray_dict = self.to_dict()
@@ -157,6 +173,11 @@ def update_attributes(self, attributes: dict[str, JSON]) -> Self:
157173
return replace(self, attributes=attributes)
158174

159175

176+
def parse_dtype(data: npt.DTypeLike) -> np.dtype[Any]:
177+
# todo: real validation
178+
return np.dtype(data)
179+
180+
160181
def parse_zarr_format(data: object) -> Literal[2]:
161182
if data == 2:
162183
return 2

0 commit comments

Comments
 (0)