Skip to content

Commit 906d86e

Browse files
authored
Merge pull request #160 from Devguru-codes/algoname
Fix: Add algorithm name validation in OsipiBase.osipi_initiate_algorithm()
2 parents b55efa1 + d1969e1 commit 906d86e

2 files changed

Lines changed: 71 additions & 5 deletions

File tree

src/wrappers/OsipiBase.py

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -178,19 +178,60 @@ def osipi_initiate_algorithm(self, algorithm, **kwargs):
178178
179179
Args:
180180
algorithm (string): The name of the algorithm, should be the same as the file in the src/standardized folder without the .py extension.
181+
182+
Raises:
183+
ValueError: If the algorithm name does not correspond to any .py file
184+
in ``src/standardized/``.
181185
"""
182186

183187
# Import the algorithm
184188
root_path = pathlib.Path(__file__).resolve().parents[2]
185189
if str(root_path) not in sys.path:
186-
print("Root folder not in PYTHONPATH")
187-
return False
188-
190+
raise RuntimeError(
191+
"Root folder not found in PYTHONPATH. "
192+
"Please ensure the project root is in sys.path."
193+
)
194+
195+
# ------------------------------------------------------------------
196+
# Validate algorithm name against available modules in src/standardized/
197+
# ------------------------------------------------------------------
198+
standardized_dir = root_path / "src" / "standardized"
199+
available_algorithms = sorted(
200+
p.stem
201+
for p in standardized_dir.glob("*.py")
202+
if p.stem != "__init__"
203+
)
204+
205+
if algorithm not in available_algorithms:
206+
raise ValueError(
207+
f"Algorithm '{algorithm}' not found. "
208+
f"Available algorithms are:\n "
209+
+ "\n ".join(available_algorithms)
210+
)
211+
189212
import_base_path = "src.standardized"
190213
import_path = import_base_path + "." + algorithm
191-
#Algorithm = getattr(importlib.import_module(import_path), algorithm)
214+
215+
# Secondary safety net: catch import / attribute errors that could
216+
# occur if the file exists but is broken or missing the class.
217+
try:
218+
module = importlib.import_module(import_path)
219+
except ImportError as exc:
220+
raise ImportError(
221+
f"Failed to import module for algorithm '{algorithm}': {exc}"
222+
) from exc
223+
224+
try:
225+
algorithm_class = getattr(module, algorithm)
226+
except AttributeError as exc:
227+
raise AttributeError(
228+
f"Module '{import_path}' was imported but does not contain "
229+
f"a class named '{algorithm}'. "
230+
f"Available names: {[n for n in dir(module) if not n.startswith('_')]}"
231+
) from exc
232+
192233
# Change the class from OsipiBase to the specified algorithm
193-
self.__class__ = getattr(importlib.import_module(import_path), algorithm)
234+
self.__class__ = algorithm_class
194235
self.__init__(**kwargs)
195236

196237
def initialize(**kwargs):

tests/IVIMmodels/unit_tests/test_ivim_fit.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,3 +300,28 @@ def to_list_if_needed(value):
300300
if errors:
301301
all_errors = "\n".join(errors)
302302
raise AssertionError(f"Some tests failed:\n{all_errors}")
303+
304+
305+
def test_invalid_algorithm_name():
306+
"""Regression test for bug_7: invalid algorithm names must raise a clear
307+
ValueError instead of a confusing ModuleNotFoundError / AttributeError.
308+
"""
309+
# A clearly wrong name should raise ValueError
310+
with pytest.raises(ValueError, match="not found"):
311+
OsipiBase(algorithm="IAR_LU_biepx") # typo: 'biepx' instead of 'biexp'
312+
313+
# The error message should list at least one known valid algorithm
314+
try:
315+
OsipiBase(algorithm="totally_fake_algorithm")
316+
except ValueError as exc:
317+
error_msg = str(exc)
318+
assert "Available algorithms are:" in error_msg
319+
# Check a few known algorithms appear in the suggestion list
320+
assert "IAR_LU_biexp" in error_msg
321+
assert "PV_MUMC_biexp" in error_msg
322+
else:
323+
pytest.fail("ValueError was not raised for a completely invalid algorithm name")
324+
325+
# A valid algorithm should still work without errors
326+
fit = OsipiBase(algorithm="IAR_LU_biexp")
327+
assert fit is not None

0 commit comments

Comments
 (0)