From 58b1786fd03414d1c920cf1e19956a34bf5cfc90 Mon Sep 17 00:00:00 2001 From: jakirkham Date: Tue, 12 Nov 2019 13:56:33 -0500 Subject: [PATCH] Use `ensure_ndarray` in a few more places (#506) * Use `ensure_ndarray` to check `chunk`'s type Instead of checking to see if `chunk` is an `ndarray`, use `ensure_ndarray` to get an `ndarray` viewing the underlying data in `chunk`. This way we know attributes like `dtype` are available and can be checked easily. Also makes this a bit more friendly with other array-like types. * Use `ensure_ndarray` on `out` Since we are interested in getting an `ndarray` representing the buffer within `out` for writing into, go ahead and use `ensure_ndarray` to coerce the underlying buffer into an `ndarray`. This way we can avoid a needless check and just write into any array-like value for `out` that is provided. * Handle `out` when it doesn't supply a buffer Appears that `out` can also be a Zarr `Array` or any other array-like that does not expose a buffer, but does allow writing into. In these cases `ensure_ndarray` will fail as there is not an underlying buffer that can be used with an `ndarray`. To also handle this case, catch the `TypeError` that `ensure_ndarray` will raise in this case and use that to indicate whether `out` is now an `ndarray` or not. This allows us to continue to write into arbitrary buffers, but also correctly handle objects that do not expose buffers. * Adds release notes entry --- docs/release.rst | 3 +++ zarr/core.py | 10 ++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/release.rst b/docs/release.rst index 42297edc3..5dd91c5e2 100644 --- a/docs/release.rst +++ b/docs/release.rst @@ -40,6 +40,9 @@ Upcoming Release * Use ``math.ceil`` for scalars. By :user:`John Kirkham `; :issue:`500`. +* Use ``ensure_ndarray`` in a few more places. + By :user:`John Kirkham `; :issue:`506`. + * Refactor out ``_tofile``/``_fromfile`` from ``DirectoryStore``. By :user:`John Kirkham `; :issue:`503`. diff --git a/zarr/core.py b/zarr/core.py index 0df9f4b8d..a922dac0e 100644 --- a/zarr/core.py +++ b/zarr/core.py @@ -1572,6 +1572,12 @@ def _chunk_getitem(self, chunk_coords, chunk_selection, out, out_selection, assert len(chunk_coords) == len(self._cdata_shape) + out_is_ndarray = True + try: + out = ensure_ndarray(out) + except TypeError: + out_is_ndarray = False + # obtain key for chunk ckey = self._chunk_key(chunk_coords) @@ -1590,7 +1596,7 @@ def _chunk_getitem(self, chunk_coords, chunk_selection, out, out_selection, else: - if (isinstance(out, np.ndarray) and + if (out_is_ndarray and not fields and is_contiguous_selection(out_selection) and is_total_slice(chunk_selection, self._chunks) and @@ -1769,7 +1775,7 @@ def _encode_chunk(self, chunk): chunk = f.encode(chunk) # check object encoding - if isinstance(chunk, np.ndarray) and chunk.dtype == object: + if ensure_ndarray(chunk).dtype == object: raise RuntimeError('cannot write object array without object codec') # compress