Skip to content

Commit 2a02052

Browse files
Display data returned in apply_ufunc error message (#8179)
* Display data returned in ufunc error message This makes debugging much easier! * Use `short_array_repr` * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 756eee6 commit 2a02052

File tree

3 files changed

+27
-16
lines changed

3 files changed

+27
-16
lines changed

xarray/core/computation.py

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,7 @@ def apply_variable_ufunc(
659659
dask_gufunc_kwargs=None,
660660
) -> Variable | tuple[Variable, ...]:
661661
"""Apply a ndarray level function over Variable and/or ndarray objects."""
662+
from xarray.core.formatting import short_array_repr
662663
from xarray.core.variable import Variable, as_compatible_data
663664

664665
dim_sizes = unified_dim_sizes(
@@ -766,11 +767,10 @@ def func(*arrays):
766767
not isinstance(result_data, tuple) or len(result_data) != signature.num_outputs
767768
):
768769
raise ValueError(
769-
"applied function does not have the number of "
770-
"outputs specified in the ufunc signature. "
771-
"Result is not a tuple of {} elements: {!r}".format(
772-
signature.num_outputs, result_data
773-
)
770+
f"applied function does not have the number of "
771+
f"outputs specified in the ufunc signature. "
772+
f"Result is not a tuple of {signature.num_outputs} elements:\n\n"
773+
f"{short_array_repr(result_data)}"
774774
)
775775

776776
objs = _all_of_type(args, Variable)
@@ -784,21 +784,22 @@ def func(*arrays):
784784
data = as_compatible_data(data)
785785
if data.ndim != len(dims):
786786
raise ValueError(
787-
"applied function returned data with unexpected "
787+
"applied function returned data with an unexpected "
788788
f"number of dimensions. Received {data.ndim} dimension(s) but "
789-
f"expected {len(dims)} dimensions with names: {dims!r}"
789+
f"expected {len(dims)} dimensions with names {dims!r}, from:\n\n"
790+
f"{short_array_repr(data)}"
790791
)
791792

792793
var = Variable(dims, data, fastpath=True)
793794
for dim, new_size in var.sizes.items():
794795
if dim in dim_sizes and new_size != dim_sizes[dim]:
795796
raise ValueError(
796-
"size of dimension {!r} on inputs was unexpectedly "
797-
"changed by applied function from {} to {}. Only "
797+
f"size of dimension '{dim}' on inputs was unexpectedly "
798+
f"changed by applied function from {dim_sizes[dim]} to {new_size}. Only "
798799
"dimensions specified in ``exclude_dims`` with "
799-
"xarray.apply_ufunc are allowed to change size.".format(
800-
dim, dim_sizes[dim], new_size
801-
)
800+
"xarray.apply_ufunc are allowed to change size. "
801+
"The data returned was:\n\n"
802+
f"{short_array_repr(data)}"
802803
)
803804

804805
var.attrs = attrs

xarray/core/formatting.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from datetime import datetime, timedelta
1111
from itertools import chain, zip_longest
1212
from reprlib import recursive_repr
13+
from typing import TYPE_CHECKING
1314

1415
import numpy as np
1516
import pandas as pd
@@ -21,6 +22,9 @@
2122
from xarray.core.pycompat import array_type
2223
from xarray.core.utils import is_duck_array
2324

25+
if TYPE_CHECKING:
26+
from xarray.core.coordinates import AbstractCoordinates
27+
2428

2529
def pretty_print(x, numchars: int):
2630
"""Given an object `x`, call `str(x)` and format the returned string so
@@ -398,7 +402,7 @@ def _mapping_repr(
398402
)
399403

400404

401-
def coords_repr(coords, col_width=None, max_rows=None):
405+
def coords_repr(coords: AbstractCoordinates, col_width=None, max_rows=None):
402406
if col_width is None:
403407
col_width = _calculate_col_width(coords)
404408
return _mapping_repr(
@@ -412,7 +416,7 @@ def coords_repr(coords, col_width=None, max_rows=None):
412416
)
413417

414418

415-
def inline_index_repr(index, max_width=None):
419+
def inline_index_repr(index: pd.Index, max_width=None):
416420
if hasattr(index, "_repr_inline_"):
417421
repr_ = index._repr_inline_(max_width=max_width)
418422
else:

xarray/tests/test_computation.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1666,7 +1666,10 @@ def identity(x):
16661666
def tuple3x(x):
16671667
return (x, x, x)
16681668

1669-
with pytest.raises(ValueError, match=r"number of outputs"):
1669+
with pytest.raises(
1670+
ValueError,
1671+
match=r"number of outputs.*Result is not a tuple of 2 elements:\n\narray\(\[0",
1672+
):
16701673
apply_ufunc(identity, variable, output_core_dims=[(), ()])
16711674

16721675
with pytest.raises(ValueError, match=r"number of outputs"):
@@ -1682,7 +1685,10 @@ def add_dim(x):
16821685
def remove_dim(x):
16831686
return x[..., 0]
16841687

1685-
with pytest.raises(ValueError, match=r"unexpected number of dimensions"):
1688+
with pytest.raises(
1689+
ValueError,
1690+
match=r"unexpected number of dimensions.*from:\n\n.*array\(\[\[0",
1691+
):
16861692
apply_ufunc(add_dim, variable, output_core_dims=[("y", "z")])
16871693

16881694
with pytest.raises(ValueError, match=r"unexpected number of dimensions"):

0 commit comments

Comments
 (0)