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

Raise error when assigning to IndexVariable.values & IndexVariable.data #3862

Merged
merged 10 commits into from
Mar 23, 2020
2 changes: 1 addition & 1 deletion doc/plotting.rst
Original file line number Diff line number Diff line change
Expand Up @@ -657,7 +657,7 @@ Additionally, the boolean kwarg ``add_guide`` can be used to prevent the display

.. ipython:: python

ds.w.values = [1, 2, 3, 5]
ds = ds.assign(w=[1, 2, 3, 5])
@savefig ds_discrete_legend_hue_scatter.png
ds.plot.scatter(x='A', y='B', hue='w', hue_style='discrete')

Expand Down
6 changes: 6 additions & 0 deletions doc/whats-new.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ 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.12.0. Please use :py:meth:`DataArray.assign_coords` or :py:meth:`Dataset.assign_coords`
instead. (:issue:`3470`, :pull:`3862`)
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 @@ -2104,9 +2104,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 @@ -1276,7 +1276,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 @@ -538,15 +538,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