diff --git a/certbot/tests/util_test.py b/certbot/tests/util_test.py index 866f71e3d..cd02d835d 100644 --- a/certbot/tests/util_test.py +++ b/certbot/tests/util_test.py @@ -45,19 +45,34 @@ class RunScriptTest(unittest.TestCase): self.assertRaises(errors.SubprocessError, self._call, ["test"]) -class WhichTest(unittest.TestCase): - @mock.patch('certbot.util._is_exe') - def test_which(self, mock_is_exe): - from certbot.util import which - mock_is_exe.return_value = True - self.assertEqual(which("/path/to/something"), "/path/to/something") +class ExeExistsTest(unittest.TestCase): + """Tests for certbot.util.exe_exists.""" - with mock.patch.dict('os.environ', {"PATH": "/floop:/fleep"}): - mock_is_exe.return_value = True - self.assertEqual(which("pingify"), "/floop/pingify") - mock_is_exe.return_value = False - self.assertEqual(which("pingify"), None) - self.assertEqual(which("/path/to/something"), None) + @classmethod + def _call(cls, exe): + from certbot.util import exe_exists + return exe_exists(exe) + + @mock.patch("certbot.util.os.path.isfile") + @mock.patch("certbot.util.os.access") + def test_full_path(self, mock_access, mock_isfile): + mock_access.return_value = True + mock_isfile.return_value = True + self.assertTrue(self._call("/path/to/exe")) + + @mock.patch("certbot.util.os.path.isfile") + @mock.patch("certbot.util.os.access") + def test_on_path(self, mock_access, mock_isfile): + mock_access.return_value = True + mock_isfile.return_value = True + self.assertTrue(self._call("exe")) + + @mock.patch("certbot.util.os.path.isfile") + @mock.patch("certbot.util.os.access") + def test_not_found(self, mock_access, mock_isfile): + mock_access.return_value = False + mock_isfile.return_value = True + self.assertFalse(self._call("exe")) class MakeOrVerifyDirTest(unittest.TestCase): diff --git a/certbot/util.py b/certbot/util.py index 733b3e501..cc0a74bd2 100644 --- a/certbot/util.py +++ b/certbot/util.py @@ -68,36 +68,28 @@ def run_script(params, log=logger.error): return stdout, stderr -def _is_exe(fpath): - return os.path.isfile(fpath) and os.access(fpath, os.X_OK) - -def which(program): +def exe_exists(exe): """Determine whether path/name refers to an executable. - :param str program: Executable path or name + :param str exe: Executable path or name - :returns: Path to executable if it exists, or None - :rtype: str or None + :returns: If exe is a valid executable + :rtype: bool """ - # Borrowed from: - # https://stackoverflow.com/questions/377017/test-if-executable-exists-in-python - # XXX May need more porting to handle .exe extensions on Windows + def is_exe(path): + """Determine if path is an exe.""" + return os.path.isfile(path) and os.access(path, os.X_OK) - fpath, _fname = os.path.split(program) - if fpath: - if _is_exe(program): - return program + path, _ = os.path.split(exe) + if path: + return is_exe(exe) else: for path in os.environ["PATH"].split(os.pathsep): - exe_file = os.path.join(path, program) - if _is_exe(exe_file): - return exe_file + if is_exe(os.path.join(path, exe)): + return True - return None - -# Either name makes sense, and we have a lot of call sites! -exe_exists = which + return False def make_or_verify_dir(directory, mode=0o755, uid=0, strict=False):