Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
5 changes: 5 additions & 0 deletions doc/whats-new.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ v0.15.1 (unreleased)
Breaking changes
~~~~~~~~~~~~~~~~

- Raise an error when assigning to the ``.values`` or ``.data`` attribute of
dimension coordinates i.e. ``IndexVariable`` objects. This has been broken since
v0.13.0. (:issue:`3470`)
By `Deepak Cherian <https://github.com/dcherian>`_

New Features
~~~~~~~~~~~~

Expand Down
14 changes: 11 additions & 3 deletions xarray/core/variable.py
Original file line number Diff line number Diff line change
Expand Up @@ -2061,9 +2061,17 @@ def load(self):
# https://github.com/python/mypy/issues/1465
@Variable.data.setter # type: ignore
def data(self, data):
Variable.data.fset(self, data)
if not isinstance(self._data, PandasIndexAdapter):
self._data = PandasIndexAdapter(self._data)
raise ValueError(
f"Cannot assign to the .data attribute of dimension coordinate a.k.a IndexVariable {self.name!r}. "
f"Please use DataArray.assign_coords, Dataset.assign_coords or Dataset.assign as appropriate."
)

@Variable.values.setter # type: ignore
def values(self, values):
raise ValueError(
f"Cannot assign to the .values attribute of dimension coordinate a.k.a IndexVariable {self.name!r}. "
f"Please use DataArray.assign_coords, Dataset.assign_coords or Dataset.assign as appropriate."
)

def chunk(self, chunks=None, name=None, lock=False):
# Dummy - do not chunk. This method is invoked e.g. by Dataset.chunk()
Expand Down
4 changes: 2 additions & 2 deletions xarray/tests/test_accessor_dt.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def test_strftime(self):
def test_not_datetime_type(self):
nontime_data = self.data.copy()
int_data = np.arange(len(self.data.time)).astype("int8")
nontime_data["time"].values = int_data
nontime_data = nontime_data.assign_coords(time=int_data)
with raises_regex(TypeError, "dt"):
nontime_data.time.dt

Expand Down Expand Up @@ -213,7 +213,7 @@ def setup(self):
def test_not_datetime_type(self):
nontime_data = self.data.copy()
int_data = np.arange(len(self.data.time)).astype("int8")
nontime_data["time"].values = int_data
nontime_data = nontime_data.assign_coords(time=int_data)
with raises_regex(TypeError, "dt"):
nontime_data.time.dt

Expand Down
2 changes: 1 addition & 1 deletion xarray/tests/test_dask.py
Original file line number Diff line number Diff line change
Expand Up @@ -1274,7 +1274,7 @@ def test_token_changes_when_data_changes(obj):
assert t3 != t2

# Change IndexVariable
obj.coords["x"] *= 2
obj = obj.assign_coords(x=obj.x * 2)
with raise_if_dask_computes():
t4 = dask.base.tokenize(obj)
assert t4 != t3
Expand Down
7 changes: 5 additions & 2 deletions xarray/tests/test_variable.py
Original file line number Diff line number Diff line change
Expand Up @@ -530,15 +530,18 @@ def test_copy_index_with_data(self):
orig = IndexVariable("x", np.arange(5))
new_data = np.arange(5, 10)
actual = orig.copy(data=new_data)
expected = orig.copy()
expected.data = new_data
expected = IndexVariable("x", np.arange(5, 10))
assert_identical(expected, actual)

def test_copy_index_with_data_errors(self):
orig = IndexVariable("x", np.arange(5))
new_data = np.arange(5, 20)
with raises_regex(ValueError, "must match shape of object"):
orig.copy(data=new_data)
with raises_regex(ValueError, "Cannot assign to the .data"):
orig.data = new_data
with raises_regex(ValueError, "Cannot assign to the .values"):
orig.values = new_data

def test_replace(self):
var = Variable(("x", "y"), [[1.5, 2.0], [3.1, 4.3]], {"foo": "bar"})
Expand Down