Skip to content

fix: skip PEP 508 marker-constrained packages in pip provider#400

Merged
ruromero merged 3 commits intoguacsec:mainfrom
ruromero:TC-4044
Apr 14, 2026
Merged

fix: skip PEP 508 marker-constrained packages in pip provider#400
ruromero merged 3 commits intoguacsec:mainfrom
ruromero:TC-4044

Conversation

@ruromero
Copy link
Copy Markdown
Collaborator

@ruromero ruromero commented Apr 9, 2026

Summary

  • Skip packages with PEP 508 environment markers (; separator) that are not installed in the current pip environment, instead of throwing PackageNotInstalledException
  • Strip marker suffixes from version strings before version-match comparison to prevent mismatches
  • Add test with mocked pip freeze/show data verifying pywin32 (Windows-only marker) is excluded while certifi (marker, installed) and six (no marker) are included
  • Fix getDependencyName() to strip PEP 508 marker suffix before scanning for version operators, preventing malformed names for marker-only requirements (TC-4085)
  • Use marker-stripped requirement spec for version matching in getDependenciesImpl() to prevent false-positive == detection from marker expressions

Closes: TC-4044

Test plan

  • New unit test test_marker_constrained_uninstalled_packages_are_skipped_in_component_analysis passes
  • New unit test test_marker_only_installed_packages_are_included_in_component_analysis passes
  • New unit test get_Dependency_Name_with_markers passes
  • All existing Python provider tests continue to pass
  • mvn spotless:apply produces no changes

🤖 Generated with Claude Code

@qodo-code-review
Copy link
Copy Markdown
Contributor

Review Summary by Qodo

Skip PEP 508 marker-constrained uninstalled packages in pip provider

🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Skip PEP 508 marker-constrained packages not installed in current environment
• Strip marker suffixes from version strings before comparison
• Add comprehensive test with mocked pip data validating marker handling
Diagram
flowchart LR
  A["Requirements with markers"] --> B["Check for semicolon marker"]
  B --> C["Strip marker from version"]
  C --> D["Compare versions"]
  B --> E["Check if package installed"]
  E --> F{Package in cache?}
  F -->|No| G["Skip package"]
  F -->|Yes| H["Include in SBOM"]
Loading

Grey Divider

File Changes

1. src/main/java/io/github/guacsec/trustifyda/utils/PythonControllerBase.java 🐞 Bug fix +7/-0

Handle PEP 508 markers in dependency processing

• Strip PEP 508 marker suffixes (after ;) from version strings before version comparison
• Add check to skip packages with markers that are not present in cached environment dependencies
• Prevents PackageNotInstalledException for platform-specific packages like pywin32

src/main/java/io/github/guacsec/trustifyda/utils/PythonControllerBase.java


2. src/test/java/io/github/guacsec/trustifyda/providers/Python_Provider_Test.java 🧪 Tests +38/-0

Test marker-constrained package skipping behavior

• Add new test test_marker_constrained_uninstalled_packages_are_skipped_in_component_analysis
• Mock pip freeze and show output with Windows-only pywin32 package and installed six and
 certifi
• Verify SBOM correctly excludes uninstalled marker-constrained packages

src/test/java/io/github/guacsec/trustifyda/providers/Python_Provider_Test.java


3. src/test/resources/tst_manifests/pip/pip_requirements_txt_marker_skip/requirements.txt 🧪 Tests +3/-0

Test manifest with PEP 508 markers

• Create test requirements file with three packages: six (no marker), certifi (with marker),
 pywin32 (Windows-only marker)
• Demonstrates handling of both installed and uninstalled marker-constrained dependencies

src/test/resources/tst_manifests/pip/pip_requirements_txt_marker_skip/requirements.txt


View more (1)
4. src/test/resources/tst_manifests/pip/pip_requirements_txt_marker_skip/expected_component_sbom.json 🧪 Tests +48/-0

Expected SBOM for marker-filtered packages

• Define expected SBOM output containing only six and certifi packages
• Confirms pywin32 is excluded from component analysis despite being in requirements
• Validates proper dependency graph structure for marker-filtered packages

src/test/resources/tst_manifests/pip/pip_requirements_txt_marker_skip/expected_component_sbom.json


Grey Divider

Qodo Logo

@qodo-code-review
Copy link
Copy Markdown
Contributor

qodo-code-review bot commented Apr 9, 2026

Code Review by Qodo

🐞 Bugs (4)   📘 Rule violations (0)   📎 Requirement gaps (0)   🎨 UX Issues (0)
🐞\ ≡ Correctness (1) ☼ Reliability (2) ◔ Observability (1) ⭐ New (2)

Grey Divider


Action required

1. Markers dropped on install 🐞
Description
installingRequirementsOneByOne() installs dependencies using getDependencyName(), but
getDependencyName() now strips everything after ';', so marker-constrained requirements are
installed unconditionally. This can cause best-efforts analysis to fail (attempting to install
non-applicable platform packages) or to include conditional packages that should have been skipped.
Code

src/main/java/io/github/guacsec/trustifyda/utils/PythonControllerBase.java[R380-393]

  public static String getDependencyName(String dep) {
-    int rightTriangleBracket = dep.indexOf(">");
-    int leftTriangleBracket = dep.indexOf("<");
-    int equalsSign = dep.indexOf("=");
+    int markerSeparator = dep.indexOf(";");
+    String requirement = markerSeparator == -1 ? dep : dep.substring(0, markerSeparator);
+    int rightTriangleBracket = requirement.indexOf(">");
+    int leftTriangleBracket = requirement.indexOf("<");
+    int equalsSign = requirement.indexOf("=");
    int minimumIndex = getFirstSign(rightTriangleBracket, leftTriangleBracket, equalsSign);
    String depName;
    if (rightTriangleBracket == -1 && leftTriangleBracket == -1 && equalsSign == -1) {
-      depName = dep;
+      depName = requirement;
    } else {
-      depName = dep.substring(0, minimumIndex);
+      depName = requirement.substring(0, minimumIndex);
    }
    return depName.trim();
Evidence
Best-efforts installation derives the pip-install argument from getDependencyName(dependency), and
the updated getDependencyName implementation explicitly removes the marker suffix by truncating at
';', so pip never sees the marker constraint during installation.

src/main/java/io/github/guacsec/trustifyda/utils/PythonControllerBase.java[113-132]
src/main/java/io/github/guacsec/trustifyda/utils/PythonControllerBase.java[380-394]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`installingRequirementsOneByOne()` uses `getDependencyName()` to construct the argument passed to `pip install`. After this PR, `getDependencyName()` strips PEP 508 marker suffixes (`; ...`), which prevents pip from evaluating markers and causes conditional dependencies to be installed unconditionally.

### Issue Context
This path is exercised when `TRUSTIFY_DA_PYTHON_INSTALL_BEST_EFFORTS=true` (virtualenv best-efforts mode). Marker constraints are part of the requirement semantics; stripping them changes what gets installed and can break analysis on non-applicable platforms.

### Fix Focus Areas
- src/main/java/io/github/guacsec/trustifyda/utils/PythonControllerBase.java[113-132]
- src/main/java/io/github/guacsec/trustifyda/utils/PythonControllerBase.java[380-394]

### Suggested approach
In `installingRequirementsOneByOne`, build the install spec in a marker-preserving way (e.g., extract marker suffix separately and append it back to the package name you install), or avoid using `getDependencyName()` for this install path so pip can evaluate markers.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Marker-only deps misparsed 🐞
Description
getDependenciesImpl() may incorrectly skip a marker-constrained requirement when it uses a marker
but no version operator (e.g. pkg ; python_version < "3.8") because getDependencyName() does not
strip the ; ... suffix in that case. This causes selectedDepName to include the marker text,
leading to a cache miss and the dependency being treated as “not installed” and skipped even when it
is installed.
Code

src/main/java/io/github/guacsec/trustifyda/utils/PythonControllerBase.java[R215-219]

     String selectedDepName = getDependencyName(dep.toLowerCase());
+      boolean hasMarker = dep.contains(";");
+      if (hasMarker && cachedEnvironmentDeps.get(new StringInsensitive(selectedDepName)) == null) {
+        continue;
+      }
Evidence
The new skip behavior hinges on selectedDepName being a clean package name for the cache lookup.
However, getDependencyName() returns the whole input string when it contains no ` or =`
operators, so any marker-only requirement line will retain the ; ... portion and fail the cache
lookup, triggering the new continue skip. The codebase also explicitly supports unpinned
requirements lines (not matching name==version) via getDependencyName(), so marker-only lines
are within supported inputs.

src/main/java/io/github/guacsec/trustifyda/utils/PythonControllerBase.java[175-223]
src/main/java/io/github/guacsec/trustifyda/utils/PythonControllerBase.java[382-394]
src/main/java/io/github/guacsec/trustifyda/providers/PythonPipProvider.java[57-66]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Marker-constrained requirements that *don’t* include version operators (no `==`, `>=`, etc.) are currently parsed with the marker suffix included in the dependency name. With the new marker-skip logic, that malformed name causes a cache miss and the dependency gets skipped even if installed.
## Issue Context
`getDependencyName()` is used as the canonical way to extract a package name from a requirement string. Today it only considers `<`, `>` and `=` as delimiters.
## Fix Focus Areas
- src/main/java/io/github/guacsec/trustifyda/utils/PythonControllerBase.java[175-223]
- src/main/java/io/github/guacsec/trustifyda/utils/PythonControllerBase.java[382-405]
## What to change
- Update `getDependencyName(String dep)` (or a dedicated helper) to strip PEP 508 marker suffixes by cutting at the first `;` before applying the existing operator-based parsing.
- Alternatively (or additionally), in `getDependenciesImpl` compute `selectedDepName` from the pre-marker portion: `String requirement = dep.split(";", 2)[0].trim(); selectedDepName = getDependencyName(requirement.toLowerCase());`.
- Add/extend a unit test covering a marker-only line without version operators, ensuring it is included when installed and skipped when not installed.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

3. Silent marker dependency skipping 🐞
Description
getDependenciesImpl() silently skips any requirement containing ';' when the dependency is not
present in the cached environment map, without emitting any log. This can produce incomplete SBOM
results with no indication that some manifest requirements were dropped due to missing environment
packages.
Code

src/main/java/io/github/guacsec/trustifyda/utils/PythonControllerBase.java[R214-217]

+      String selectedDepName = getDependencyName(requirementSpec.toLowerCase());
+      if (hasMarker && cachedEnvironmentDeps.get(new StringInsensitive(selectedDepName)) == null) {
+        continue;
+      }
Evidence
The new logic checks only for presence of ';' and cache membership, then continues without any
logging/telemetry, meaning the omission is not visible to users/debug logs.

src/main/java/io/github/guacsec/trustifyda/utils/PythonControllerBase.java[175-221]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
Marker-constrained requirements that are not installed in the environment are skipped via `continue;` with no log. This makes SBOM incompleteness hard to detect/debug.

### Issue Context
The PR intentionally avoids throwing for marker-constrained packages missing from the current environment. Even if this is desired behavior, it should be observable.

### Fix Focus Areas
- src/main/java/io/github/guacsec/trustifyda/utils/PythonControllerBase.java[175-221]

### Suggested approach
Add a debug/info log when a marker requirement is skipped (include the original `dep` line and the parsed `selectedDepName`). Optionally gate logging behind `debugLoggingIsNeeded()` to avoid noise.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


4. Platform-dependent test newlines 🐞
Description
The new unit test hardcodes \n in mocked pip freeze/show output, but production parsing splits
on System.lineSeparator(). On Windows (\r\n), the mocked output won’t split correctly, making
the test (and env-var based mocking) platform-dependent.
Code

src/test/java/io/github/guacsec/trustifyda/providers/Python_Provider_Test.java[R231-243]

+    // pip environment where only six and certifi are installed (pywin32 is Windows-only)
+    String pipFreezeContent = "six==1.16.0\ncertifi==2023.7.22\n";
+    String pipShowContent =
+        "Name: certifi\nVersion: 2023.7.22\nSummary: Python package for providing Mozilla's CA"
+            + " Bundle.\nRequires: \nRequired-by: \n---\nName: six\nVersion: 1.16.0\nSummary:"
+            + " Python 2 and 3 compatibility utilities\nRequires: \nRequired-by: ";
+    System.setProperty(
+        PROP_TRUSTIFY_DA_PIP_FREEZE,
+        new String(Base64.getEncoder().encode(pipFreezeContent.getBytes())));
+    System.setProperty(
+        PROP_TRUSTIFY_DA_PIP_SHOW,
+        new String(Base64.getEncoder().encode(pipShowContent.getBytes())));
+
Evidence
The test injects pipFreezeContent/pipShowContent with \n, while
fillCacheWithEnvironmentDeps() splits freeze output by System.lineSeparator() and
splitPipShowLines() splits show output on System.lineSeparator()+"---"+System.lineSeparator().
On platforms where System.lineSeparator() is not \n, the injected data won’t be parsed into the
intended lines/blocks.

src/test/java/io/github/guacsec/trustifyda/providers/Python_Provider_Test.java[214-250]
src/main/java/io/github/guacsec/trustifyda/utils/PythonControllerBase.java[408-412]
src/main/java/io/github/guacsec/trustifyda/utils/PythonControllerBase.java[434-440]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The test constructs mocked pip outputs using hardcoded `\n`, but the parser splits on `System.lineSeparator()`, which will break on Windows.
## Issue Context
The mocking path (`TRUSTIFY_DA_PIP_FREEZE` / `TRUSTIFY_DA_PIP_SHOW`) is intended to simulate real pip output, which uses platform-native newlines.
## Fix Focus Areas
- src/test/java/io/github/guacsec/trustifyda/providers/Python_Provider_Test.java[231-243]
## What to change
- Build `pipFreezeContent` using `String.join(System.lineSeparator(), ...) + System.lineSeparator()`.
- Build `pipShowContent` using `System.lineSeparator()` consistently around the `---` separator.
- (Optional, more robust) normalize newlines in production parsing when decoding env-provided outputs (e.g., replace `\r\n` with `\n` and split on `\n`).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Grey Divider

Previous review results

Review updated until commit c1292e7

Results up to commit 310c568


🐞 Bugs (2)  
📘 Rule violations (0)  
📎 Requirement gaps (0)  
🎨 UX Issues (0)

🐞\ ≡ Correctness (1) ☼ Reliability (1)

Grey Divider


Action required

1. Marker-only deps misparsed 🐞
Description
getDependenciesImpl() may incorrectly skip a marker-constrained requirement when it uses a marker
but no version operator (e.g. pkg ; python_version < "3.8") because getDependencyName() does not
strip the ; ... suffix in that case. This causes selectedDepName to include the marker text,
leading to a cache miss and the dependency being treated as “not installed” and skipped even when it
is installed.
Code

src/main/java/io/github/guacsec/trustifyda/utils/PythonControllerBase.java[R215-219]

      String selectedDepName = getDependencyName(dep.toLowerCase());
+      boolean hasMarker = dep.contains(";");
+      if (hasMarker && cachedEnvironmentDeps.get(new StringInsensitive(selectedDepName)) == null) {
+        continue;
+      }
Evidence
The new skip behavior hinges on selectedDepName being a clean package name for the cache lookup.
However, getDependencyName() returns the whole input string when it contains no <, > or =
operators, so any marker-only requirement line will retain the ; ... portion and fail the cache
lookup, triggering the new continue skip. The codebase also explicitly supports unpinned
requirements lines (not matching name==version) via getDependencyName(), so marker-only lines
are within supported inputs.

src/main/java/io/github/guacsec/trustifyda/utils/PythonControllerBase.java[175-223]
src/main/java/io/github/guacsec/trustifyda/utils/PythonControllerBase.java[382-394]
src/main/java/io/github/guacsec/trustifyda/providers/PythonPipProvider.java[57-66]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Marker-constrained requirements that *don’t* include version operators (no `==`, `>=`, etc.) are currently parsed with the marker suffix included in the dependency name. With the new marker-skip logic, that malformed name causes a cache miss and the dependency gets skipped even if installed.

## Issue Context
`getDependencyName()` is used as the canonical way to extract a package name from a requirement string. Today it only considers `<`, `>` and `=` as delimiters.

## Fix Focus Areas
- src/main/java/io/github/guacsec/trustifyda/utils/PythonControllerBase.java[175-223]
- src/main/java/io/github/guacsec/trustifyda/utils/PythonControllerBase.java[382-405]

## What to change
- Update `getDependencyName(String dep)` (or a dedicated helper) to strip PEP 508 marker suffixes by cutting at the first `;` before applying the existing operator-based parsing.
- Alternatively (or additionally), in `getDependenciesImpl` compute `selectedDepName` from the pre-marker portion: `String requirement = dep.split(";", 2)[0].trim(); selectedDepName = getDependencyName(requirement.toLowerCase());`.
- Add/extend a unit test covering a marker-only line without version operators, ensuring it is included when installed and skipped when not installed.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Platform-dependent test newlines 🐞
Description
The new unit test hardcodes \n in mocked pip freeze/show output, but production parsing splits
on System.lineSeparator(). On Windows (\r\n), the mocked output won’t split correctly, making
the test (and env-var based mocking) platform-dependent.
Code

src/test/java/io/github/guacsec/trustifyda/providers/Python_Provider_Test.java[R231-243]

+    // pip environment where only six and certifi are installed (pywin32 is Windows-only)
+    String pipFreezeContent = "six==1.16.0\ncertifi==2023.7.22\n";
+    String pipShowContent =
+        "Name: certifi\nVersion: 2023.7.22\nSummary: Python package for providing Mozilla's CA"
+            + " Bundle.\nRequires: \nRequired-by: \n---\nName: six\nVersion: 1.16.0\nSummary:"
+            + " Python 2 and 3 compatibility utilities\nRequires: \nRequired-by: ";
+    System.setProperty(
+        PROP_TRUSTIFY_DA_PIP_FREEZE,
+        new String(Base64.getEncoder().encode(pipFreezeContent.getBytes())));
+    System.setProperty(
+        PROP_TRUSTIFY_DA_PIP_SHOW,
+        new String(Base64.getEncoder().encode(pipShowContent.getBytes())));
+
Evidence
The test injects pipFreezeContent/pipShowContent with \n, while
fillCacheWithEnvironmentDeps() splits freeze output by System.lineSeparator() and
splitPipShowLines() splits show output on System.lineSeparator()+"---"+System.lineSeparator().
On platforms where System.lineSeparator() is not \n, the injected data won’t be parsed into the
intended lines/blocks.

src/test/java/io/github/guacsec/trustifyda/providers/Python_Provider_Test.java[214-250]
src/main/java/io/github/guacsec/trustifyda/utils/PythonControllerBase.java[408-412]
src/main/java/io/github/guacsec/trustifyda/utils/PythonControllerBase.java[434-440]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The test constructs mocked pip outputs using hardcoded `\n`, but the parser splits on `System.lineSeparator()`, which will break on Windows.

## Issue Context
The mocking path (`TRUSTIFY_DA_PIP_FREEZE` / `TRUSTIFY_DA_PIP_SHOW`) is intended to simulate real pip output, which uses platform-native newlines.

## Fix Focus Areas
- src/test/java/io/github/guacsec/trustifyda/providers/Python_Provider_Test.java[231-243]

## What to change
- Build `pipFreezeContent` using `String.join(System.lineSeparator(), ...) + System.lineSeparator()`.
- Build `pipShowContent` using `System.lineSeparator()` consistently around the `---` separator.
- (Optional, more robust) normalize newlines in production parsing when decoding env-provided outputs (e.g., replace `\r\n` with `\n` and split on `\n`).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Grey Divider

Qodo Logo

Comment thread src/main/java/io/github/guacsec/trustifyda/utils/PythonControllerBase.java Outdated
@ruromero
Copy link
Copy Markdown
Collaborator Author

ruromero commented Apr 10, 2026

Verification Report for TC-4044 (commit 96dae1e)

Check Result Details
Review Feedback WARN 1 code change request from qodo-code-review bot — getDependencyName() misparses marker-only deps without version operators. Sub-task TC-4085 created.
Scope & Diff PASS Changes limited to PythonControllerBase.java (production fix) + test file and fixtures — all within task scope.
Commit History PASS 2 clean commits: implementation + test. Conventional format.
Sensitive Patterns PASS No credentials, tokens, or secrets detected.
CI Status PASS mvn verify passes (Spotless, Surefire).
Acceptance Criteria PASS All 4 criteria satisfied — see breakdown below.
Test Quality PASS Deterministic unit test covering the marker-skip path with realistic pip mock data.

Acceptance Criteria Breakdown

# Criterion Status
1 Packages with env markers not installed on current platform are silently excluded from SBOM PASSpywin32 with platform_system == "Windows" marker excluded when not in pip freeze
2 Packages with env markers that ARE installed are included normally PASScertifi with python_version >= "3" marker included when present in pip freeze
3 No changes to behavior for requirements without markers PASS — existing pip_requirements_txt_no_ignore and pip_requirements_txt_ignore tests still pass unchanged
4 Unit test covering the marker-skip path PASStest_marker_constrained_uninstalled_packages_are_skipped_in_component_analysis() added

Review Feedback Sub-tasks

Sub-task Description Status
TC-4085 Fix getDependencyName() to handle marker-only deps without version operators Created (blocks TC-4044)

🤖 Generated with Claude Code

@ruromero
Copy link
Copy Markdown
Collaborator Author

/review

@qodo-code-review
Copy link
Copy Markdown
Contributor

qodo-code-review bot commented Apr 10, 2026

Persistent review updated to latest commit c1292e7

@ruromero
Copy link
Copy Markdown
Collaborator Author

Verification Report for TC-4044 (commit c1292e7)

Check Result Details
Review Feedback PASS 1 prior code change request (TC-4085, already handled); 1 new suggestion (deliberate scope decision, no action)
Root-Cause Investigation N/A No new sub-tasks created in this run
Scope Containment PASS 1 source file + 2 test files + 4 test resources — all expected
Diff Size PASS 208 additions, 10 deletions, 7 files — proportionate to scope
Commit Traceability FAIL Neither commit references TC-4044; commit 2 references TC-4085 only
Sensitive Patterns PASS No matches
CI Status PASS All 37 checks pass (unit tests, integration tests across ubuntu/macos/windows)
Acceptance Criteria PASS 5 of 5 criteria met
Test Quality WARN 2 marker tests are parameterization candidates; 1 test missing doc comment
Verification Commands PASS mvn verify and mvn spotless:check both pass

Overall: FAIL

Issues requiring attention:

  1. Commit Traceability (FAIL): Neither commit message references the parent task TC-4044. Commit 1 should include TC-4044 in the message or body. Commit 2 correctly references TC-4085 but does not reference TC-4044.

Advisory (non-blocking):

  • Test Quality (WARN): test_marker_constrained_uninstalled_packages_are_skipped_in_component_analysis and test_marker_only_installed_packages_are_included_in_component_analysis share the same algorithm (load fixture → inject pip data → call provideComponent → assert SBOM) with different data values — candidates for @ParameterizedTest @MethodSource. Also, test_marker_constrained_uninstalled_packages_are_skipped_in_component_analysis is missing a doc comment.

This comment was AI-generated by sdlc-workflow/verify-pr v0.5.11.

ruromero and others added 3 commits April 13, 2026 19:47
…vironment

When a requirements.txt contains packages with environment markers (e.g.,
`pywin32==306 ; platform_system == "Windows"`), pip only installs packages
whose markers match the current platform. The component analysis now detects
the semicolon marker separator and silently skips packages that have markers
but are not present in the pip freeze cache, instead of throwing a
PackageNotInstalledException. Also strips marker suffixes from version
strings before version-match comparison.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ss requirements

getDependencyName() picked up operators from marker expressions (e.g.,
== in sys_platform == "win32") when a requirement had no version operator,
producing malformed names and cache misses. Strip the marker suffix (;)
before scanning for version operators in both getDependencyName() and the
version matching block in getDependenciesImpl().

Implements TC-4085

Assisted-by: Claude Code
Signed-off-by: Ruben Romero Montes <rromerom@redhat.com>
Copy link
Copy Markdown
Contributor

@a-oren a-oren left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@ruromero ruromero merged commit 1aee31c into guacsec:main Apr 14, 2026
38 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants