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

solve a bug when the units attribute is not a string #7085

Merged
merged 8 commits into from
Sep 28, 2022
2 changes: 2 additions & 0 deletions doc/whats-new.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ Deprecations
Bug fixes
~~~~~~~~~

- Allow reading netcdf files where the 'units' attribute is a number(:pull:`7085`)
By `Ghislain Picard <https://github.com/ghislainp>`_.
- Allow decoding of 0 sized datetimes(:issue:`1329`, :pull:`6882`)
By `Deepak Cherian <https://github.com/dcherian>`_.
- Make sure DataArray.name is always a string when used as label for plotting.
Expand Down
3 changes: 2 additions & 1 deletion xarray/coding/times.py
Original file line number Diff line number Diff line change
Expand Up @@ -681,7 +681,8 @@ def encode(self, variable, name=None):
def decode(self, variable, name=None):
dims, data, attrs, encoding = unpack_for_decoding(variable)

if "units" in attrs and "since" in attrs["units"]:
units = attrs.get("units")
if isinstance(units, str) and "since" in units:
units = pop_to(attrs, encoding, "units")
calendar = pop_to(attrs, encoding, "calendar")
dtype = _decode_cf_datetime_dtype(data, units, calendar, self.use_cftime)
Expand Down
3 changes: 2 additions & 1 deletion xarray/conventions.py
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,8 @@ def _update_bounds_attributes(variables):
# For all time variables with bounds
for v in variables.values():
attrs = v.attrs
has_date_units = "units" in attrs and "since" in attrs["units"]
units = attrs.get("units")
has_date_units = isinstance(units, str) and "since" in units
if has_date_units and "bounds" in attrs:
if attrs["bounds"] in variables:
bounds_attrs = variables[attrs["bounds"]].attrs
Expand Down
8 changes: 8 additions & 0 deletions xarray/tests/test_coding_times.py
Original file line number Diff line number Diff line change
Expand Up @@ -1167,3 +1167,11 @@ def test_decode_0size_datetime(use_cftime):
use_cftime=use_cftime,
)
np.testing.assert_equal(expected, actual)


@requires_cftime
def test_scalar_unit() -> None:
# test that a scalar units (often NaN when using to_netcdf) does not raise an error
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does Xarray actually write a nan for units? That seems problematic. Can you open a new issue witha reproducible example?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Opened: #7093

variable = Variable(("x", "y"), np.array([[0, 1], [2, 3]]), {"units": np.nan})
result = coding.times.CFDatetimeCoder().decode(variable)
assert np.isnan(result.attrs["units"])
8 changes: 8 additions & 0 deletions xarray/tests/test_conventions.py
Original file line number Diff line number Diff line change
Expand Up @@ -467,3 +467,11 @@ def test_decode_cf_variable_cftime():
decoded = conventions.decode_cf_variable("time", variable)
assert decoded.encoding == {}
assert_identical(decoded, variable)


def test_scalar_units() -> None:
# test that scalar units does not raise an exception
var = Variable(["t"], [np.nan, np.nan, 2], {"units": np.nan})

actual = conventions.decode_cf_variable("t", var)
assert_identical(actual, var)