Skip to content

Commit 8bb79ef

Browse files
authored
Merge branch 'main' into sharding-storage-transformer
2 parents 1ccf052 + 1793da0 commit 8bb79ef

File tree

5 files changed

+79
-8
lines changed

5 files changed

+79
-8
lines changed

docs/release.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ Unreleased
1414
# .. warning::
1515
# Pre-release! Use :command:`pip install --pre zarr` to evaluate this release.
1616
17+
Major changes
18+
~~~~~~~~~~~~~
19+
1720
* Improve Zarr V3 support, adding partial store read/write and storage transformers.
1821
Add two features of the [v3 spec](https://zarr-specs.readthedocs.io/en/latest/core/v3.0.html):
1922
* storage transformers
@@ -22,6 +25,13 @@ Unreleased
2225
* sharding storage transformer
2326
By :user:`Jonathan Striebel <jstriebel>`; :issue:`1096`, :issue:`1111`.
2427

28+
29+
Bug fixes
30+
~~~~~~~~~
31+
32+
* Ensure contiguous data is give to ``FSStore``. Only copying if needed.
33+
By :user:`Mads R. B. Kristensen <madsbk>` :issue:`1285`.
34+
2535
.. _release_2.13.6:
2636

2737
2.13.6

requirements_dev_optional.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@ pytest-cov==4.0.0
1818
pytest-doctestplus==0.12.1
1919
pytest-timeout==2.1.0
2020
h5py==3.7.0
21-
fsspec==2022.11.0
22-
s3fs==2022.11.0
21+
fsspec==2023.1.0
22+
s3fs==2023.1.0
2323
moto[server]>=4.0.8

zarr/storage.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@
5555
from zarr.util import (buffer_size, json_loads, nolock, normalize_chunks,
5656
normalize_dimension_separator,
5757
normalize_dtype, normalize_fill_value, normalize_order,
58-
normalize_shape, normalize_storage_path, retry_call
59-
)
58+
normalize_shape, normalize_storage_path, retry_call,
59+
ensure_contiguous_ndarray_or_bytes)
6060

6161
from zarr._storage.absstore import ABSStore # noqa: F401
6262
from zarr._storage.store import (_get_hierarchy_metadata, # noqa: F401
@@ -1395,13 +1395,19 @@ def __getitem__(self, key):
13951395
def setitems(self, values):
13961396
if self.mode == 'r':
13971397
raise ReadOnlyError()
1398-
values = {self._normalize_key(key): val for key, val in values.items()}
1398+
1399+
# Normalize keys and make sure the values are bytes
1400+
values = {
1401+
self._normalize_key(key): ensure_contiguous_ndarray_or_bytes(val)
1402+
for key, val in values.items()
1403+
}
13991404
self.map.setitems(values)
14001405

14011406
def __setitem__(self, key, value):
14021407
if self.mode == 'r':
14031408
raise ReadOnlyError()
14041409
key = self._normalize_key(key)
1410+
value = ensure_contiguous_ndarray_or_bytes(value)
14051411
path = self.dir_path(key)
14061412
try:
14071413
if self.fs.isdir(path):

zarr/tests/test_core.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from numpy.testing import assert_array_almost_equal, assert_array_equal
1818
from pkg_resources import parse_version
1919

20+
import zarr
2021
from zarr._storage.store import (
2122
v3_api_available,
2223
)
@@ -3520,3 +3521,27 @@ def test_array_mismatched_store_versions():
35203521
Array(store_v3, path='dataset', read_only=False, chunk_store=chunk_store_v2)
35213522
with pytest.raises(ValueError):
35223523
Array(store_v2, path='dataset', read_only=False, chunk_store=chunk_store_v3)
3524+
3525+
3526+
@pytest.mark.skipif(have_fsspec is False, reason="needs fsspec")
3527+
def test_issue_1279(tmpdir):
3528+
"""See <https://github.com/zarr-developers/zarr-python/issues/1279>"""
3529+
3530+
data = np.arange(25).reshape((5, 5))
3531+
ds = zarr.create(
3532+
shape=data.shape,
3533+
chunks=(5, 5),
3534+
dtype=data.dtype,
3535+
compressor=(None),
3536+
store=FSStore(url=str(tmpdir), mode="a"),
3537+
order="F",
3538+
)
3539+
3540+
ds[:] = data
3541+
3542+
ds_reopened = zarr.open_array(
3543+
store=FSStore(url=str(tmpdir), mode="r")
3544+
)
3545+
3546+
written_data = ds_reopened[:]
3547+
assert_array_equal(data, written_data)

zarr/util.py

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,22 @@
55
from textwrap import TextWrapper
66
import mmap
77
import time
8+
from typing import Any, Callable, Dict, Optional, Tuple, Union
89

910
import numpy as np
1011
from asciitree import BoxStyle, LeftAligned
1112
from asciitree.traversal import Traversal
1213
from collections.abc import Iterable
13-
from numcodecs.compat import ensure_text, ensure_ndarray_like
14+
from numcodecs.compat import (
15+
ensure_text,
16+
ensure_ndarray_like,
17+
ensure_bytes,
18+
ensure_contiguous_ndarray_like
19+
)
20+
from numcodecs.ndarray_like import NDArrayLike
1421
from numcodecs.registry import codec_registry
1522
from numcodecs.blosc import cbuffer_sizes, cbuffer_metainfo
1623

17-
from typing import Any, Callable, Dict, Optional, Tuple, Union
18-
1924

2025
def flatten(arg: Iterable) -> Iterable:
2126
for element in arg:
@@ -715,3 +720,28 @@ def all_equal(value: Any, array: Any):
715720
# using == raises warnings from numpy deprecated pattern, but
716721
# using np.equal() raises type errors for structured dtypes...
717722
return np.all(value == array)
723+
724+
725+
def ensure_contiguous_ndarray_or_bytes(buf) -> Union[NDArrayLike, bytes]:
726+
"""Convenience function to coerce `buf` to ndarray-like array or bytes.
727+
728+
First check if `buf` can be zero-copy converted to a contiguous array.
729+
If not, `buf` will be copied to a newly allocated `bytes` object.
730+
731+
Parameters
732+
----------
733+
buf : ndarray-like, array-like, or bytes-like
734+
A numpy array like object such as numpy.ndarray, cupy.ndarray, or
735+
any object exporting a buffer interface.
736+
737+
Returns
738+
-------
739+
arr : NDArrayLike or bytes
740+
A ndarray-like or bytes object
741+
"""
742+
743+
try:
744+
return ensure_contiguous_ndarray_like(buf)
745+
except TypeError:
746+
# An error is raised if `buf` couldn't be zero-copy converted
747+
return ensure_bytes(buf)

0 commit comments

Comments
 (0)