diff --git a/splunk_add_on_ucc_framework/install_python_libraries.py b/splunk_add_on_ucc_framework/install_python_libraries.py index d63130762..40ae0baea 100644 --- a/splunk_add_on_ucc_framework/install_python_libraries.py +++ b/splunk_add_on_ucc_framework/install_python_libraries.py @@ -95,13 +95,6 @@ def _pip_is_lib_installed( lib_installed_cmd = f"{installer} -m pip show --version {libname}" - if version and allow_higher_version: - cmd = f'{lib_installed_cmd} | grep "Version"' - elif version and not allow_higher_version: - cmd = f'{lib_installed_cmd} | grep "Version: {version}"' - else: - cmd = lib_installed_cmd - try: my_env = os.environ.copy() my_env["PYTHONPATH"] = target @@ -109,15 +102,20 @@ def _pip_is_lib_installed( # Disable writing of .pyc files (__pycache__) my_env["PYTHONDONTWRITEBYTECODE"] = "1" - if allow_higher_version: - result = _subprocess_run(command=cmd, env=my_env) - if result.returncode != 0: - return False - result_version = result.stdout.decode("utf-8").split("Version:")[1].strip() - return Version(result_version) >= Version(version) + result = _subprocess_run(command=lib_installed_cmd, env=my_env) + if result.returncode != 0 or "Version:" not in result.stdout.decode("utf-8"): + return False + + if version: + pip_show_result = result.stdout.decode("utf-8").splitlines() + result_row = next(el for el in pip_show_result if el.startswith("Version:")) + result_version = result_row.split("Version:")[1].strip() + if allow_higher_version: + return Version(result_version) >= Version(version) + return Version(result_version) == Version(version) else: - return_code = _subprocess_run(command=cmd, env=my_env).returncode - return return_code == 0 + return result.returncode == 0 + except OSError as e: raise CouldNotInstallRequirements from e diff --git a/tests/unit/test_install_python_libraries.py b/tests/unit/test_install_python_libraries.py index 12192831b..d6740fbf0 100644 --- a/tests/unit/test_install_python_libraries.py +++ b/tests/unit/test_install_python_libraries.py @@ -5,6 +5,7 @@ from unittest import mock import pytest + import tests.unit.helpers as helpers from splunk_add_on_ucc_framework.global_config import OSDependentLibraryConfig @@ -28,8 +29,9 @@ class MockSubprocessResult: - def __init__(self, returncode): + def __init__(self, returncode, stdout=b""): self.returncode = returncode + self.stdout = stdout @mock.patch("subprocess.run", autospec=True) @@ -281,8 +283,23 @@ def test_install_libraries_valid_os_libraries( "valid_config_with_os_libraries.json" ) global_config = gc.GlobalConfig(global_config_path) - - mock_subprocess_run.return_value = MockSubprocessResult(0) + mock_subprocess_run.side_effect = [ + MockSubprocessResult(0), # mock subprocess.run from _pip_install + MockSubprocessResult(0), # mock subprocess.run from _pip_install + MockSubprocessResult( + 0, b"Version: 41.0.5" + ), # mock subprocess.run from _pip_is_lib_installed + MockSubprocessResult(0), # mock subprocess.run from _pip_install + MockSubprocessResult( + 0, b"Version: 41.0.5" + ), # mock subprocess.run from _pip_is_lib_installed + MockSubprocessResult(0), # mock subprocess.run from _pip_install + MockSubprocessResult( + 0, b"Version: 1.5.1" + ), # mock subprocess.run from _pip_is_lib_installed + MockSubprocessResult(0), # mock subprocess.run from _pip_install + MockSubprocessResult(0), # mock subprocess.run from _pip_install + ] tmp_ucc_lib_target = tmp_path / "ucc-lib-target" tmp_lib_path = tmp_path / "lib" tmp_lib_path.mkdir() @@ -369,15 +386,13 @@ def test_install_libraries_version_mismatch( tmp_lib_reqs_file = tmp_lib_path / "requirements.txt" tmp_lib_reqs_file.write_text("splunktaucclib\n") - version_mismatch_shell_cmd = ( - 'python3 -m pip show --version cryptography | grep "Version: 41.0.5"' - ) + version_mismatch_shell_cmd = "python3 -m pip show --version cryptography" mock_subprocess_run.side_effect = ( lambda command, shell=True, env=None, capture_output=True: ( MockSubprocessResult(1) if command == version_mismatch_shell_cmd and ucc_lib_target == env["PYTHONPATH"] - else MockSubprocessResult(0) + else MockSubprocessResult(0, b"Version: 40.0.0") ) ) @@ -521,7 +536,7 @@ def run(command, env): assert command == "python3 -m pip show --version libname" assert env["PYTHONPATH"] == "target" assert env["PYTHONDONTWRITEBYTECODE"] == "1" - return Result(0, b"", b"") + return Result(0, b"Version: 1.0.0", b"") monkeypatch.setattr(install_python_libraries_module, "_subprocess_run", run) assert _pip_is_lib_installed("python3", "target", "libname")