Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions doc/whats-new.rst
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,12 @@ Bug Fixes

Documentation
~~~~~~~~~~~~~
- Clarified that :py:meth:`DataArray.item` and :py:meth:`Variable.item` are not
implemented for lazy (e.g. dask) arrays, both in the method docstring and in the
raised error message, which now suggests loading the data into memory first
(:issue:`7916`).
By `imam <https://github.com/imam2004i>`_.

- Add hidden intersphinx inventory entries for methods, properties and
attributes at the path where they are defined, e.g.
``xarray.core.dataarray.DataArray.sel``. This lets tools such as
Expand Down
19 changes: 18 additions & 1 deletion xarray/computation/ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,12 +126,29 @@ def _call_possibly_missing_method(arg, name, args, kwargs):
return method(*args, **kwargs)


# Note appended to the inherited NumPy docstring of ``item``, which is not
# implemented for lazy (e.g. dask) arrays, see
# duck_array_ops.fail_on_dask_array_input. Inserted before the "Parameters"
# section so it renders near the top of the method documentation.
_ITEM_DASK_NOTE = (
"\n.. note::\n"
" For xarray objects wrapping a lazy array such as a dask array,\n"
" ``item`` is not implemented and raises ``NotImplementedError``.\n"
" Load the data into memory first, for example with\n"
" ``obj.compute().item()`` or ``obj.as_numpy().item()``.\n"
)


def _values_method_wrapper(name):
def func(self, *args, **kwargs):
return _call_possibly_missing_method(self.data, name, args, kwargs)

func.__name__ = name
func.__doc__ = getattr(np.ndarray, name).__doc__
doc = getattr(np.ndarray, name).__doc__
if name == "item" and doc is not None:
anchor = "\nParameters\n"
doc = doc.replace(anchor, _ITEM_DASK_NOTE + anchor, 1)
func.__doc__ = doc
return func


Expand Down
5 changes: 4 additions & 1 deletion xarray/core/duck_array_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,10 @@ def f(*args, **kwargs):
def fail_on_dask_array_input(values, msg=None, func_name=None):
if is_duck_dask_array(values):
if msg is None:
msg = "%r is not yet a valid method on dask arrays"
msg = (
"%r is not yet a valid method on dask arrays. Load the data into "
"memory first, e.g. with '.compute()' or '.load()'."
)
if func_name is None:
func_name = inspect.stack()[1][3]
raise NotImplementedError(msg % func_name)
Expand Down
2 changes: 1 addition & 1 deletion xarray/tests/test_dask.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ def test_missing_methods(self):
v = self.lazy_var
with pytest.raises(NotImplementedError, match="dask"):
v.argsort()
with pytest.raises(NotImplementedError, match="dask"):
with pytest.raises(NotImplementedError, match="Load the data into memory"):
v[0].item() # type: ignore[attr-defined]

def test_univariate_ufunc(self):
Expand Down
Loading