Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,26 @@ def extract_units(obj: object, /) -> dict:
raise TypeError(msg)


def _reject_unknown_unit_names(
units: "Mapping[Hashable, Any]", valid_names: "set[Any]", obj_kind: str
) -> None:
"""Raise if units names something that is not a variable/coordinate.

Without this, a typo in a **unit_kwargs name (e.g.
quantify(temperatrue="K")) is silently dropped by units.get(name),
leaving the data unquantified with no error or warning.
"""
unknown = [k for k in units if k not in valid_names]
if unknown:
valid = ", ".join(sorted(repr(n) for n in valid_names if n is not None))
bad = ", ".join(repr(k) for k in unknown)
msg = (
f"got unit(s) for name(s) not in the {obj_kind}: {bad}. "
f"Valid names: {valid}."
)
Comment thread
nstarman marked this conversation as resolved.
Outdated
raise ValueError(msg)


@dispatch
def attach_units(
obj: DataArray, units: Mapping[Hashable, u.AbstractUnit | str | None]
Expand Down Expand Up @@ -296,6 +316,8 @@ def attach_units(
{}

"""
_reject_unknown_unit_names(units, {None} | set(obj.coords), "DataArray")

# Handle the data array itself (None key = the DataArray's own data)
data_unit = units.get(None)
new_data = _array_attach_units(obj.data, data_unit)
Expand Down Expand Up @@ -346,6 +368,8 @@ def attach_units(
New Dataset with units attached as Quantities.

"""
_reject_unknown_unit_names(units, set(obj.data_vars) | set(obj.coords), "Dataset")

# Handle all variables in dataset
new_vars = {}
for name, var in obj.data_vars.items():
Expand Down
29 changes: 29 additions & 0 deletions packages/unxts.interop.xarray/tests/test_unknown_unit_keys.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"""quantify()/attach_units reject unit specs for names that don't exist.

Regression: a typo in a `**unit_kwargs` name was silently dropped, leaving the
data unquantified with no error.
"""

import pytest
import unxts.interop.xarray # noqa: F401 # registers the .unxt accessor
import xarray as xr

import unxt as u


def test_dataset_typo_key_raises():
ds = xr.Dataset({"temperature": ("x", [1.0, 2.0])})
with pytest.raises(ValueError, match=r"not in the Dataset.*temperatrue"):
ds.unxt.quantify(temperatrue="K")
# the correct name still works
q = ds.unxt.quantify(temperature="K")
assert u.unit_of(q["temperature"].data) == u.unit("K")


def test_dataarray_typo_coord_key_raises():
da = xr.DataArray([1.0, 2.0], dims=["x"], coords={"x": ("x", [0.0, 1.0])})
with pytest.raises(ValueError, match=r"not in the DataArray.*'xx'"):
da.unxt.quantify(xx="s")
# valid data + coord names still work
q = da.unxt.quantify("m", x="s")
assert u.unit_of(q.data) == u.unit("m")
Comment thread
nstarman marked this conversation as resolved.
Outdated
Loading