Skip to content

Commit d4e4d2b

Browse files
committed
special type for array.chunks
2 parents 41d4a91 + 884a8c9 commit d4e4d2b

6 files changed

Lines changed: 54 additions & 22 deletions

File tree

.pre-commit-config.yaml

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,13 @@ ci:
44
autofix_commit_msg: "style: pre-commit fixes"
55
autofix_prs: false
66
default_stages: [pre-commit, pre-push]
7+
8+
default_language_version:
9+
python: python3.11
10+
711
repos:
812
- repo: https://github.com/astral-sh/ruff-pre-commit
9-
rev: v0.14.3
13+
rev: v0.14.10
1014
hooks:
1115
- id: ruff-check
1216
args: ["--fix", "--show-fixes"]
@@ -23,7 +27,7 @@ repos:
2327
exclude: mkdocs.yml
2428
- id: trailing-whitespace
2529
- repo: https://github.com/pre-commit/mirrors-mypy
26-
rev: v1.18.2
30+
rev: v1.19.1
2731
hooks:
2832
- id: mypy
2933
files: src|tests
@@ -42,7 +46,7 @@ repos:
4246
- hypothesis
4347
- s3fs
4448
- repo: https://github.com/scientific-python/cookie
45-
rev: 2025.10.20
49+
rev: 2025.11.21
4650
hooks:
4751
- id: sp-repo-review
4852
- repo: https://github.com/pre-commit/pygrep-hooks
@@ -51,7 +55,7 @@ repos:
5155
- id: rst-directive-colons
5256
- id: rst-inline-touching-normal
5357
- repo: https://github.com/numpy/numpydoc
54-
rev: v1.9.0
58+
rev: v1.10.0
5559
hooks:
5660
- id: numpydoc-validation
5761
- repo: https://github.com/twisted/towncrier

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,7 @@ ignore_errors = true
395395
minversion = "7"
396396
testpaths = ["tests", "docs/user-guide"]
397397
log_cli_level = "INFO"
398+
log_level = "INFO"
398399
xfail_strict = true
399400
asyncio_mode = "auto"
400401
asyncio_default_fixture_loop_scope = "function"

src/zarr/_cli/cli.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ class CLIZarrFormatV3(str, Enum):
3535
v3 = "v3"
3636

3737

38-
@app.command() # type: ignore[misc]
38+
@app.command() # type: ignore[untyped-decorator]
3939
def migrate(
4040
zarr_format: Annotated[
4141
CLIZarrFormatV3,
@@ -120,7 +120,7 @@ def migrate(
120120
sync(migrate_metadata.remove_metadata(write_store, 2, force=False, dry_run=dry_run))
121121

122122

123-
@app.command() # type: ignore[misc]
123+
@app.command() # type: ignore[untyped-decorator]
124124
def remove_metadata(
125125
zarr_format: Annotated[
126126
CLIZarrFormat,
@@ -168,7 +168,7 @@ def remove_metadata(
168168
)
169169

170170

171-
@app.callback() # type: ignore[misc]
171+
@app.callback() # type: ignore[untyped-decorator]
172172
def main(
173173
verbose: Annotated[
174174
bool,

src/zarr/core/array.py

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1300,6 +1300,8 @@ def _shard_grid_shape(self) -> tuple[int, ...]:
13001300
"""
13011301
The shape of the shard grid for this array.
13021302
1303+
When no shards are present this will automatically fall back to the chunk grid.
1304+
13031305
Returns
13041306
-------
13051307
tuple[int, ...]
@@ -1331,10 +1333,12 @@ def _nshards(self) -> int:
13311333
"""
13321334
The number of shards in this array.
13331335
1336+
If no shards are present this will fall back to giving the number of chunks
1337+
13341338
Returns
13351339
-------
13361340
int
1337-
The total number of shards in the array.
1341+
The total number of shards or if absent, chunks in the array.
13381342
"""
13391343
return product(self._shard_grid_shape)
13401344

@@ -1464,6 +1468,8 @@ def _iter_shard_coords(
14641468
"""
14651469
Create an iterator over the coordinates of shards in shard grid space.
14661470
1471+
This will fall back to chunk grid space in case no shards are present.
1472+
14671473
Note that
14681474
14691475
If the `origin` keyword is used, iteration will start at the shard index specified by `origin`.
@@ -1482,7 +1488,7 @@ def _iter_shard_coords(
14821488
Yields
14831489
------
14841490
chunk_coords: tuple[int, ...]
1485-
The coordinates of each shard in the selection.
1491+
The coordinates of each shard in the selection or chunk in case of no shard being present.
14861492
"""
14871493
return _iter_shard_coords(
14881494
array=self,
@@ -1496,6 +1502,9 @@ def _iter_shard_keys(
14961502
"""
14971503
Iterate over the keys of the stored objects supporting this array.
14981504
1505+
Although only stored objects, e.g. shards should have keys, in case no
1506+
shards are present this automatically falls back to chunks.
1507+
14991508
Parameters
15001509
----------
15011510
origin : Sequence[int] | None, default=None
@@ -1506,7 +1515,8 @@ def _iter_shard_keys(
15061515
Yields
15071516
------
15081517
key: str
1509-
The storage key of each chunk in the selection.
1518+
The storage key of each shard in the selection or in case of no shard
1519+
present of each chunk although the latter case as technically incorrect.
15101520
"""
15111521
# Iterate over the coordinates of chunks in chunk grid space.
15121522
return _iter_shard_keys(
@@ -1545,6 +1555,8 @@ def _iter_shard_regions(
15451555
"""
15461556
Iterate over the regions spanned by each shard.
15471557
1558+
This will automatically fall back to chunks if no shards are present.
1559+
15481560
Parameters
15491561
----------
15501562
origin : Sequence[int] | None, default=None
@@ -1555,7 +1567,8 @@ def _iter_shard_regions(
15551567
Yields
15561568
------
15571569
region: tuple[slice, ...]
1558-
A tuple of slice objects representing the region spanned by each shard in the selection.
1570+
A tuple of slice objects representing the region spanned by each shard in the selection or chunk in the
1571+
absence of shards.
15591572
"""
15601573
return _iter_shard_regions(array=self, origin=origin, selection_shape=selection_shape)
15611574

@@ -2640,6 +2653,9 @@ def _iter_shard_keys(
26402653
Iterate over the storage keys of each shard, relative to an optional origin, and optionally
26412654
limited to a contiguous region in chunk grid coordinates.
26422655
2656+
If no shards are present this falls back to chunks, though in this case these are then actually
2657+
not storage keys.
2658+
26432659
Parameters
26442660
----------
26452661
origin : Sequence[int] | None, default=None
@@ -2650,7 +2666,8 @@ def _iter_shard_keys(
26502666
Yields
26512667
------
26522668
str
2653-
The storage key of each shard in the selection.
2669+
The storage key of each shard in the selection or chunk though chunks technically do not have
2670+
storage keys.
26542671
"""
26552672
return self.async_array._iter_shard_keys(origin=origin, selection_shape=selection_shape)
26562673

@@ -2730,7 +2747,7 @@ def _iter_shard_regions(
27302747
self, origin: Sequence[int] | None = None, selection_shape: Sequence[int] | None = None
27312748
) -> Iterator[tuple[slice, ...]]:
27322749
"""
2733-
Iterate over the regions spanned by each shard.
2750+
Iterate over the regions spanned by each shard or chunk if no shard is present.
27342751
27352752
Parameters
27362753
----------
@@ -2742,7 +2759,8 @@ def _iter_shard_regions(
27422759
Yields
27432760
------
27442761
tuple[slice, ...]
2745-
A tuple of slice objects representing the region spanned by each chunk in the selection.
2762+
A tuple of slice objects representing the region spanned by each shard or if no shard is present,
2763+
chunk in the selection.
27462764
"""
27472765
return self.async_array._iter_shard_regions(origin=origin, selection_shape=selection_shape)
27482766

@@ -4275,7 +4293,9 @@ async def _shards_initialized(
42754293
array: AnyAsyncArray,
42764294
) -> tuple[str, ...]:
42774295
"""
4278-
Return the keys of the chunks that have been persisted to the storage backend.
4296+
Return the keys of the shards that have been persisted to the storage backend.
4297+
4298+
This will fall back to chunks in case no shards are present.
42794299
42804300
Parameters
42814301
----------
@@ -4285,7 +4305,7 @@ async def _shards_initialized(
42854305
Returns
42864306
-------
42874307
chunks_initialized : tuple[str, ...]
4288-
The keys of the chunks that have been initialized.
4308+
The keys of the shards or if these are not present, chunks that have been initialized.
42894309
42904310
Related
42914311
-------
@@ -5560,6 +5580,8 @@ def _iter_shard_coords(
55605580
If the `selection_shape` keyword is used, iteration will be bounded over a contiguous region
55615581
ranging from `[origin, origin selection_shape]`, where the upper bound is exclusive as
55625582
per python indexing conventions.
5583+
If no shards are present this will iterate over the coordinates of chunks in chunk grid space
5584+
instead.
55635585
55645586
Parameters
55655587
----------
@@ -5573,7 +5595,7 @@ def _iter_shard_coords(
55735595
Yields
55745596
------
55755597
chunk_coords: tuple[int, ...]
5576-
The coordinates of each shard in the selection.
5598+
The coordinates of each shard in the selection or chunks if no shards are present.
55775599
"""
55785600
return _iter_grid(array._shard_grid_shape, origin=origin, selection_shape=selection_shape)
55795601

@@ -5588,6 +5610,8 @@ def _iter_shard_keys(
55885610
Iterate over the storage keys of each shard, relative to an optional origin, and optionally
55895611
limited to a contiguous region in shard grid coordinates.
55905612
5613+
This automatically falls back to chunks when no shards are present.
5614+
55915615
Parameters
55925616
----------
55935617
array : Array | AsyncArray
@@ -5600,7 +5624,7 @@ def _iter_shard_keys(
56005624
Yields
56015625
------
56025626
key: str
5603-
The storage key of each chunk in the selection.
5627+
The storage key of each shard in the selection or chunk when no shards are present.
56045628
"""
56055629
# Iterate over the coordinates of chunks in chunk grid space.
56065630
_iter = _iter_grid(array._shard_grid_shape, origin=origin, selection_shape=selection_shape)
@@ -5616,7 +5640,8 @@ def _iter_shard_regions(
56165640
"""
56175641
Iterate over the regions spanned by each shard.
56185642
5619-
These are the smallest regions of the array that are safe to write concurrently.
5643+
These are the smallest regions of the array that are safe to write concurrently. When
5644+
no shards are present this will fall back to chunks.
56205645
56215646
Parameters
56225647
----------
@@ -5630,12 +5655,13 @@ def _iter_shard_regions(
56305655
Yields
56315656
------
56325657
region: tuple[slice, ...]
5633-
A tuple of slice objects representing the region spanned by each shard in the selection.
5658+
A tuple of slice objects representing the region spanned by each shard in the selection or chunk
56345659
56355660
Raises
56365661
------
56375662
NotImplementedError
56385663
If the array uses RectilinearChunkGrid (variable-sized chunks).
5664+
when no shards are present.
56395665
"""
56405666
chunks = array.chunks
56415667
if not isinstance(chunks, RegularChunks):

src/zarr/core/common.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
ChunkCoords = tuple[int, ...]
4343
ZarrFormat = Literal[2, 3]
4444
NodeType = Literal["array", "group"]
45-
JSON = str | int | float | Mapping[str, "JSON"] | Sequence["JSON"] | None
45+
JSON = str | int | float | bool | Mapping[str, "JSON"] | Sequence["JSON"] | None
4646
MemoryOrder = Literal["C", "F"]
4747
AccessModeLiteral = Literal["r", "r+", "a", "w", "w-"]
4848
ANY_ACCESS_MODE: Final = "r", "r+", "a", "w", "w-"

tests/test_metadata/test_v2.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,12 +309,13 @@ def test_from_dict_extra_fields() -> None:
309309

310310

311311
def test_zstd_checksum() -> None:
312+
compressor_config: dict[str, JSON] = {"id": "zstd", "level": 5, "checksum": False}
312313
arr = zarr.create_array(
313314
{},
314315
shape=(10,),
315316
chunks=(10,),
316317
dtype="int32",
317-
compressors={"id": "zstd", "level": 5, "checksum": False},
318+
compressors=compressor_config,
318319
zarr_format=2,
319320
)
320321
metadata = json.loads(

0 commit comments

Comments
 (0)