Skip to content

Commit 0ab320e

Browse files
authored
Merge branch 'main' into doc/update-contributor-guide
2 parents ae4ac1a + ae6e8e6 commit 0ab320e

File tree

20 files changed

+769
-503
lines changed

20 files changed

+769
-503
lines changed

.github/workflows/test.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,22 @@ jobs:
9393
- name: Run Tests
9494
run: |
9595
hatch env run --env ${{ matrix.dependency-set }} run
96+
97+
test-complete:
98+
name: Test complete
99+
100+
needs:
101+
[
102+
test,
103+
test-upstream-and-min-deps,
104+
]
105+
if: always()
106+
runs-on: ubuntu-latest
107+
steps:
108+
- name: Check failure
109+
if: |
110+
contains(needs.*.result, 'failure') ||
111+
contains(needs.*.result, 'cancelled')
112+
run: exit 1
113+
- name: Success
114+
run: echo Success!

.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.8.0
10+
rev: v0.8.1
1111
hooks:
1212
- id: ruff
1313
args: ["--fix", "--show-fixes"]

pyproject.toml

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ gpu = [
8181
docs = [
8282
'sphinx==8.1.3',
8383
'sphinx-autobuild>=2021.3.14',
84-
'sphinx-autoapi==3.3.3',
84+
'sphinx-autoapi==3.4.0',
8585
'sphinx_design',
8686
'sphinx-issues',
8787
'sphinx-copybutton',
@@ -294,19 +294,14 @@ extend-select = [
294294
"W", # pycodestyle warnings
295295
]
296296
ignore = [
297-
"ANN101", # deprecated
298-
"ANN102", # deprecated
299297
"ANN401",
300-
"PT004", # deprecated
301-
"PT005", # deprecated
302298
"PT011", # TODO: apply this rule
303299
"PT012", # TODO: apply this rule
304300
"RET505",
305301
"RET506",
306302
"RUF005",
307303
"SIM108",
308304
"TRY003",
309-
"UP027", # deprecated
310305
"UP038", # https://github.com/astral-sh/ruff/issues/7871
311306
# https://docs.astral.sh/ruff/formatter/#conflicting-lint-rules
312307
"W191",
@@ -347,6 +342,7 @@ ignore_errors = true
347342

348343
[[tool.mypy.overrides]]
349344
module = [
345+
"zarr.testing.stateful", # lots of hypothesis decorator errors
350346
"tests.package_with_entrypoint.*",
351347
"tests.test_codecs.test_codecs",
352348
"tests.test_codecs.test_transpose",

src/zarr/api/asynchronous.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -653,12 +653,12 @@ async def open_group(
653653
Store or path to directory in file system or name of zip file.
654654
655655
Strings are interpreted as paths on the local file system
656-
and used as the ``root`` argument to :class:`zarr.store.LocalStore`.
656+
and used as the ``root`` argument to :class:`zarr.storage.LocalStore`.
657657
658658
Dictionaries are used as the ``store_dict`` argument in
659-
:class:`zarr.store.MemoryStore``.
659+
:class:`zarr.storage.MemoryStore``.
660660
661-
By default (``store=None``) a new :class:`zarr.store.MemoryStore`
661+
By default (``store=None``) a new :class:`zarr.storage.MemoryStore`
662662
is created.
663663
664664
mode : {'r', 'r+', 'a', 'w', 'w-'}, optional

src/zarr/codecs/_v2.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from typing import TYPE_CHECKING
66

77
import numcodecs
8-
from numcodecs.compat import ensure_ndarray_like
8+
from numcodecs.compat import ensure_bytes, ensure_ndarray_like
99

1010
from zarr.abc.codec import ArrayBytesCodec
1111
from zarr.registry import get_ndbuffer_class
@@ -68,6 +68,9 @@ async def _encode_single(
6868
) -> Buffer | None:
6969
chunk = chunk_array.as_ndarray_like()
7070

71+
# ensure contiguous and correct order
72+
chunk = chunk.astype(chunk_spec.dtype, order=chunk_spec.order, copy=False)
73+
7174
# apply filters
7275
if self.filters:
7376
for f in self.filters:
@@ -83,6 +86,7 @@ async def _encode_single(
8386
else:
8487
cdata = chunk
8588

89+
cdata = ensure_bytes(cdata)
8690
return chunk_spec.prototype.buffer.from_bytes(cdata)
8791

8892
def compute_encoded_size(self, _input_byte_length: int, _chunk_spec: ArraySpec) -> int:

src/zarr/core/array.py

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1346,18 +1346,53 @@ def info(self) -> Any:
13461346
AsyncArray.info_complete
13471347
All information about a group, including dynamic information
13481348
like the number of bytes and chunks written.
1349+
1350+
Examples
1351+
--------
1352+
1353+
>>> arr = await zarr.api.asynchronous.create(
1354+
... path="array", shape=(3, 4, 5), chunks=(2, 2, 2))
1355+
... )
1356+
>>> arr.info
1357+
Type : Array
1358+
Zarr format : 3
1359+
Data type : DataType.float64
1360+
Shape : (3, 4, 5)
1361+
Chunk shape : (2, 2, 2)
1362+
Order : C
1363+
Read-only : False
1364+
Store type : MemoryStore
1365+
Codecs : [{'endian': <Endian.little: 'little'>}]
1366+
No. bytes : 480
13491367
"""
13501368
return self._info()
13511369

13521370
async def info_complete(self) -> Any:
1353-
# TODO: get the size of the object from the store.
1354-
extra = {
1355-
"count_chunks_initialized": await self.nchunks_initialized(),
1356-
# count_bytes_stored isn't yet implemented.
1357-
}
1358-
return self._info(extra=extra)
1359-
1360-
def _info(self, extra: dict[str, int] | None = None) -> Any:
1371+
"""
1372+
Return all the information for an array, including dynamic information like a storage size.
1373+
1374+
In addition to the static information, this provides
1375+
1376+
- The count of chunks initialized
1377+
- The sum of the bytes written
1378+
1379+
Returns
1380+
-------
1381+
ArrayInfo
1382+
1383+
See Also
1384+
--------
1385+
AsyncArray.info
1386+
A property giving just the statically known information about an array.
1387+
"""
1388+
return self._info(
1389+
await self.nchunks_initialized(),
1390+
await self.store_path.store.getsize_prefix(self.store_path.path),
1391+
)
1392+
1393+
def _info(
1394+
self, count_chunks_initialized: int | None = None, count_bytes_stored: int | None = None
1395+
) -> Any:
13611396
kwargs: dict[str, Any] = {}
13621397
if self.metadata.zarr_format == 2:
13631398
assert isinstance(self.metadata, ArrayV2Metadata)
@@ -1386,6 +1421,8 @@ def _info(self, extra: dict[str, int] | None = None) -> Any:
13861421
_read_only=self.read_only,
13871422
_store_type=type(self.store_path.store).__name__,
13881423
_count_bytes=self.dtype.itemsize * self.size,
1424+
_count_bytes_stored=count_bytes_stored,
1425+
_count_chunks_initialized=count_chunks_initialized,
13891426
**kwargs,
13901427
)
13911428

@@ -2844,6 +2881,14 @@ def set_coordinate_selection(
28442881
if hasattr(value, "shape") and len(value.shape) > 1:
28452882
value = np.array(value).reshape(-1)
28462883

2884+
if not is_scalar(value, self.dtype) and (
2885+
isinstance(value, NDArrayLike) and indexer.shape != value.shape
2886+
):
2887+
raise ValueError(
2888+
f"Attempting to set a selection of {indexer.sel_shape[0]} "
2889+
f"elements with an array of {value.shape[0]} elements."
2890+
)
2891+
28472892
sync(self._async_array._set_selection(indexer, value, fields=fields, prototype=prototype))
28482893

28492894
@_deprecate_positional_args

src/zarr/core/buffer/core.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,13 @@ def reshape(
8080

8181
def view(self, dtype: npt.DTypeLike) -> Self: ...
8282

83-
def astype(self, dtype: npt.DTypeLike, order: Literal["K", "A", "C", "F"] = ...) -> Self: ...
83+
def astype(
84+
self,
85+
dtype: npt.DTypeLike,
86+
order: Literal["K", "A", "C", "F"] = ...,
87+
*,
88+
copy: bool = ...,
89+
) -> Self: ...
8490

8591
def fill(self, value: Any) -> None: ...
8692

src/zarr/core/group.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,7 @@ async def from_store(
434434
async def open(
435435
cls,
436436
store: StoreLike,
437-
zarr_format: Literal[2, 3, None] = 3,
437+
zarr_format: Literal[2, 3] | None = 3,
438438
use_consolidated: bool | str | None = None,
439439
) -> AsyncGroup:
440440
"""Open a new AsyncGroup
@@ -1691,7 +1691,7 @@ def from_store(
16911691
def open(
16921692
cls,
16931693
store: StoreLike,
1694-
zarr_format: Literal[2, 3, None] = 3,
1694+
zarr_format: Literal[2, 3] | None = 3,
16951695
) -> Group:
16961696
"""Open a group from an initialized store.
16971697

src/zarr/core/indexing.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1346,8 +1346,15 @@ def decode_morton(z: int, chunk_shape: ChunkCoords) -> ChunkCoords:
13461346

13471347

13481348
def morton_order_iter(chunk_shape: ChunkCoords) -> Iterator[ChunkCoords]:
1349-
for i in range(product(chunk_shape)):
1350-
yield decode_morton(i, chunk_shape)
1349+
i = 0
1350+
order: list[ChunkCoords] = []
1351+
while len(order) < product(chunk_shape):
1352+
m = decode_morton(i, chunk_shape)
1353+
if m not in order and all(x < y for x, y in zip(m, chunk_shape, strict=False)):
1354+
order.append(m)
1355+
i += 1
1356+
for j in range(product(chunk_shape)):
1357+
yield order[j]
13511358

13521359

13531360
def c_order_iter(chunks_per_shard: ChunkCoords) -> Iterator[ChunkCoords]:

src/zarr/storage/common.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@
1212
from zarr.storage.local import LocalStore
1313
from zarr.storage.memory import MemoryStore
1414

15-
# from zarr.store.remote import RemoteStore
16-
1715
if TYPE_CHECKING:
1816
from zarr.core.buffer import BufferPrototype
1917

0 commit comments

Comments
 (0)