diff --git a/Documentation/source/site-specific-config.rst b/Documentation/source/site-specific-config.rst index b7481c08..9faaeb04 100644 --- a/Documentation/source/site-specific-config.rst +++ b/Documentation/source/site-specific-config.rst @@ -20,7 +20,12 @@ contains all the tools that will be used during the build process, but it can only store one tool per category. If a certain tool should not be defined in the toolbox, the default from the `ToolRepository` will be used. This is useful for many standard tools like `git`, `rsync` -etc that de-facto will never be changed. +etc that de-facto will never be changed. Fab will check if a tool +is actually available on the system before adding it to a ToolBox. +This is typically done by trying to run the tool with some testing +parameters, for example requesting its version number. If this fails, +the tool is considered not to be available and will not be used (unless +the user explicitly puts a tool into the ToolBox). .. note:: If you need to use for example different compilers for different files, you would implement this as a `meta-compiler`: diff --git a/source/fab/tools/tool.py b/source/fab/tools/tool.py index a870c657..78a8de62 100644 --- a/source/fab/tools/tool.py +++ b/source/fab/tools/tool.py @@ -63,8 +63,7 @@ def check_available(self) -> bool: :returns: whether the tool is working (True) or not. ''' try: - op = self._availability_option - self.run(op) + self.run(self._availability_option) except (RuntimeError, FileNotFoundError): return False return True diff --git a/source/fab/tools/tool_repository.py b/source/fab/tools/tool_repository.py index 0a17d7e6..965e252b 100644 --- a/source/fab/tools/tool_repository.py +++ b/source/fab/tools/tool_repository.py @@ -75,7 +75,7 @@ def __init__(self): # Add the common shells. While Fab itself does not need this, # it is a very convenient tool for user configuration (e.g. to # query nc-config etc) - for shell_name in ["bash", "sh", "ksh", "dash"]: + for shell_name in ["sh", "bash", "ksh", "dash"]: self.add_tool(Shell(shell_name)) # Now create the potential mpif90 and Cray ftn wrapper @@ -174,6 +174,8 @@ def get_default(self, category: Category, OpenMP. :raises KeyError: if the category does not exist. + :raises RuntimeError: if no tool in the requested category is + available on the system. :raises RuntimeError: if no compiler/linker is found with the requested level of MPI support (yes or no). ''' diff --git a/tests/unit_tests/tools/test_shell.py b/tests/unit_tests/tools/test_shell.py index 38ba8c71..deab54d4 100644 --- a/tests/unit_tests/tools/test_shell.py +++ b/tests/unit_tests/tools/test_shell.py @@ -39,11 +39,11 @@ def test_shell_check_available(): def test_shell_exec_single_arg(): '''Test running a shell script without additional parameters.''' - bash = Shell("ksh") + ksh = Shell("ksh") mock_result = mock.Mock(returncode=0) with mock.patch('fab.tools.tool.subprocess.run', return_value=mock_result) as tool_run: - bash.exec("echo") + ksh.exec("echo") tool_run.assert_called_with(['ksh', '-c', 'echo'], capture_output=True, env=None, cwd=None, check=False) @@ -51,11 +51,11 @@ def test_shell_exec_single_arg(): def test_shell_exec_multiple_args(): '''Test running a shell script with parameters.''' - bash = Shell("ksh") + ksh = Shell("ksh") mock_result = mock.Mock(returncode=0) with mock.patch('fab.tools.tool.subprocess.run', return_value=mock_result) as tool_run: - bash.exec(["some", "shell", "function"]) + ksh.exec(["some", "shell", "function"]) tool_run.assert_called_with(['ksh', '-c', 'some', 'shell', 'function'], capture_output=True, env=None, cwd=None, check=False)