From 5b5f6212901a5353c0e3f4f0d10744755677a4b7 Mon Sep 17 00:00:00 2001 From: "Rodrigo V. Honorato" Date: Fri, 20 Feb 2026 16:30:18 +0100 Subject: [PATCH 1/6] add fallback to local if grid not available --- src/haddock/modules/__init__.py | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/haddock/modules/__init__.py b/src/haddock/modules/__init__.py index f385e7cead..f531680143 100644 --- a/src/haddock/modules/__init__.py +++ b/src/haddock/modules/__init__.py @@ -28,7 +28,7 @@ from haddock.gear.parameters import config_mandatory_general_parameters from haddock.gear.yaml2cfg import read_from_yaml_config, find_incompatible_parameters from haddock.libs.libhpc import HPCScheduler -from haddock.libs.libgrid import GRIDScheduler +from haddock.libs.libgrid import GRIDScheduler, ping_dirac from haddock.libs.libio import folder_exists, working_directory from haddock.libs.libmpi import MPIScheduler from haddock.libs.libontology import ModuleIO, PDBFile @@ -65,9 +65,7 @@ # modules will use these parameters. It is the responsibility of the module to # extract the parameters it needs. # the config file is in modules/defaults.cfg -non_mandatory_general_parameters_defaults = read_from_yaml_config( - modules_defaults_path -) # noqa : E501 +non_mandatory_general_parameters_defaults = read_from_yaml_config(modules_defaults_path) # noqa : E501 incompatible_defaults_params = find_incompatible_parameters(modules_defaults_path) @@ -187,9 +185,7 @@ def update_params( >>> m.update_params(...) """ if update_from_cfg_file and params: - _msg = ( - "You can not provide both `update_from_cfg_file` " "and key arguments." - ) + _msg = "You can not provide both `update_from_cfg_file` and key arguments." raise TypeError(_msg) if update_from_cfg_file: @@ -305,7 +301,7 @@ def export_io_models(self, faulty_tolerance: float = 0.0) -> None: if detected_errors := find_all_cns_errors(self.path): _msg += linesep for error in detected_errors.values(): - _msg += f'{str(error["error"])}{linesep}' + _msg += f"{str(error['error'])}{linesep}" # Show final error message self.finish_with_error(_msg) @@ -433,7 +429,19 @@ def get_engine( return partial(MPIScheduler, ncores=params["ncores"]) # type: ignore elif mode == "grid": - return partial(GRIDScheduler, params=params) # type: ignore + # `grid` mode should only be used IF the grid is reachable, + # if not it should fallback to `local` + grid_available = ping_dirac() + + if grid_available: + return partial(GRIDScheduler, params=params) # type: ignore + else: + log.warning("GRID is not available, activating fallback using `mode=local`") + return partial( # type: ignore + Scheduler, + ncores=params["ncores"], + max_cpus=params["max_cpus"], + ) else: available_engines = ("batch", "local", "mpi") From 68e7a88513d33e26bfa96900ee215b4613c7eaf2 Mon Sep 17 00:00:00 2001 From: "Rodrigo V. Honorato" Date: Fri, 20 Feb 2026 16:30:26 +0100 Subject: [PATCH 2/6] add `test_modules.py` --- tests/test_modules.py | 49 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 tests/test_modules.py diff --git a/tests/test_modules.py b/tests/test_modules.py new file mode 100644 index 0000000000..fa87d20388 --- /dev/null +++ b/tests/test_modules.py @@ -0,0 +1,49 @@ +from functools import partial +from unittest.mock import patch + +from haddock.libs.libgrid import GRIDScheduler +from haddock.libs.libhpc import HPCScheduler +from haddock.libs.libmpi import MPIScheduler +from haddock.libs.libparallel import Scheduler +from haddock.modules import get_engine + + +def test_get_engine_grid_unavailable(): + with patch("haddock.modules.ping_dirac", return_value=False): + engine = get_engine(mode="grid", params={"ncores": 1, "max_cpus": 4}) + assert isinstance(engine, partial) + assert engine.func is Scheduler + + +def test_get_engine_grid_available(): + with patch("haddock.modules.ping_dirac", return_value=True): + engine = get_engine(mode="grid", params={"ncores": 1, "max_cpus": 4}) + assert isinstance(engine, partial) + assert engine.func is GRIDScheduler + + +def test_get_engine_local(): + engine = get_engine(mode="local", params={"ncores": 2, "max_cpus": 8}) + assert isinstance(engine, partial) + assert engine.func is Scheduler + assert engine.keywords["ncores"] == 2 + assert engine.keywords["max_cpus"] == 8 + + +def test_get_engine_batch(): + engine = get_engine( + mode="batch", + params={"queue": "short", "queue_limit": 100, "concat": 5}, + ) + assert isinstance(engine, partial) + assert engine.func is HPCScheduler + assert engine.keywords["target_queue"] == "short" + assert engine.keywords["queue_limit"] == 100 + assert engine.keywords["concat"] == 5 + + +def test_get_engine_mpi(): + engine = get_engine(mode="mpi", params={"ncores": 4}) + assert isinstance(engine, partial) + assert engine.func is MPIScheduler + assert engine.keywords["ncores"] == 4 From e6c1b8a9a4a81956e1ea58d48b216fc998d6b079 Mon Sep 17 00:00:00 2001 From: "Rodrigo V. Honorato" Date: Fri, 20 Feb 2026 16:36:50 +0100 Subject: [PATCH 3/6] update changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e958fec0c1..348612cf7e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,11 @@ # Changelog +- 2026-01-20: Add fallback routine to use `Scheduler` if the GRID is not available - 2025-12-15: Added missing NGA glycan parameters - Issue #1462 - 2025-11-25: Simplify the use of multiple ambig archives - 2025-11-19: Corrected CNS verbosity settings - Issue #1446 - 2025-11-19: Added zinc-finger docking example, related to Issue #1445 -- 2025-11-19: Corrected flexref module for Issue #1445 +- 2025-11-19: Corrected flexref module for Issue #1445 - 2025-11-17: Added possibility to use alascan with ligands - Issue #1411 - 2025-10-22: Allow the definition of chain combinations to be used for scoring - Issue #1414 - 2025-09-11: Added `grid` mode From 6be491ff9bafe74dd53a2827b0b118b22ab58866 Mon Sep 17 00:00:00 2001 From: "Rodrigo V. Honorato" Date: Fri, 20 Feb 2026 16:43:48 +0100 Subject: [PATCH 4/6] add missing return value --- src/haddock/modules/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/haddock/modules/__init__.py b/src/haddock/modules/__init__.py index f531680143..40d483bd3c 100644 --- a/src/haddock/modules/__init__.py +++ b/src/haddock/modules/__init__.py @@ -395,7 +395,7 @@ def _fill_emptypaths(self) -> None: def get_engine( mode: str, params: dict[Any, Any], -) -> partial[Union[HPCScheduler, Scheduler, MPIScheduler]]: +) -> partial[Union[HPCScheduler, Scheduler, MPIScheduler, GRIDScheduler]]: """ Create an engine to run the jobs. From 9dccc2037e72e71b5e5d785cbde59d125825f2a4 Mon Sep 17 00:00:00 2001 From: "Rodrigo V. Honorato" Date: Fri, 20 Feb 2026 22:21:21 +0100 Subject: [PATCH 5/6] fix date --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 348612cf7e..68b752917f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -- 2026-01-20: Add fallback routine to use `Scheduler` if the GRID is not available +- 2026-02-20: Add fallback routine to use `Scheduler` if the GRID is not available - 2025-12-15: Added missing NGA glycan parameters - Issue #1462 - 2025-11-25: Simplify the use of multiple ambig archives - 2025-11-19: Corrected CNS verbosity settings - Issue #1446 From f0adb0c3d7b6afe747d5ca810acbec3c72dc73b0 Mon Sep 17 00:00:00 2001 From: "Rodrigo V. Honorato" Date: Fri, 20 Feb 2026 22:21:28 +0100 Subject: [PATCH 6/6] add grid to available engines --- src/haddock/modules/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/haddock/modules/__init__.py b/src/haddock/modules/__init__.py index 40d483bd3c..4d58043515 100644 --- a/src/haddock/modules/__init__.py +++ b/src/haddock/modules/__init__.py @@ -444,7 +444,7 @@ def get_engine( ) else: - available_engines = ("batch", "local", "mpi") + available_engines = ("batch", "local", "mpi", "grid") raise ValueError( f"Scheduler `mode` {mode!r} not recognized. " f"Available options are {', '.join(available_engines)}"