From 30e957754ad62943f9b70a50ab5e6b23a24e9c9b Mon Sep 17 00:00:00 2001 From: Kkkakania <200867803+Kkkakania@users.noreply.github.com> Date: Fri, 24 Jul 2026 10:01:46 +0800 Subject: [PATCH] Add get method to CF accessors --- cf_xarray/accessor.py | 33 ++++++++++++++++++++++++++++++++ cf_xarray/tests/test_accessor.py | 16 ++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/cf_xarray/accessor.py b/cf_xarray/accessor.py index ed0c216d..4241d929 100644 --- a/cf_xarray/accessor.py +++ b/cf_xarray/accessor.py @@ -172,6 +172,7 @@ def __repr__(self) -> str: # Type for decorators F = TypeVar("F", bound=Callable[..., Any]) +T_Default = TypeVar("T_Default") def sort_maybe_hashable(iterable: Iterable[Hashable]) -> list[Hashable]: @@ -1544,6 +1545,38 @@ def __init__(self, obj): def __setstate__(self, d): self.__dict__ = d + @overload + def get( + self, key: Hashable | Iterable[Hashable], default: None = None + ) -> DataArray | Dataset | None: ... + + @overload + def get( + self, key: Hashable | Iterable[Hashable], default: T_Default + ) -> DataArray | Dataset | T_Default: ... + + def get(self, key: Hashable | Iterable[Hashable], default=None): + """ + Access a variable using CF attributes, returning a default if not found. + + Parameters + ---------- + key : Hashable or Iterable of Hashable + Key passed to ``__getitem__``. + default : Any, optional + Value to return when ``key`` is not found. + + Returns + ------- + DataArray, Dataset, or Any + The object selected by ``key``, or ``default`` if selection raises + ``KeyError``. + """ + try: + return self[key] # type: ignore[index] + except KeyError: + return default + def _assert_valid_other_comparison(self, other): # TODO cache this property flag_dict = create_flag_dict(self._obj) diff --git a/cf_xarray/tests/test_accessor.py b/cf_xarray/tests/test_accessor.py index 6657be46..570c5839 100644 --- a/cf_xarray/tests/test_accessor.py +++ b/cf_xarray/tests/test_accessor.py @@ -692,6 +692,22 @@ def test_getitem_errors(obj): obj2.cf["X"] +@pytest.mark.parametrize("obj", objects) +def test_get(obj): + assert_identical(obj.cf.get("longitude"), obj.cf["longitude"]) + assert obj.cf.get("missing") is None + + default = object() + assert obj.cf.get("missing", default) is default + + +def test_get_iterable_key(): + assert_identical(airds.cf.get(["longitude"]), airds.cf[["longitude"]]) + + default = object() + assert airds.air.cf.get(["longitude"], default) is default + + def test_bad_cell_measures_attribute() -> None: air2 = airds.copy(deep=False) air2.air.attrs["cell_measures"] = "--OPT"