Skip to content

Commit eb0758a

Browse files
baris-talarclaude
andauthored
FIX: handle missing __version__ in check_version (#13870)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 9755cbf commit eb0758a

4 files changed

Lines changed: 27 additions & 4 deletions

File tree

doc/changes/dev/13870.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix handling of optional dependencies that don't specify a version attribute, by :newcontrib:`Baris Talar`.

doc/changes/names.inc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
.. _Asish Panda: https://github.com/kaichogami
3737
.. _Austin Hurst: https://github.com/a-hurst
3838
.. _Ayushi Satodiya: https://github.com/ayuclan
39+
.. _Baris Talar: https://github.com/baris-talar
3940
.. _Beige Jin: https://github.com/BeiGeJin
4041
.. _Ben Beasley: https://github.com/musicinmybrain
4142
.. _Benedikt Ehinger: https://www.benediktehinger.de

mne/utils/check.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,9 @@ def check_version(library, min_version="0.0", *, strip=True, return_version=Fals
8383
Parameters
8484
----------
8585
library : str
86-
The library name to import. Must have a ``__version__`` property.
86+
The library name to import. Should have a ``__version__`` property;
87+
if absent and ``min_version`` is specified, the version check will
88+
fail.
8789
min_version : str
8890
The minimum version string. Anything that matches
8991
``'(\d+ | [a-z]+ | \.)'``. Can also be empty to skip version
@@ -120,11 +122,14 @@ def check_version(library, min_version="0.0", *, strip=True, return_version=Fals
120122
check_version = min_version and min_version != "0.0"
121123
get_version = check_version or return_version
122124
if get_version:
123-
version = library.__version__
124-
if strip:
125+
try:
126+
version = library.__version__
127+
except AttributeError:
128+
version = None
129+
if version is not None and strip:
125130
version = _strip_dev(version)
126131
if check_version:
127-
if _compare_version(version, "<", min_version):
132+
if version is None or _compare_version(version, "<", min_version):
128133
ok = False
129134
out = (ok, version) if return_version else ok
130135
return out

mne/utils/tests/test_check.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,3 +415,19 @@ def test_soft_import():
415415
"""Test _soft_import."""
416416
with pytest.raises(RuntimeError, match=r".* the module mne>=999 \(found version.*"):
417417
_soft_import("mne", "testing", min_version="999")
418+
419+
420+
def test_soft_import_missing_version(monkeypatch):
421+
"""Test _soft_import handles packages without __version__."""
422+
import types
423+
424+
fake_mod = types.ModuleType("fake_no_version")
425+
monkeypatch.setitem(sys.modules, "fake_no_version", fake_mod)
426+
427+
# No min_version: should succeed even without __version__
428+
mod = _soft_import("fake_no_version", "testing", strict=True)
429+
assert mod is fake_mod
430+
431+
# With min_version: should fail because __version__ is absent
432+
with pytest.raises(RuntimeError, match="module fake_no_version"):
433+
_soft_import("fake_no_version", "testing", strict=True, min_version="1.0")

0 commit comments

Comments
 (0)