From 21e42b8e1cc936b16958979d8383a04bb20dc74f Mon Sep 17 00:00:00 2001 From: Adva Oren Date: Mon, 3 Aug 2026 16:49:11 +0300 Subject: [PATCH 1/5] fix(python): validate BEST_EFFORTS requires VIRTUAL_ENV Add early validation in PythonControllerBase.getDependencies() that throws a RuntimeException when BEST_EFFORTS=true is set without VIRTUAL_ENV=true. Without this check, the best-efforts install logic is silently skipped because it is gated behind automaticallyInstallPackageOnEnvironment(), which returns false for PythonControllerRealEnv. Implements TC-5477 Assisted-by: Claude Code --- .../trustifyda/utils/PythonControllerBase.java | 9 +++++++++ .../utils/PythonControllerRealEnvTest.java | 17 +++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/src/main/java/io/github/guacsec/trustifyda/utils/PythonControllerBase.java b/src/main/java/io/github/guacsec/trustifyda/utils/PythonControllerBase.java index c7441cb9..0cb77e6a 100644 --- a/src/main/java/io/github/guacsec/trustifyda/utils/PythonControllerBase.java +++ b/src/main/java/io/github/guacsec/trustifyda/utils/PythonControllerBase.java @@ -78,6 +78,15 @@ public final List> getDependencies( if (isVirtualEnv() || isRealEnv()) { prepareEnvironment(pathToPythonBin); } + if (Environment.getBoolean(PROP_TRUSTIFY_DA_PYTHON_INSTALL_BEST_EFFORTS, false) + && !automaticallyInstallPackageOnEnvironment()) { + throw new RuntimeException( + "Conflicting settings, " + + PROP_TRUSTIFY_DA_PYTHON_INSTALL_BEST_EFFORTS + + "=true requires " + + PROP_TRUSTIFY_DA_PYTHON_VIRTUAL_ENV + + "=true"); + } if (automaticallyInstallPackageOnEnvironment()) { boolean installBestEfforts = Environment.getBoolean(PROP_TRUSTIFY_DA_PYTHON_INSTALL_BEST_EFFORTS, false); diff --git a/src/test/java/io/github/guacsec/trustifyda/utils/PythonControllerRealEnvTest.java b/src/test/java/io/github/guacsec/trustifyda/utils/PythonControllerRealEnvTest.java index 4aa98d2c..fa6e754c 100644 --- a/src/test/java/io/github/guacsec/trustifyda/utils/PythonControllerRealEnvTest.java +++ b/src/test/java/io/github/guacsec/trustifyda/utils/PythonControllerRealEnvTest.java @@ -17,6 +17,8 @@ package io.github.guacsec.trustifyda.utils; import static io.github.guacsec.trustifyda.Provider.PROP_MATCH_MANIFEST_VERSIONS; +import static io.github.guacsec.trustifyda.utils.PythonControllerBase.PROP_TRUSTIFY_DA_PYTHON_INSTALL_BEST_EFFORTS; +import static io.github.guacsec.trustifyda.utils.PythonControllerBase.PROP_TRUSTIFY_DA_PYTHON_VIRTUAL_ENV; import static io.github.guacsec.trustifyda.utils.PythonControllerBaseTest.matchCommandPipFreeze; import static io.github.guacsec.trustifyda.utils.PythonControllerBaseTest.matchCommandPipShow; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -334,6 +336,21 @@ void get_Dependency_Name_with_extras_and_special_operators() { PythonControllerRealEnv.getDependencyName("package[extra]~=1.0 ; python_version >= \"3\"")); } + /** Verifies that BEST_EFFORTS=true without VIRTUAL_ENV=true throws a descriptive error. */ + @Test + @RestoreSystemProperties + @SetSystemProperty(key = PROP_TRUSTIFY_DA_PYTHON_INSTALL_BEST_EFFORTS, value = "true") + void best_Efforts_Without_Virtual_Env_Should_Throw_Runtime_Exception() { + String requirementsTxt = getFileFromString("requirements.txt", "flask==9.9.9\n"); + RuntimeException runtimeException = + assertThrows( + RuntimeException.class, + () -> pythonControllerRealEnv.getDependencies(requirementsTxt, true)); + assertTrue( + runtimeException.getMessage().contains(PROP_TRUSTIFY_DA_PYTHON_INSTALL_BEST_EFFORTS)); + assertTrue(runtimeException.getMessage().contains(PROP_TRUSTIFY_DA_PYTHON_VIRTUAL_ENV)); + } + @Test void automaticallyInstallPackageOnEnvironment() { assertFalse(pythonControllerRealEnv.automaticallyInstallPackageOnEnvironment()); From 5e2f300c782729b45732a5ab2eabd9b474c36c2f Mon Sep 17 00:00:00 2001 From: Adva Oren Date: Mon, 3 Aug 2026 19:09:30 +0300 Subject: [PATCH 2/5] refactor(python): use IllegalStateException for conflicting settings Change RuntimeException to IllegalStateException for conflicting configuration state validations in PythonControllerBase.getDependencies(). This aligns with the codebase convention where IllegalStateException is used for invalid/conflicting configuration states (16 existing instances across providers). Both conflicting-settings throw statements are updated: - BEST_EFFORTS=true without VIRTUAL_ENV=true (line 83) - BEST_EFFORTS=true with MATCH_MANIFEST_VERSIONS=true (line 102) The test assertion in PythonControllerRealEnvTest is updated to expect IllegalStateException. The VirtualEnvTest assertion still passes since IllegalStateException extends RuntimeException. Implements TC-5493 Assisted-by: Claude Code --- .../guacsec/trustifyda/utils/PythonControllerBase.java | 4 ++-- .../trustifyda/utils/PythonControllerRealEnvTest.java | 9 ++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/main/java/io/github/guacsec/trustifyda/utils/PythonControllerBase.java b/src/main/java/io/github/guacsec/trustifyda/utils/PythonControllerBase.java index 0cb77e6a..6d3ac76f 100644 --- a/src/main/java/io/github/guacsec/trustifyda/utils/PythonControllerBase.java +++ b/src/main/java/io/github/guacsec/trustifyda/utils/PythonControllerBase.java @@ -80,7 +80,7 @@ public final List> getDependencies( } if (Environment.getBoolean(PROP_TRUSTIFY_DA_PYTHON_INSTALL_BEST_EFFORTS, false) && !automaticallyInstallPackageOnEnvironment()) { - throw new RuntimeException( + throw new IllegalStateException( "Conflicting settings, " + PROP_TRUSTIFY_DA_PYTHON_INSTALL_BEST_EFFORTS + "=true requires " @@ -99,7 +99,7 @@ public final List> getDependencies( if (installBestEfforts) { boolean matchManifestVersions = Environment.getBoolean(PROP_MATCH_MANIFEST_VERSIONS, true); if (matchManifestVersions) { - throw new RuntimeException( + throw new IllegalStateException( "Conflicting settings, " + PythonControllerBase.PROP_TRUSTIFY_DA_PYTHON_INSTALL_BEST_EFFORTS + "=true can only work with " diff --git a/src/test/java/io/github/guacsec/trustifyda/utils/PythonControllerRealEnvTest.java b/src/test/java/io/github/guacsec/trustifyda/utils/PythonControllerRealEnvTest.java index fa6e754c..eee26914 100644 --- a/src/test/java/io/github/guacsec/trustifyda/utils/PythonControllerRealEnvTest.java +++ b/src/test/java/io/github/guacsec/trustifyda/utils/PythonControllerRealEnvTest.java @@ -342,13 +342,12 @@ void get_Dependency_Name_with_extras_and_special_operators() { @SetSystemProperty(key = PROP_TRUSTIFY_DA_PYTHON_INSTALL_BEST_EFFORTS, value = "true") void best_Efforts_Without_Virtual_Env_Should_Throw_Runtime_Exception() { String requirementsTxt = getFileFromString("requirements.txt", "flask==9.9.9\n"); - RuntimeException runtimeException = + IllegalStateException exception = assertThrows( - RuntimeException.class, + IllegalStateException.class, () -> pythonControllerRealEnv.getDependencies(requirementsTxt, true)); - assertTrue( - runtimeException.getMessage().contains(PROP_TRUSTIFY_DA_PYTHON_INSTALL_BEST_EFFORTS)); - assertTrue(runtimeException.getMessage().contains(PROP_TRUSTIFY_DA_PYTHON_VIRTUAL_ENV)); + assertTrue(exception.getMessage().contains(PROP_TRUSTIFY_DA_PYTHON_INSTALL_BEST_EFFORTS)); + assertTrue(exception.getMessage().contains(PROP_TRUSTIFY_DA_PYTHON_VIRTUAL_ENV)); } @Test From 92e3f2c594007c93974587d910ff4ffa379f9110 Mon Sep 17 00:00:00 2001 From: Adva Oren Date: Mon, 3 Aug 2026 19:17:24 +0300 Subject: [PATCH 3/5] refactor(python): extract bestEfforts variable and validate before prepareEnvironment Read Environment.getBoolean(PROP_TRUSTIFY_DA_PYTHON_INSTALL_BEST_EFFORTS) once into a local variable to avoid duplication and ensure consistency. Move the BEST_EFFORTS/VIRTUAL_ENV validation before prepareEnvironment() so invalid configurations fail before any side effects occur. Implements TC-5493 Assisted-by: Claude Code --- .../trustifyda/utils/PythonControllerBase.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/main/java/io/github/guacsec/trustifyda/utils/PythonControllerBase.java b/src/main/java/io/github/guacsec/trustifyda/utils/PythonControllerBase.java index 6d3ac76f..7ee7b385 100644 --- a/src/main/java/io/github/guacsec/trustifyda/utils/PythonControllerBase.java +++ b/src/main/java/io/github/guacsec/trustifyda/utils/PythonControllerBase.java @@ -75,11 +75,9 @@ void installPackages(String pathToRequirements) { public final List> getDependencies( String pathToRequirements, boolean includeTransitive) { - if (isVirtualEnv() || isRealEnv()) { - prepareEnvironment(pathToPythonBin); - } - if (Environment.getBoolean(PROP_TRUSTIFY_DA_PYTHON_INSTALL_BEST_EFFORTS, false) - && !automaticallyInstallPackageOnEnvironment()) { + boolean installBestEfforts = + Environment.getBoolean(PROP_TRUSTIFY_DA_PYTHON_INSTALL_BEST_EFFORTS, false); + if (installBestEfforts && !automaticallyInstallPackageOnEnvironment()) { throw new IllegalStateException( "Conflicting settings, " + PROP_TRUSTIFY_DA_PYTHON_INSTALL_BEST_EFFORTS @@ -87,9 +85,10 @@ public final List> getDependencies( + PROP_TRUSTIFY_DA_PYTHON_VIRTUAL_ENV + "=true"); } + if (isVirtualEnv() || isRealEnv()) { + prepareEnvironment(pathToPythonBin); + } if (automaticallyInstallPackageOnEnvironment()) { - boolean installBestEfforts = - Environment.getBoolean(PROP_TRUSTIFY_DA_PYTHON_INSTALL_BEST_EFFORTS, false); /* make best efforts to install the requirements.txt on the virtual environment created from the python3 passed in. that means that it will install the packages without referring to From b976123817e0691ac65621cdeb24d83b1ad12d8f Mon Sep 17 00:00:00 2001 From: Adva Oren Date: Tue, 4 Aug 2026 10:37:10 +0300 Subject: [PATCH 4/5] test(python): add explicit @SetSystemProperty for VIRTUAL_ENV in BEST_EFFORTS test Set PROP_TRUSTIFY_DA_PYTHON_VIRTUAL_ENV to "false" explicitly instead of relying on the default state, improving test isolation. Implements TC-5492 Assisted-by: Claude Code --- .../guacsec/trustifyda/utils/PythonControllerRealEnvTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/java/io/github/guacsec/trustifyda/utils/PythonControllerRealEnvTest.java b/src/test/java/io/github/guacsec/trustifyda/utils/PythonControllerRealEnvTest.java index eee26914..43fee7fd 100644 --- a/src/test/java/io/github/guacsec/trustifyda/utils/PythonControllerRealEnvTest.java +++ b/src/test/java/io/github/guacsec/trustifyda/utils/PythonControllerRealEnvTest.java @@ -340,6 +340,7 @@ void get_Dependency_Name_with_extras_and_special_operators() { @Test @RestoreSystemProperties @SetSystemProperty(key = PROP_TRUSTIFY_DA_PYTHON_INSTALL_BEST_EFFORTS, value = "true") + @SetSystemProperty(key = PROP_TRUSTIFY_DA_PYTHON_VIRTUAL_ENV, value = "false") void best_Efforts_Without_Virtual_Env_Should_Throw_Runtime_Exception() { String requirementsTxt = getFileFromString("requirements.txt", "flask==9.9.9\n"); IllegalStateException exception = From 0fbf99a9ca2876658f3906dbcf51fe04a183f8d0 Mon Sep 17 00:00:00 2001 From: Adva Oren Date: Tue, 4 Aug 2026 10:41:47 +0300 Subject: [PATCH 5/5] docs(python): document VIRTUAL_ENV requirement for BEST_EFFORTS Update README to clarify that BEST_EFFORTS=true requires both VIRTUAL_ENV=true and MATCH_MANIFEST_VERSIONS=false. Implements TC-5477 Assisted-by: Claude Code --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8c6f8e9d..f0451261 100644 --- a/README.md +++ b/README.md @@ -629,7 +629,7 @@ This increasing the chances and the probability a lot that the automatic install ##### Usage A New setting is introduced - `TRUSTIFY_DA_PYTHON_INSTALL_BEST_EFFORTS` (as both env variable/key in `options` object) 1. `TRUSTIFY_DA_PYTHON_INSTALL_BEST_EFFORTS`="false" - install requirements.txt while respecting declared versions for all packages. -2. `TRUSTIFY_DA_PYTHON_INSTALL_BEST_EFFORTS`="true" - install all packages from requirements.txt, not respecting the declared version, but trying to install a version tailored for the used python version, when using this setting,you must set setting `MATCH_MANIFEST_VERSIONS`="false" +2. `TRUSTIFY_DA_PYTHON_INSTALL_BEST_EFFORTS`="true" - install all packages from requirements.txt, not respecting the declared version, but trying to install a version tailored for the used python version. When using this setting, you must set `TRUSTIFY_DA_PYTHON_VIRTUAL_ENV`="true" and `MATCH_MANIFEST_VERSIONS`="false" ##### Using `pipdeptree` By Default, The API algorithm will use native commands of PIP installer as data source to build the dependency tree.