From dedc25e9bf66e83e727e3ed3241feddf89428e51 Mon Sep 17 00:00:00 2001 From: Clemens Brunner Date: Wed, 25 Feb 2026 08:38:01 +0100 Subject: [PATCH 1/2] Fix dependency detection in standalone --- src/mnelab/utils/dependencies.py | 20 ++++++--- tests/test_dependencies.py | 71 ++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 5 deletions(-) create mode 100644 tests/test_dependencies.py diff --git a/src/mnelab/utils/dependencies.py b/src/mnelab/utils/dependencies.py index 85b9dce8..fb538fb3 100644 --- a/src/mnelab/utils/dependencies.py +++ b/src/mnelab/utils/dependencies.py @@ -2,7 +2,7 @@ # # License: BSD (3-clause) -from importlib import metadata +from importlib import import_module, metadata required = [ "mne", @@ -21,14 +21,24 @@ optional = ["autoreject", "mne-qt-browser", "picard", "sklearn"] _distribution_names = { - "python-picard": "picard", - "scikit-learn": "sklearn", + "picard": "python-picard", + "sklearn": "scikit-learn", } +_import_names = { + "pyside6": "PySide6", +} + have = {} for dep in required + optional: - distribution_name = {v: k for k, v in _distribution_names.items()}.get(dep, dep) + distribution_name = _distribution_names.get(dep, dep) + import_name = _import_names.get(dep, dep).replace("-", "_") try: version = metadata.version(distribution_name) except metadata.PackageNotFoundError: - version = False + try: + mod = import_module(import_name) + except ImportError: + version = False + else: + version = getattr(mod, "__version__", None) or "unknown" have[distribution_name] = version diff --git a/tests/test_dependencies.py b/tests/test_dependencies.py new file mode 100644 index 00000000..96c8a9e9 --- /dev/null +++ b/tests/test_dependencies.py @@ -0,0 +1,71 @@ +# © MNELAB developers +# +# License: BSD (3-clause) + +import importlib +import sys +from importlib import metadata as importlib_metadata +from importlib import util as importlib_util +from pathlib import Path +from types import SimpleNamespace + + +def _load_dependencies_module(monkeypatch, modules): + module_path = ( + Path(__file__).resolve().parents[1] + / "src" + / "mnelab" + / "utils" + / "dependencies.py" + ) + + def fake_metadata_version(_name): + raise importlib_metadata.PackageNotFoundError + + def fake_import_module(name): + if name in modules: + return modules[name] + raise ImportError(name) + + monkeypatch.setattr(importlib_metadata, "version", fake_metadata_version) + monkeypatch.setattr(importlib, "import_module", fake_import_module) + + module_name = "mnelab_test_dependencies" + sys.modules.pop(module_name, None) + spec = importlib_util.spec_from_file_location(module_name, module_path) + if spec is None or spec.loader is None: + raise RuntimeError("Could not create module spec for dependencies.py") + module = importlib_util.module_from_spec(spec) + sys.modules[module_name] = module + spec.loader.exec_module(module) + return module + + +def test_standalone_fallback_detects_importable_dependencies(monkeypatch): + modules = { + "PySide6": SimpleNamespace(__version__="6.9.4"), + "matplotlib": SimpleNamespace(__version__="3.10.0"), + "scipy": SimpleNamespace(__version__="1.14.1"), + "pyxdf": SimpleNamespace(__version__="1.16.0"), + "pybvrf": SimpleNamespace(__version__="0.1.1"), + "black": SimpleNamespace(__version__="25.0.0"), + "onnx": SimpleNamespace(__version__="1.20.0"), + "picard": SimpleNamespace(__version__="0.8.0"), + } + + dependencies = _load_dependencies_module(monkeypatch, modules) + + assert dependencies.have["pyside6"] == "6.9.4" + assert dependencies.have["matplotlib"] == "3.10.0" + assert dependencies.have["scipy"] == "1.14.1" + assert dependencies.have["pyxdf"] == "1.16.0" + assert dependencies.have["pybvrf"] == "0.1.1" + assert dependencies.have["black"] == "25.0.0" + assert dependencies.have["onnx"] == "1.20.0" + assert dependencies.have["python-picard"] == "0.8.0" + + +def test_standalone_fallback_keeps_false_for_missing_import(monkeypatch): + dependencies = _load_dependencies_module(monkeypatch, modules={}) + + assert dependencies.have["pyside6"] is False From 8741bf30152c39763ceedc143d3e9e6358444836 Mon Sep 17 00:00:00 2001 From: Clemens Brunner Date: Wed, 25 Feb 2026 08:48:39 +0100 Subject: [PATCH 2/2] Add changelog entry --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2aeb3a7f..7a3ee56f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,9 @@ - Add dialog for automatic epoch artifact detection with configurable methods ([#558](https://github.com/cbrnr/mnelab/pull/558) by [Fabian Schellander](https://github.com/SchellanderF)) - Add MNE log messages viewer to history dialog ([#561](https://github.com/cbrnr/mnelab/pull/561) by [Clemens Brunner](https://github.com/cbrnr)) +### 🔧 Fixed +- Fix dependency detection in standalone versions that could have caused some features to not work ([#562](https://github.com/cbrnr/mnelab/pull/562)) by [Clemens Brunner](https://github.com/cbrnr)) + ## [1.2.0] · 2026-02-17 ### ✨ Added - Add support for BVRF import via PyBVRF ([#560](https://github.com/cbrnr/mnelab/pull/560) by [Clemens Brunner](https://github.com/cbrnr))