Skip to content

Commit d6667a7

Browse files
authored
Merge branch 'main' into fix-obstore-listdir
2 parents cd086b1 + a06318e commit d6667a7

File tree

14 files changed

+355
-130
lines changed

14 files changed

+355
-130
lines changed

changes/3700.bugfix.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
CacheStore, LoggingStore and LatencyStore now support with_read_only.

changes/3705.bugfix.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix a performance bug in morton curve generation.

changes/3706.misc.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Allow NumPy ints as input when declaring a shape.

src/zarr/core/common.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
overload,
2222
)
2323

24+
import numpy as np
2425
from typing_extensions import ReadOnly
2526

2627
from zarr.core.config import config as zarr_config
@@ -37,7 +38,7 @@
3738
ZMETADATA_V2_JSON = ".zmetadata"
3839

3940
BytesLike = bytes | bytearray | memoryview
40-
ShapeLike = Iterable[int] | int
41+
ShapeLike = Iterable[int | np.integer[Any]] | int | np.integer[Any]
4142
# For backwards compatibility
4243
ChunkCoords = tuple[int, ...]
4344
ZarrFormat = Literal[2, 3]
@@ -185,23 +186,28 @@ def parse_named_configuration(
185186

186187

187188
def parse_shapelike(data: ShapeLike) -> tuple[int, ...]:
188-
if isinstance(data, int):
189+
"""
190+
Parse a shape-like input into an explicit shape.
191+
"""
192+
if isinstance(data, int | np.integer):
189193
if data < 0:
190194
raise ValueError(f"Expected a non-negative integer. Got {data} instead")
191-
return (data,)
195+
return (int(data),)
192196
try:
193197
data_tuple = tuple(data)
194198
except TypeError as e:
195199
msg = f"Expected an integer or an iterable of integers. Got {data} instead."
196200
raise TypeError(msg) from e
197201

198-
if not all(isinstance(v, int) for v in data_tuple):
202+
if not all(isinstance(v, int | np.integer) for v in data_tuple):
199203
msg = f"Expected an iterable of integers. Got {data} instead."
200204
raise TypeError(msg)
201205
if not all(v > -1 for v in data_tuple):
202206
msg = f"Expected all values to be non-negative. Got {data} instead."
203207
raise ValueError(msg)
204-
return data_tuple
208+
209+
# cast NumPy scalars to plain python ints
210+
return tuple(int(x) for x in data_tuple)
205211

206212

207213
def parse_fill_value(data: Any) -> Any:

src/zarr/core/indexing.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from collections.abc import Iterator, Sequence
88
from dataclasses import dataclass
99
from enum import Enum
10-
from functools import reduce
10+
from functools import lru_cache, reduce
1111
from types import EllipsisType
1212
from typing import (
1313
TYPE_CHECKING,
@@ -1467,16 +1467,21 @@ def decode_morton(z: int, chunk_shape: tuple[int, ...]) -> tuple[int, ...]:
14671467
return tuple(out)
14681468

14691469

1470-
def morton_order_iter(chunk_shape: tuple[int, ...]) -> Iterator[tuple[int, ...]]:
1471-
i = 0
1470+
@lru_cache
1471+
def _morton_order(chunk_shape: tuple[int, ...]) -> tuple[tuple[int, ...], ...]:
1472+
n_total = product(chunk_shape)
14721473
order: list[tuple[int, ...]] = []
1473-
while len(order) < product(chunk_shape):
1474+
i = 0
1475+
while len(order) < n_total:
14741476
m = decode_morton(i, chunk_shape)
1475-
if m not in order and all(x < y for x, y in zip(m, chunk_shape, strict=False)):
1477+
if all(x < y for x, y in zip(m, chunk_shape, strict=False)):
14761478
order.append(m)
14771479
i += 1
1478-
for j in range(product(chunk_shape)):
1479-
yield order[j]
1480+
return tuple(order)
1481+
1482+
1483+
def morton_order_iter(chunk_shape: tuple[int, ...]) -> Iterator[tuple[int, ...]]:
1484+
return iter(_morton_order(tuple(chunk_shape)))
14801485

14811486

14821487
def c_order_iter(chunks_per_shard: tuple[int, ...]) -> Iterator[tuple[int, ...]]:

0 commit comments

Comments
 (0)