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

Allow user to explicitly disable coordinates attribute #5514

Merged
merged 10 commits into from
Jul 1, 2021
3 changes: 3 additions & 0 deletions doc/whats-new.rst
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ New Features
By `Justus Magin <https://github.com/keewis>`_.
- Allow plotting categorical data (:pull:`5464`).
By `Jimmy Westling <https://github.com/illviljan>`_.
- Allow removal of the coordinate attribute ``coordinates`` on variables by setting ``.attrs['coordinates']= None``
(:issue:`5510`).
By `Elle Smith <https://github.com/ellesmith88>`_.

Breaking changes
~~~~~~~~~~~~~~~~
Expand Down
12 changes: 12 additions & 0 deletions xarray/conventions.py
Original file line number Diff line number Diff line change
Expand Up @@ -751,6 +751,18 @@ def _encode_coordinates(variables, attributes, non_dim_coord_names):
f"'coordinates' found in both attrs and encoding for variable {name!r}."
)

# if coordinates set to None, don't write coordinates attribute
if (
"coordinates" in attrs
and attrs.get("coordinates") is None
or "coordinates" in encoding
and encoding.get("coordinates") is None
):
# make sure "coordinates" is removed from attrs/encoding
attrs.pop("coordinates", None)
encoding.pop("coordinates", None)
continue

# this will copy coordinates from encoding to attrs if "coordinates" in attrs
# after the next line, "coordinates" is never in encoding
# we get support for attrs["coordinates"] for free.
Expand Down
34 changes: 34 additions & 0 deletions xarray/tests/test_conventions.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,40 @@ def test_do_not_overwrite_user_coordinates(self):
with pytest.raises(ValueError, match=r"'coordinates' found in both attrs"):
conventions.encode_dataset_coordinates(orig)

def test_emit_coordinates_attribute_in_attrs(self):
orig = Dataset(
{"a": 1, "b": 1},
coords={"t": np.array("2004-11-01T00:00:00", dtype=np.datetime64)},
)

orig["a"].attrs["coordinates"] = None
enc, _ = conventions.encode_dataset_coordinates(orig)

# check coordinate attribute emitted for 'a'
assert "coordinates" not in enc["a"].attrs
assert "coordinates" not in enc["a"].encoding

# check coordinate attribute not emitted for 'b'
assert enc["b"].attrs.get("coordinates") == "t"
assert "coordinates" not in enc["b"].encoding

def test_emit_coordinates_attribute_in_encoding(self):
orig = Dataset(
{"a": 1, "b": 1},
coords={"t": np.array("2004-11-01T00:00:00", dtype=np.datetime64)},
)

orig["a"].encoding["coordinates"] = None
enc, _ = conventions.encode_dataset_coordinates(orig)

# check coordinate attribute emitted for 'a'
assert "coordinates" not in enc["a"].attrs
assert "coordinates" not in enc["a"].encoding

# check coordinate attribute not emitted for 'b'
assert enc["b"].attrs.get("coordinates") == "t"
assert "coordinates" not in enc["b"].encoding

@requires_dask
def test_string_object_warning(self):
original = Variable(("x",), np.array(["foo", "bar"], dtype=object)).chunk()
Expand Down