Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

properly diff objects with arrays as attributes on variables #9169

Merged
merged 10 commits into from
Jun 30, 2024
Merged
3 changes: 2 additions & 1 deletion doc/whats-new.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ Deprecations

Bug fixes
~~~~~~~~~

- Allow diffing objects with array attributes on variables (:issue:`9153`, :pull:`9169`).
By `Justus Magin <https://github.com/keewis>`_.

Documentation
~~~~~~~~~~~~~
Expand Down
13 changes: 13 additions & 0 deletions properties/test_properties.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from hypothesis import given

import xarray as xr
import xarray.testing.strategies as xrst


@given(attrs=xrst.attrs())
def test_assert_identical(attrs):
v = xr.Variable(dims=(), data=0, attrs=attrs)
xr.testing.assert_identical(v, v)

ds = xr.Dataset(attrs=attrs)
xr.testing.assert_identical(ds, ds)
18 changes: 12 additions & 6 deletions xarray/core/formatting.py
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,12 @@ def _diff_mapping_repr(
a_indexes=None,
b_indexes=None,
):
def compare_attr(a, b):
if is_duck_array(a) or is_duck_array(b):
return array_equiv(a, b)
else:
return a == b

def extra_items_repr(extra_keys, mapping, ab_side, kwargs):
extra_repr = [
summarizer(k, mapping[k], col_width, **kwargs[k]) for k in extra_keys
Expand Down Expand Up @@ -801,11 +807,7 @@ def extra_items_repr(extra_keys, mapping, ab_side, kwargs):
is_variable = True
except AttributeError:
# compare attribute value
if is_duck_array(a_mapping[k]) or is_duck_array(b_mapping[k]):
compatible = array_equiv(a_mapping[k], b_mapping[k])
else:
compatible = a_mapping[k] == b_mapping[k]

compatible = compare_attr(a_mapping[k], b_mapping[k])
is_variable = False

if not compatible:
Expand All @@ -821,7 +823,11 @@ def extra_items_repr(extra_keys, mapping, ab_side, kwargs):

attrs_to_print = set(a_attrs) ^ set(b_attrs)
attrs_to_print.update(
{k for k in set(a_attrs) & set(b_attrs) if a_attrs[k] != b_attrs[k]}
{
k
for k in set(a_attrs) & set(b_attrs)
if not compare_attr(a_attrs[k], b_attrs[k])
}
)
for m in (a_mapping, b_mapping):
attr_s = "\n".join(
Expand Down
30 changes: 30 additions & 0 deletions xarray/tests/test_formatting.py
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,36 @@ def test_diff_attrs_repr_with_array(self) -> None:
actual = formatting.diff_attrs_repr(attrs_a, attrs_c, "equals")
assert expected == actual

def test__diff_mapping_repr_array_attrs_on_variables(self) -> None:
a = {
"a": xr.DataArray(
dims="x",
data=np.array([1], dtype="int16"),
attrs={"b": np.array([1, 2], dtype="int8")},
)
}
b = {
"a": xr.DataArray(
dims="x",
data=np.array([1], dtype="int16"),
attrs={"b": np.array([2, 3], dtype="int8")},
)
}
actual = formatting.diff_data_vars_repr(a, b, compat="identical", col_width=8)
expected = dedent(
"""\
Differing data variables:
L a (x) int16 2B 1
Differing variable attributes:
b: [1 2]
R a (x) int16 2B 1
Differing variable attributes:
b: [2 3]
""".rstrip()
)

assert actual == expected

def test_diff_dataset_repr(self) -> None:
ds_a = xr.Dataset(
data_vars={
Expand Down
Loading