Skip to content

Commit b5e5216

Browse files
authored
Merge branch 'main' into refactor/store-mode
2 parents ee47265 + 498cb78 commit b5e5216

36 files changed

+258
-220
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/gh-action-pypi-publish@v1.10.3
58+
- uses: pypa/gh-action-pypi-publish@v1.11.0
5959
with:
6060
user: __token__
6161
password: ${{ secrets.pypi_password }}

.github/workflows/test.yml

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,14 @@ jobs:
3333
numpy-version: '2.1'
3434
dependency-set: 'optional'
3535
os: 'macos-latest'
36-
# https://github.com/zarr-developers/zarr-python/issues/2438
37-
# - python-version: '3.11'
38-
# numpy-version: '1.25'
39-
# dependency-set: 'optional'
40-
# os: 'windows-latest'
41-
# - python-version: '3.13'
42-
# numpy-version: '2.1'
43-
# dependency-set: 'optional'
44-
# os: 'windows-latest'
36+
- python-version: '3.11'
37+
numpy-version: '1.25'
38+
dependency-set: 'optional'
39+
os: 'windows-latest'
40+
- python-version: '3.13'
41+
numpy-version: '2.1'
42+
dependency-set: 'optional'
43+
os: 'windows-latest'
4544
runs-on: ${{ matrix.os }}
4645

4746
steps:

.pre-commit-config.yaml

Lines changed: 2 additions & 2 deletions
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.7.0
10+
rev: v0.7.2
1111
hooks:
1212
- id: ruff
1313
args: ["--fix", "--show-fixes"]
@@ -22,7 +22,7 @@ repos:
2222
hooks:
2323
- id: check-yaml
2424
- repo: https://github.com/pre-commit/mirrors-mypy
25-
rev: v1.12.1
25+
rev: v1.13.0
2626
hooks:
2727
- id: mypy
2828
files: src|tests

pyproject.toml

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ gpu = [
8383
docs = [
8484
'sphinx==8.1.3',
8585
'sphinx-autobuild>=2021.3.14',
86-
'sphinx-autoapi==3.3.2',
86+
'sphinx-autoapi==3.3.3',
8787
'sphinx_design',
8888
'sphinx-issues',
8989
'sphinx-copybutton',
@@ -269,19 +269,25 @@ extend-exclude = [
269269
extend-select = [
270270
"ANN", # flake8-annotations
271271
"B", # flake8-bugbear
272+
"EXE", # flake8-executable
272273
"C4", # flake8-comprehensions
274+
"FA", # flake8-future-annotations
273275
"FLY", # flynt
274276
"FURB", # refurb
275277
"G", # flake8-logging-format
276278
"I", # isort
277279
"ISC", # flake8-implicit-str-concat
280+
"LOG", # flake8-logging
278281
"PERF", # Perflint
282+
"PIE", # flake8-pie
279283
"PGH", # pygrep-hooks
280284
"PT", # flake8-pytest-style
281285
"PYI", # flake8-pyi
282-
"RSE", # flake8-raise
283286
"RET", # flake8-return
287+
"RSE", # flake8-raise
284288
"RUF",
289+
"SIM", # flake8-simplify
290+
"SLOT", # flake8-slots
285291
"TCH", # flake8-type-checking
286292
"TRY", # tryceratops
287293
"UP", # pyupgrade
@@ -298,6 +304,7 @@ ignore = [
298304
"RET505",
299305
"RET506",
300306
"RUF005",
307+
"SIM108",
301308
"TRY003",
302309
"UP027", # deprecated
303310
"UP038", # https://github.com/astral-sh/ruff/issues/7871
@@ -319,7 +326,7 @@ ignore = [
319326
]
320327

321328
[tool.ruff.lint.extend-per-file-ignores]
322-
"tests/**" = ["ANN001", "ANN201"]
329+
"tests/**" = ["ANN001", "ANN201", "RUF029", "SIM117", "SIM300"]
323330

324331
[tool.mypy]
325332
python_version = "3.11"

src/zarr/abc/codec.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,6 @@ def validate(self, *, shape: ChunkCoords, dtype: np.dtype[Any], chunk_grid: Chun
106106
chunk_grid : ChunkGrid
107107
The array chunk grid
108108
"""
109-
...
110109

111110
async def _decode_single(self, chunk_data: CodecOutput, chunk_spec: ArraySpec) -> CodecInput:
112111
raise NotImplementedError

src/zarr/abc/metadata.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,5 @@ def from_dict(cls, data: dict[str, JSON]) -> Self:
4242
"""
4343
Create an instance of the model from a dictionary
4444
"""
45-
...
4645

4746
return cls(**data)

src/zarr/abc/store.py

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,6 @@ async def _set_many(self, values: Iterable[tuple[str, Buffer]]) -> None:
250250
Insert multiple (key, value) pairs into storage.
251251
"""
252252
await gather(*starmap(self.set, values))
253-
return
254253

255254
@property
256255
@abstractmethod
@@ -296,20 +295,19 @@ def supports_listing(self) -> bool:
296295
...
297296

298297
@abstractmethod
299-
def list(self) -> AsyncGenerator[str, None]:
298+
def list(self) -> AsyncGenerator[str]:
300299
"""Retrieve all keys in the store.
301300
302301
Returns
303302
-------
304303
AsyncGenerator[str, None]
305304
"""
306-
...
307305

308306
@abstractmethod
309-
def list_prefix(self, prefix: str) -> AsyncGenerator[str, None]:
307+
def list_prefix(self, prefix: str) -> AsyncGenerator[str]:
310308
"""
311-
Retrieve all keys in the store that begin with a given prefix. Keys are returned as
312-
absolute paths (i.e. including the prefix).
309+
Retrieve all keys in the store that begin with a given prefix. Keys are returned relative
310+
to the root of the store.
313311
314312
Parameters
315313
----------
@@ -319,10 +317,9 @@ def list_prefix(self, prefix: str) -> AsyncGenerator[str, None]:
319317
-------
320318
AsyncGenerator[str, None]
321319
"""
322-
...
323320

324321
@abstractmethod
325-
def list_dir(self, prefix: str) -> AsyncGenerator[str, None]:
322+
def list_dir(self, prefix: str) -> AsyncGenerator[str]:
326323
"""
327324
Retrieve all keys and prefixes with a given prefix and which do not contain the character
328325
“/” after the given prefix.
@@ -335,7 +332,20 @@ def list_dir(self, prefix: str) -> AsyncGenerator[str, None]:
335332
-------
336333
AsyncGenerator[str, None]
337334
"""
338-
...
335+
336+
async def delete_dir(self, prefix: str) -> None:
337+
"""
338+
Remove all keys and prefixes in the store that begin with a given prefix.
339+
"""
340+
if not self.supports_deletes:
341+
raise NotImplementedError
342+
if not self.supports_listing:
343+
raise NotImplementedError
344+
self._check_writable()
345+
if not prefix.endswith("/"):
346+
prefix += "/"
347+
async for key in self.list_prefix(prefix):
348+
await self.delete(key)
339349

340350
async def delete_dir(self, prefix: str) -> None:
341351
"""

src/zarr/api/asynchronous.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import numpy.typing as npt
1010

1111
from zarr.core.array import Array, AsyncArray, get_array_metadata
12+
from zarr.core.buffer import NDArrayLike
1213
from zarr.core.common import (
1314
JSON,
1415
AccessModeLiteral,
@@ -422,6 +423,8 @@ async def save_array(
422423
_handle_zarr_version_or_format(zarr_version=zarr_version, zarr_format=zarr_format)
423424
or _default_zarr_version()
424425
)
426+
if not isinstance(arr, NDArrayLike):
427+
raise TypeError("arr argument must be numpy or other NDArrayLike array")
425428

426429
mode = kwargs.pop("mode", "a")
427430
store_mode = _handle_store_mode(mode)
@@ -484,16 +487,27 @@ async def save_group(
484487
or _default_zarr_version()
485488
)
486489

490+
for arg in args:
491+
if not isinstance(arg, NDArrayLike):
492+
raise TypeError(
493+
"All arguments must be numpy or other NDArrayLike arrays (except store, path, storage_options, and zarr_format)"
494+
)
495+
for k, v in kwargs.items():
496+
if not isinstance(v, NDArrayLike):
497+
raise TypeError(f"Keyword argument '{k}' must be a numpy or other NDArrayLike array")
498+
487499
if len(args) == 0 and len(kwargs) == 0:
488500
raise ValueError("at least one array must be provided")
489501
aws = []
490502
for i, arr in enumerate(args):
503+
_path = f"{path}/arr_{i}" if path is not None else f"arr_{i}"
491504
aws.append(
492505
save_array(
493506
store_path,
494507
arr,
495508
zarr_format=zarr_format,
496-
path=f"arr_{i}",
509+
path=_path,
510+
storage_options=storage_options,
497511
)
498512
)
499513
for k, arr in kwargs.items():
@@ -923,7 +937,6 @@ async def create(
923937
store, path=path, mode=store_mode, storage_options=storage_options
924938
)
925939
await store_path._init(mode)
926-
927940
return await AsyncArray.create(
928941
store_path,
929942
shape=shape,

src/zarr/codecs/__init__.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,13 @@
99
from zarr.codecs.bytes import BytesCodec, Endian
1010
from zarr.codecs.crc32c_ import Crc32cCodec
1111
from zarr.codecs.gzip import GzipCodec
12-
from zarr.codecs.pipeline import BatchedCodecPipeline
1312
from zarr.codecs.sharding import ShardingCodec, ShardingCodecIndexLocation
1413
from zarr.codecs.transpose import TransposeCodec
1514
from zarr.codecs.vlen_utf8 import VLenBytesCodec, VLenUTF8Codec
1615
from zarr.codecs.zstd import ZstdCodec
1716
from zarr.core.metadata.v3 import DataType
1817

1918
__all__ = [
20-
"BatchedCodecPipeline",
2119
"BloscCname",
2220
"BloscCodec",
2321
"BloscShuffle",

src/zarr/codecs/gzip.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
def parse_gzip_level(data: JSON) -> int:
2222
if not isinstance(data, (int)):
2323
raise TypeError(f"Expected int, got {type(data)}")
24-
if data not in range(0, 10):
24+
if data not in range(10):
2525
raise ValueError(
2626
f"Expected an integer from the inclusive range (0, 9). Got {data} instead."
2727
)

0 commit comments

Comments
 (0)