Skip to content

Fix bare requirements wheel paths not contesting VEX (#1587) - #1599

Open
Mikola Lysenko (mikolalysenko) wants to merge 3 commits into
mainfrom
agent/fix-requirements-bare-path-contest
Open

Mikola Lysenko (mikolalysenko) wants to merge 3 commits into
mainfrom
agent/fix-requirements-bare-path-contest

Conversation

@mikolalysenko

@mikolalysenko Mikola Lysenko (mikolalysenko) commented Oct 16, 2026 •

Copy link
Copy Markdown
Collaborator

LLM Description written by Claude Code:claude-opus-5-5

Fixes #1587

Summary

pip installs a requirements.txt line such as wheels/six-1.16.0-py3-none-any.whl, six-1.16.0-py3-none-any.whl or dist/six-1.16.0.tar.gz as a local, unpatched artifact. Before this fix, vex ignored those lines and attested not_affected for a Socket wiring of the same release in Pipfile.lock. Only the ./wheels/… spelling was withheld (#1562). These spellings now contest the wiring the same way, so vex withholds the statement with patched_ref_unattributable.

Root cause

requirement_location (crates/socket-patch-core/src/vex/discover/pypi_other.rs) read a line as a path only when its first character wasn't a letter or digit. pip's rule (_looks_like_path / _get_url_from_path) is different: a token is a path when it holds a path separator, starts with ., or names an archive file.

Changes

  • utils::requirements, the shared requirements grammar, gets pip's rule as pip_reads_as_path, with is_archive_file (pip's ARCHIVE_EXTENSIONS, and its splitext handling of .tar.<ext>), names_before_at and strip_path_extras.
  • requirement_location uses these helpers and now also follows pip on two more points:
    • A no-space six@https://… or six@wheels/…whl is a PEP 508 reference to six. Before, the url form was read as a bare url and lost its declared name.
    • A path's [extras] are cut before its filename is read, so wheels/six-…whl[socks] also contests.

Tests (red → green)

Covers Test main this PR
#1587 wheels/…whl, …whl, dist/…tar.gz, wheels\…whl, path with a ; marker, vendored Pipfile.lock wiring vex::discover::pypi_other::tests::issue_1549_non_socket_direct_references_contest_wiring (new cases) FAILED ok
#1587 parser vex::discover::pypi_other::tests::issue_1587_requirement_location_reads_paths_as_pip_does FAILED (left: None) ok
#1587 shared rule utils::requirements::tests::pip_reads_as_path_follows_pip (new helper) ok
#1587 real CLI vex, hosted and vendored wiring e2e_vex_lockfile pipenv::requirements_direct_reference_contests_the_lock_wiring (the issue's three spellings) FAILED (vex exit 0) ok

The red runs used main's pypi_other.rs with the new e2e cases in place.

Local runs:

  • cargo fmt --all -- --check: clean
  • cargo clippy --workspace --all-features -- -D warnings: clean
  • cargo test -p socket-patch-core --lib: 6536 passed, 4 failed. The 4 are chmod-based tests that can't fail under uid 0 in this sandbox: relax_loop_must_not_traverse_symlinked_root, an_unremovable_hidden_lock_keeps_every_store_entry, and the poetry and requirements write-failure tests. Other agent PRs report the same 4 on main.
  • e2e_vex_lockfile: 350 passed
  • e2e_vex_redirect (53), e2e_vex_vendor (52), in_process_redirect_pipenv (11), in_process_vendor_pypi_takeover (6), scan_requirements_lock_only (10) and scan_vendor_requirements_unwired (4): all pass
  • npm/pypi/gem wrappers: not touched, since they only dispatch the binary

CI and Bugbot

CI on 3a4de37: ci-ok green, no failed checks. Bugbot reviewed 3a4de37 and found no issues.

/code-review high

Fixed in 3a4de37:

  • six@https://… lost its declared name.
  • [extras] on a path hid its filename.
  • The archive test didn't split .tar.<ext> the way pip does.
  • The rule lived privately in VEX discovery. It now sits in the shared requirements grammar.

Not changed:

  • Rare archive suffixes pip accepts (.tar, .tbz, .txz, .tlz, .tar.lz, .tar.lzma) are now read as paths. The release can't be read from those filenames, though, so they still give no evidence, as before this PR. Real sdists use .tar.gz or .zip (PEP 625 requires .tar.gz). Widening the filename reader would also change the hosted rewriter and the lock inventory.
  • Hosted/vendored requirements writers: requirement_name still reads a bare path line as a name (wheels). These writers don't attest anything. Whether they should treat such a line as an install source of the package is a separate change, left as a follow-up.

🤖 Generated with Claude Code

https://claude.ai/code/session_01JM7idHTBGCQp9fzoGJviT3


Generated by Claude Code

Assisted-by: Claude Code:claude-opus-5-5
A requirements.txt line such as `wheels/six-1.16.0-py3-none-any.whl`,
`six-1.16.0-py3-none-any.whl` or `dist/six-1.16.0.tar.gz` is installed
by pip as a local, unpatched artifact. VEX discovery only treated a line
as a path when it began with `.`, `/` or another non-alphanumeric
character, so these spellings gave no evidence and `vex` attested
not_affected for a Socket wiring of the same release in Pipfile.lock.

Read a line as a path the way pip does: it holds a path separator,
starts with something other than a letter or digit, or names an
archive (`.whl`, `.tar.gz`, `.zip`, ...). `name@<location>` stays a
PEP 508 direct reference, as in pip.

Fixes #1587

Assisted-by: Claude Code:claude-opus-5-5
Move the "pip installs this as a local artifact" rule into
utils::requirements beside the shared requirements grammar, and follow
pip more closely:

- `six@https://...` (no spaces) is a PEP 508 reference to six, not a
  bare url, as pip reads it.
- A path's `[extras]` are cut before its filename is read, so
  `wheels/six-1.16.0-...whl[socks]` also contests the wiring.
- The archive test splits `.tar.<ext>` the way pip's splitext does.

Refs #1587

Assisted-by: Claude Code:claude-opus-5-5
@mikolalysenko
Mikola Lysenko (mikolalysenko) marked this pull request as ready for review October 16, 2026 04:48
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

BugBot review


Generated by Claude Code

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 3a4de37. Configure here.

@mikolalysenko Mikola Lysenko (mikolalysenko) added the Ready for review Agent-verified: mergeable, CI green, Bugbot clean — awaiting human review label Oct 16, 2026
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

Labeled Ready for review at head 3a4de37.

  • CI: 36/36 checks green (50 skipped). No main-wide failures.
  • Bugbot: reviewed 3a4de37, no findings; no open review threads.
  • Reviewer focus: requirement_location in crates/socket-patch-core/src/utils/requirements.rs now treats bare (alphanumeric-leading) wheel paths as paths, the way pip does; the pipenv e2e covers it.

Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Ready for review Agent-verified: mergeable, CI green, Bugbot clean — awaiting human review

Projects

None yet

2 participants