Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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
31 changes: 31 additions & 0 deletions doc/internals.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,37 @@ xarray objects via the (readonly) :py:attr:`Dataset.variables
<xarray.Dataset.variables>` and
:py:attr:`DataArray.variable <xarray.DataArray.variable>` attributes.

Duck arrays
-----------

.. warning::

This is a experimental feature.

xarray can wrap custom `duck array`_ objects as long as they define numpy's
`shape`, `dtype` and `ndim` properties and the `__array__`, `__array_ufunc__`
and `__array_function__` methods.

In certain situations (e.g. when printing the variables of ``Dataset``), xarray
will display the repr of a `duck array`_ in a single line, limiting it to a
certain number of characters. If that would drop too much information, the
`duck array`_ may define a ``_repr_inline_`` method:

.. code:: python

class MyDuckArray:
...

def _repr_inline_(self, max_width):
""" display the array in a single line with max_width characters """

...

...

.. _duck arrays: https://numpy.org/neps/nep-0022-ndarray-duck-typing-overview.html


Extending xarray
----------------

Expand Down
2 changes: 2 additions & 0 deletions xarray/core/formatting.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,8 @@ def inline_variable_array_repr(var, max_width):
return inline_dask_repr(var.data)
elif isinstance(var._data, sparse_array_type):
return inline_sparse_repr(var.data)
elif hasattr(var._data, "_repr_inline_"):
return var._data._repr_inline_(max_width)
elif hasattr(var._data, "__array_function__"):
return maybe_truncate(repr(var._data).replace("\n", " "), max_width)
else:
Expand Down
37 changes: 37 additions & 0 deletions xarray/tests/test_formatting.py
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,43 @@ def test_array_repr(self):
assert actual == expected


def test_inline_variable_array_repr_custom_repr():
class CustomArray:
def __init__(self, value, attr):
self.value = value
self.attr = attr

def _repr_inline_(self, width):
formatted = f"({self.attr}) {self.value}"
if len(formatted) > width:
formatted = f"({self.attr}) ..."

return formatted

def __array_function__(self, *args, **kwargs):
return NotImplemented

@property
def shape(self):
return self.value.shape

@property
def dtype(self):
return self.value.dtype

@property
def ndim(self):
return self.value.ndim

value = CustomArray(np.array([20, 40]), "m")
variable = xr.Variable("x", value)

max_width = 10
actual = formatting.inline_variable_array_repr(variable, max_width=10)

assert actual == value._repr_inline_(max_width)


def test_set_numpy_options():
original_options = np.get_printoptions()
with formatting.set_numpy_options(threshold=10):
Expand Down