From 41aa357f913bf8c7fae92831176e8b2c483a7e32 Mon Sep 17 00:00:00 2001 From: Keewis Date: Wed, 22 Jul 2020 16:37:01 +0200 Subject: [PATCH 01/11] call the duck array's _repr_short_ method if it exists --- xarray/core/formatting.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xarray/core/formatting.py b/xarray/core/formatting.py index 28eaae5f05b..23c357a23b0 100644 --- a/xarray/core/formatting.py +++ b/xarray/core/formatting.py @@ -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_short_"): + return var._data._repr_short_(max_width) elif hasattr(var._data, "__array_function__"): return maybe_truncate(repr(var._data).replace("\n", " "), max_width) else: From 0d42e58cc11a2128aedb250c4c800f77a6007c5e Mon Sep 17 00:00:00 2001 From: Keewis Date: Mon, 3 Aug 2020 11:09:57 +0200 Subject: [PATCH 02/11] rename to _repr_inline_ --- xarray/core/formatting.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xarray/core/formatting.py b/xarray/core/formatting.py index 23c357a23b0..9aa20f2b87e 100644 --- a/xarray/core/formatting.py +++ b/xarray/core/formatting.py @@ -261,8 +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_short_"): - return var._data._repr_short_(max_width) + 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: From b6814041d8c6a77b031ea9328fab636140a4b551 Mon Sep 17 00:00:00 2001 From: Keewis Date: Thu, 6 Aug 2020 01:04:42 +0200 Subject: [PATCH 03/11] add a crude test to make sure the object's _repr_inline_ is called --- xarray/tests/test_formatting.py | 37 +++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/xarray/tests/test_formatting.py b/xarray/tests/test_formatting.py index 82de8080c80..dd1872bb146 100644 --- a/xarray/tests/test_formatting.py +++ b/xarray/tests/test_formatting.py @@ -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): From 3635ff64a697df13cf2f805809407fdc6ad67c8a Mon Sep 17 00:00:00 2001 From: Keewis Date: Thu, 6 Aug 2020 01:24:36 +0200 Subject: [PATCH 04/11] add a section about duck arrays --- doc/internals.rst | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/doc/internals.rst b/doc/internals.rst index 46c117e312b..a4576f8278e 100644 --- a/doc/internals.rst +++ b/doc/internals.rst @@ -42,6 +42,37 @@ xarray objects via the (readonly) :py:attr:`Dataset.variables ` and :py:attr:`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 ---------------- From fd8e9f0f29c7b987dfe7dbe6678a9da6d54e907e Mon Sep 17 00:00:00 2001 From: Keewis Date: Thu, 6 Aug 2020 01:43:09 +0200 Subject: [PATCH 05/11] update whats-new.rst --- doc/whats-new.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/whats-new.rst b/doc/whats-new.rst index 81ef2cd9e17..c8e923cd233 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -29,6 +29,9 @@ New Features property for :py:class:`CFTimeIndex` and show ``calendar`` and ``length`` in :py:meth:`CFTimeIndex.__repr__` (:issue:`2416`, :pull:`4092`) `Aaron Spring `_. +- Use a wrapped array's ``_repr_inline_`` method to construct the collapsed ``repr`` + of :py:class:`DataArray` and :py:class:`Dataset` objects. (:pull:`4248`). + By `Justus Magin `_. Bug fixes From 2b311313a635394102620adeff29da4e6ad82852 Mon Sep 17 00:00:00 2001 From: Keewis Date: Thu, 6 Aug 2020 01:43:39 +0200 Subject: [PATCH 06/11] fix a link --- doc/internals.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/internals.rst b/doc/internals.rst index a4576f8278e..5931e1d1e97 100644 --- a/doc/internals.rst +++ b/doc/internals.rst @@ -70,7 +70,7 @@ certain number of characters. If that would drop too much information, the ... -.. _duck arrays: https://numpy.org/neps/nep-0022-ndarray-duck-typing-overview.html +.. _duck array: https://numpy.org/neps/nep-0022-ndarray-duck-typing-overview.html Extending xarray From 5cd757b46527b7d3f00035953495c90b1ebb7c79 Mon Sep 17 00:00:00 2001 From: Keewis Date: Thu, 6 Aug 2020 01:46:58 +0200 Subject: [PATCH 07/11] make sure the tests are not run without support for NEP18 --- xarray/tests/test_formatting.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xarray/tests/test_formatting.py b/xarray/tests/test_formatting.py index dd1872bb146..1cc91266421 100644 --- a/xarray/tests/test_formatting.py +++ b/xarray/tests/test_formatting.py @@ -7,6 +7,7 @@ import xarray as xr from xarray.core import formatting +from xarray.core.npcompat import IS_NEP18_ACTIVE from . import raises_regex @@ -391,6 +392,7 @@ def test_array_repr(self): assert actual == expected +@pytest.mark.skipif(not IS_NEP18_ACTIVE, reason="requires __array_function__") def test_inline_variable_array_repr_custom_repr(): class CustomArray: def __init__(self, value, attr): From ccc9054fe6173e6f97810f20f80d127e895e898a Mon Sep 17 00:00:00 2001 From: Keewis Date: Thu, 6 Aug 2020 02:02:49 +0200 Subject: [PATCH 08/11] move the explanation for max_width into the text block --- doc/internals.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/internals.rst b/doc/internals.rst index 5931e1d1e97..91eec72b521 100644 --- a/doc/internals.rst +++ b/doc/internals.rst @@ -53,10 +53,12 @@ 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: +In certain situations (e.g. when printing the collapsed preview of +variables of a ``Dataset``), xarray will display the repr of a `duck array`_ +in a single line, truncating it to a certain number of characters. If that +would drop too much information, the `duck array`_ may define a +``_repr_inline_`` method that takes ``max_width`` (number of characters) as an +argument: .. code:: python @@ -64,8 +66,6 @@ certain number of characters. If that would drop too much information, the ... def _repr_inline_(self, max_width): - """ display the array in a single line with max_width characters """ - ... ... From 97977c27df8b5370baf50f5bf5636d7f93172eba Mon Sep 17 00:00:00 2001 From: Keewis Date: Thu, 6 Aug 2020 02:04:29 +0200 Subject: [PATCH 09/11] use double instead of single quotes --- doc/internals.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/internals.rst b/doc/internals.rst index 91eec72b521..298ac4b01e3 100644 --- a/doc/internals.rst +++ b/doc/internals.rst @@ -50,8 +50,8 @@ Duck arrays 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. +``shape``, ``dtype`` and ``ndim`` properties and the ``__array__``, +``__array_ufunc__`` and ``__array_function__`` methods. In certain situations (e.g. when printing the collapsed preview of variables of a ``Dataset``), xarray will display the repr of a `duck array`_ From 6ebf3ae8e8e1c6c7871473a865d074c649187ba7 Mon Sep 17 00:00:00 2001 From: Keewis Date: Thu, 6 Aug 2020 02:11:14 +0200 Subject: [PATCH 10/11] add back the docstring --- doc/internals.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/internals.rst b/doc/internals.rst index 298ac4b01e3..b158f12ac6d 100644 --- a/doc/internals.rst +++ b/doc/internals.rst @@ -66,6 +66,7 @@ argument: ... def _repr_inline_(self, max_width): + """ format to a single line with at most max_width characters """ ... ... From f6161f3e45ed5200efa1d885a79c49480a3719fd Mon Sep 17 00:00:00 2001 From: Keewis Date: Thu, 6 Aug 2020 02:12:12 +0200 Subject: [PATCH 11/11] link to internals in whats-new.rst --- doc/whats-new.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/whats-new.rst b/doc/whats-new.rst index c8e923cd233..573583f0de3 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -30,7 +30,8 @@ New Features :py:meth:`CFTimeIndex.__repr__` (:issue:`2416`, :pull:`4092`) `Aaron Spring `_. - Use a wrapped array's ``_repr_inline_`` method to construct the collapsed ``repr`` - of :py:class:`DataArray` and :py:class:`Dataset` objects. (:pull:`4248`). + of :py:class:`DataArray` and :py:class:`Dataset` objects and + document the new method in :doc:`internals`. (:pull:`4248`). By `Justus Magin `_.