Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
4 changes: 4 additions & 0 deletions doc/changes/dev/13870.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
``check_version`` now gracefully handles packages that do not expose
``__version__`` at the top level when no minimum version is required,
improving handling of optional dependencies in ``_soft_import``, by
:newcontrib:`Baris Talar`.
Comment thread
drammock marked this conversation as resolved.
Outdated
1 change: 1 addition & 0 deletions doc/changes/names.inc
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
.. _Ashley Drew: https://github.com/ashdrew
.. _Asish Panda: https://github.com/kaichogami
.. _Austin Hurst: https://github.com/a-hurst
.. _Baris Talar: https://github.com/baris-talar
.. _Beige Jin: https://github.com/BeiGeJin
.. _Ben Beasley: https://github.com/musicinmybrain
.. _Benedikt Ehinger: https://www.benediktehinger.de
Expand Down
13 changes: 9 additions & 4 deletions mne/utils/check.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,9 @@ def check_version(library, min_version="0.0", *, strip=True, return_version=Fals
Parameters
----------
library : str
The library name to import. Must have a ``__version__`` property.
The library name to import. Should have a ``__version__`` property;
if absent and ``min_version`` is specified, the version check will
fail.
min_version : str
The minimum version string. Anything that matches
``'(\d+ | [a-z]+ | \.)'``. Can also be empty to skip version
Expand Down Expand Up @@ -120,11 +122,14 @@ def check_version(library, min_version="0.0", *, strip=True, return_version=Fals
check_version = min_version and min_version != "0.0"
get_version = check_version or return_version
if get_version:
version = library.__version__
if strip:
try:
version = library.__version__
except AttributeError:
version = None
if version is not None and strip:
version = _strip_dev(version)
if check_version:
if _compare_version(version, "<", min_version):
if version is None or _compare_version(version, "<", min_version):
ok = False
out = (ok, version) if return_version else ok
return out
Expand Down
16 changes: 16 additions & 0 deletions mne/utils/tests/test_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -415,3 +415,19 @@ def test_soft_import():
"""Test _soft_import."""
with pytest.raises(RuntimeError, match=r".* the module mne>=999 \(found version.*"):
_soft_import("mne", "testing", min_version="999")


def test_soft_import_missing_version(monkeypatch):
"""Test _soft_import handles packages without __version__."""
import types

fake_mod = types.ModuleType("fake_no_version")
monkeypatch.setitem(sys.modules, "fake_no_version", fake_mod)

# No min_version: should succeed even without __version__
mod = _soft_import("fake_no_version", "testing", strict=True)
assert mod is fake_mod

# With min_version: should fail because __version__ is absent
with pytest.raises(RuntimeError, match="module fake_no_version"):
_soft_import("fake_no_version", "testing", strict=True, min_version="1.0")
Loading