diff --git a/doc/whats-new.rst b/doc/whats-new.rst index 15da1221c90..15d9210c3a6 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -47,6 +47,8 @@ Bug fixes :py:meth:`DataArray.to_index` for multi-index levels (convert to single index). (:issue:`6836`, :pull:`7105`) By `BenoƮt Bovy `_. +- Support for open_dataset backends that return datasets containing multi-indexes (:issue:`7139`, :pull:`7150`) + By `Lukas Bindreiter `_. Documentation ~~~~~~~~~~~~~ diff --git a/xarray/backends/api.py b/xarray/backends/api.py index 3e34af08e27..13bcf046ac3 100644 --- a/xarray/backends/api.py +++ b/xarray/backends/api.py @@ -234,7 +234,7 @@ def _get_mtime(filename_or_obj): def _protect_dataset_variables_inplace(dataset, cache): for name, variable in dataset.variables.items(): - if name not in variable.dims: + if name not in dataset._indexes: # no need to protect IndexVariable objects data = indexing.CopyOnWriteArray(variable._data) if cache: diff --git a/xarray/tests/test_backends_api.py b/xarray/tests/test_backends_api.py index e14234bcaf9..efff86d7683 100644 --- a/xarray/tests/test_backends_api.py +++ b/xarray/tests/test_backends_api.py @@ -48,6 +48,25 @@ def open_dataset( assert_identical(expected, actual) +def test_multiindex() -> None: + # GH7139 + # Check that we properly handle backends that change index variables + dataset = xr.Dataset(coords={"coord1": ["A", "B"], "coord2": [1, 2]}) + dataset = dataset.stack(z=["coord1", "coord2"]) + + class MultiindexBackend(xr.backends.BackendEntrypoint): + def open_dataset( + self, + filename_or_obj, + drop_variables=None, + **kwargs, + ) -> xr.Dataset: + return dataset.copy(deep=True) + + loaded = xr.open_dataset("fake_filename", engine=MultiindexBackend) + assert_identical(dataset, loaded) + + class PassThroughBackendEntrypoint(xr.backends.BackendEntrypoint): """Access an object passed to the `open_dataset` method."""