Skip to content

Commit 93b6b50

Browse files
committed
Do not change coordinate inplace when throwing error (pydata#5957)
1 parent 884f0cb commit 93b6b50

File tree

5 files changed

+37
-1
lines changed

5 files changed

+37
-1
lines changed

xarray/core/dataset.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ def merge_indexes(
224224
vars_to_remove: List[Hashable] = []
225225
dims_to_replace: Dict[Hashable, Hashable] = {}
226226
error_msg = "{} is not the name of an existing variable."
227+
keep_attrs = _get_keep_attrs(default=True)
227228

228229
for dim, var_names in indexes.items():
229230
if isinstance(var_names, str) or not isinstance(var_names, Sequence):
@@ -277,7 +278,8 @@ def merge_indexes(
277278
for n in names:
278279
dims_to_replace[n] = dim
279280

280-
vars_to_replace[dim] = IndexVariable(dim, idx)
281+
attrs = variables[var_names[0]].attrs if keep_attrs else None
282+
vars_to_replace[dim] = IndexVariable(dim, idx, attrs=attrs)
281283
vars_to_remove.extend(var_names)
282284

283285
new_variables = {k: v for k, v in variables.items() if k not in vars_to_remove}

xarray/core/variable.py

+5
Original file line numberDiff line numberDiff line change
@@ -2813,6 +2813,11 @@ def name(self):
28132813
def name(self, value):
28142814
raise AttributeError("cannot modify name of IndexVariable in-place")
28152815

2816+
def _inplace_binary_op(self, other, f):
2817+
raise TypeError(
2818+
"Values of an IndexVariable are immutable and can not be modified inplace"
2819+
)
2820+
28162821

28172822
# for backwards compatibility
28182823
Coordinate = utils.alias(IndexVariable, "Coordinate")

xarray/tests/test_dataarray.py

+12
Original file line numberDiff line numberDiff line change
@@ -1987,6 +1987,18 @@ def test_inplace_math_basics(self):
19871987
assert_array_equal(b.values, x)
19881988
assert source_ndarray(b.values) is x
19891989

1990+
def test_inplace_math_error(self):
1991+
data = np.random.rand(4)
1992+
times = np.arange(4)
1993+
foo = DataArray(data, coords=[times], dims=["time"])
1994+
b = times.copy()
1995+
with pytest.raises(
1996+
TypeError, match=r"Values of an IndexVariable are immutable"
1997+
):
1998+
foo.coords["time"] += 1
1999+
# Check error throwing prevented inplace operation
2000+
assert_array_equal(foo.coords["time"], b)
2001+
19902002
def test_inplace_math_automatic_alignment(self):
19912003
a = DataArray(range(5), [("x", range(5))])
19922004
b = DataArray(range(1, 6), [("x", range(1, 6))])

xarray/tests/test_dataset.py

+9
Original file line numberDiff line numberDiff line change
@@ -2976,6 +2976,15 @@ def test_set_index(self):
29762976
ds.set_index(foo="bar")
29772977
assert str(excinfo.value) == "bar is not the name of an existing variable."
29782978

2979+
# ensure attrs are kept
2980+
da = DataArray([1, 2], dims=["x"])
2981+
da.coords["x"] = (["x"], [2, 3], {"name": "coord_1"})
2982+
da.coords["a"] = (["x"], [0, 1], {"name": "coord_2"})
2983+
ds = Dataset({"x_var": da})
2984+
assert ds.set_index(x="a").x.attrs == {"name": "coord_2"}
2985+
with set_options(keep_attrs=False):
2986+
assert ds.set_index(x="a").x.attrs == {}
2987+
29792988
def test_reset_index(self):
29802989
ds = create_test_multiindex()
29812990
mindex = ds["x"].to_index()

xarray/tests/test_variable.py

+8
Original file line numberDiff line numberDiff line change
@@ -1656,6 +1656,14 @@ def test_inplace_math(self):
16561656
with pytest.raises(ValueError, match=r"dimensions cannot change"):
16571657
v += Variable("y", np.arange(5))
16581658

1659+
def test_inplace_math_error(self):
1660+
x = np.arange(5)
1661+
v = IndexVariable(["x"], x)
1662+
with pytest.raises(
1663+
TypeError, match=r"Values of an IndexVariable are immutable"
1664+
):
1665+
v += 1
1666+
16591667
def test_reduce(self):
16601668
v = Variable(["x", "y"], self.d, {"ignored": "attributes"})
16611669
assert_identical(v.reduce(np.std, "x"), Variable(["y"], self.d.std(axis=0)))

0 commit comments

Comments
 (0)