Skip to content

Add xarray.backends.NoMatchingEngineError #5351

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
1 change: 1 addition & 0 deletions doc/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -887,6 +887,7 @@ Exceptions

MergeError
SerializationWarning
backends.NoMatchingEngineError

Advanced API
============
Expand Down
5 changes: 5 additions & 0 deletions doc/whats-new.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ New Features
Breaking changes
~~~~~~~~~~~~~~~~

- :py:func:`open_dataset` now raises ``xarray.backends.NoMatchingEngineError``
when the ``engine`` keyword is not provided and it is unable to detect the
correct engine to use when opening a file (:issue:`5329`).
Previously (in xarray 0.18.0 and 0.18.1), this was ``ValueError``.
By `Stephan Hoyer <https://github.com/shoyer>`_

Deprecations
~~~~~~~~~~~~
Expand Down
3 changes: 2 additions & 1 deletion xarray/backends/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from .h5netcdf_ import H5NetCDFStore
from .memory import InMemoryDataStore
from .netCDF4_ import NetCDF4DataStore
from .plugins import list_engines
from .plugins import NoMatchingEngineError, list_engines
from .pseudonetcdf_ import PseudoNetCDFDataStore
from .pydap_ import PydapDataStore
from .pynio_ import NioDataStore
Expand All @@ -33,4 +33,5 @@
"ZarrStore",
"PseudoNetCDFDataStore",
"list_engines",
"NoMatchingEngineError",
]
7 changes: 7 additions & 0 deletions xarray/backends/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,13 @@ def open_dataset(
dataset : Dataset
The newly created dataset.

Raises
------
xarray.backends.NoMatchingEngineError
If ``engine`` is not provided and automatic engine detection fails,
either because the file-type cannot be inferred or because the necessary
backend dependencies are not installed.

Notes
-----
``open_dataset`` opens the file with read-only access. When you modify
Expand Down
11 changes: 8 additions & 3 deletions xarray/backends/plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ def list_engines():
return build_engines(pkg_entrypoints)


class NoMatchingEngineError(Exception):
pass


def guess_engine(store_spec):
engines = list_engines()

Expand All @@ -108,16 +112,17 @@ def guess_engine(store_spec):

installed = [k for k in engines if k != "store"]
if installed:
raise ValueError(
raise NoMatchingEngineError(
"did not find a match in any of xarray's currently installed IO "
f"backends {installed}. Consider explicitly selecting one of the "
f"backends {installed}. The provided file may not exist: "
f"{store_spec}\n\nConsider explicitly selecting one of the "
"installed backends via the ``engine`` parameter to "
"xarray.open_dataset(), or installing additional IO dependencies:\n"
"http://xarray.pydata.org/en/stable/getting-started-guide/installing.html\n"
"http://xarray.pydata.org/en/stable/user-guide/io.html"
)
else:
raise ValueError(
raise NoMatchingEngineError(
"xarray is unable to open this file because it has no currently "
"installed IO backends. Xarray's read/write support requires "
"installing optional dependencies:\n"
Expand Down
5 changes: 3 additions & 2 deletions xarray/tests/test_backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -2772,7 +2772,8 @@ def test_open_badbytes(self):
with open_dataset(b"\211HDF\r\n\032\n", engine="h5netcdf"):
pass
with pytest.raises(
ValueError, match=r"match in any of xarray's currently installed IO"
backends.NoMatchingEngineError,
match=r"match in any of xarray's currently installed IO",
):
with open_dataset(b"garbage"):
pass
Expand Down Expand Up @@ -2826,7 +2827,7 @@ def test_open_fileobj(self):
with open(tmp_file, "rb") as f:
f.seek(8)
with pytest.raises(
ValueError,
backends.NoMatchingEngineError,
match="match in any of xarray's currently installed IO",
):
with pytest.warns(
Expand Down
9 changes: 6 additions & 3 deletions xarray/tests/test_plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import pkg_resources
import pytest

from xarray.backends import common, plugins
from xarray.backends import NoMatchingEngineError, common, plugins


class DummyBackendEntrypointArgs(common.BackendEntrypoint):
Expand Down Expand Up @@ -165,7 +165,7 @@ def test_build_engines_sorted():
)
def test_no_matching_engine_found():
with pytest.raises(
ValueError, match="match in any of xarray's currently installed IO"
NoMatchingEngineError, match="match in any of xarray's currently installed IO"
):
plugins.guess_engine("not-valid")

Expand All @@ -175,5 +175,8 @@ def test_no_matching_engine_found():
mock.MagicMock(return_value={}),
)
def test_no_engines_installed():
with pytest.raises(ValueError, match="no currently installed IO backends."):
with pytest.raises(
NoMatchingEngineError,
match="no currently installed IO backends.",
):
plugins.guess_engine("not-valid")