Skip to content

fix(vendor): recover pypi wheels for pdm/poetry/pipenv, not just uv - #165

Open
Mikola Lysenko (mikolalysenko) wants to merge 1 commit into
mainfrom
fix/repair-pypi-recovery-all-lock-kinds
Open

fix(vendor): recover pypi wheels for pdm/poetry/pipenv, not just uv#165
Mikola Lysenko (mikolalysenko) wants to merge 1 commit into
mainfrom
fix/repair-pypi-recovery-all-lock-kinds

Conversation

@mikolalysenko

@mikolalysenko Mikola Lysenko (mikolalysenko) commented Aug 12, 2026

Copy link
Copy Markdown
Collaborator

Problem

The pypi arm of recover_lock_entry (crates/socket-patch-core/src/vendor/lock_inventory.rs:1112, pre-fix) only accepted the uv_lock_package wiring kind:

let unit = wiring_original(entry, &["uv_lock_package"])

But every other pypi package manager records the pre-vendor resolution under its own kind — pdm writes pdm_lock_package (pypi_pdm.rs:44), poetry poetry_lock_package (pypi_poetry.rs:40), pipenv pipenv_lock_entry (pypi_pipenv.rs:42), bare pip requirements_line (pypi_requirements.rs:452). So repair could not rebuild a missing vendored wheel in a pdm/poetry/pipenv/pip project even when state.json held the full pre-vendor fragment (sha256 included).

Worse, the downstream diagnostic in repair_vendor.rs:580 (pre-fix) discarded the real reason and printed a false message — "the package is not installed ... the ledger records no recoverable registry fragment" — when the package was installed and the fragment was present (confirmed in prod: pdm + urllib3==1.26.18).

Fix

  • crates/socket-patch-core/src/vendor/lock_inventory.rs:1112 — the pypi arm now accepts all five pypi lock-fragment kinds (uv_lock_package, pdm_lock_package, poetry_lock_package, pipenv_lock_entry, requirements_line). pdm's static_urls lock inlines the wheel URL exactly like uv.lock ({url = "…", hash = "sha256:…"}, see the fixture at pypi_pdm.rs:662), so pure_wheel_from_uv_unit recovers it cleanly and repair can now fetch + verify it.
  • The URL-less formats (default pdm/poetry {file = …}, pipenv hashes only, pip --hash=) genuinely carry no fetchable registry URL — only uv.lock and pdm static_urls do. Those now return an accurate, actionable message ("… records the wheel hash but no fetchable registry URL … reinstall the package so repair can rebuild from the installed copy") instead of the uv-specific "no uv.lock fragment recorded".
  • crates/socket-patch-cli/src/commands/repair_vendor.rs:574 — the vendor_artifact_unrepairable path now surfaces that precise Unverifiable reason instead of the blanket, false "no recoverable registry fragment" text.

Test

crates/socket-patch-core/src/vendor/lock_inventory.rs (recover_tests):

  • recover_pypi_pdm_static_urls_recovers_pure_wheel — a pdm_lock_package fragment with static_urls (url = …) recovers the pure wheel (resolved URL + sha256). Fails before the fix: the uv-only wiring_original returns None, so recover_lock_entry(...).unwrap() panics.
  • recover_pypi_urlless_locks_report_no_fetchable_urlpoetry_lock_package / default-pdm_lock_package (file = …) and pipenv_lock_entry (JSON object) now return the accurate "no fetchable registry URL" error. Fails before the fix: those kinds hit the uv-specific "no uv.lock fragment recorded" message.

cargo test -p socket-patch-core --lib recover → 12 passed. cargo test -p socket-patch-cli --lib repair → 10 passed. Both crates build clean.

Scope

  • Kills sweep finding pypi-ledger-recovery-uv-only-repair-unrepairable (P1).
  • The task named pipenv_lock_package; the actual constant is pipenv_lock_entry (pypi_pipenv.rs:42) — used here.
  • Ecosystem reality: PyPI wheel download URLs are blake2b-based and not derivable from a filename+sha256, and there is no PyPI simple-index/JSON resolver in this repo (pypi vendoring rebuilds from the installed site-packages tree, see pypi_wheel.rs). So a registry fetch is only possible for lock formats that inline the URL (uv.lock, pdm static_urls). For the URL-less formats repair's primary path remains the installed copy; this PR makes recovery recognize their fragments and stops the false diagnostic, but does not add a registry resolver for them.
  • The revendor/rescan "skip message names uv.lock in a pdm/pipenv project" findings (revendor-emits-misleading-uv-lock-warning-in-pdm-project P2, rescan-skip-message-names-uvlock-in-pipenv-project P3) live in a different code path (the vendor skip/idempotency messaging, not recover_lock_entry) and are not touched here.
  • Touches repair_vendor.rs (one match arm) in addition to lock_inventory.rs; no overlap expected with other in-flight fixes.

🤖 Generated with Claude Code


Note

Medium Risk
Changes PyPI vendor repair and ledger recovery behavior for non-uv projects; incorrect recovery could block repairs or misreport causes, but does not alter auth or broad install paths.

Overview
PyPI ledger recovery in recover_lock_entry no longer only reads uv_lock_package wiring fragments. It now accepts pdm, poetry, pipenv, and requirements pre-vendor lock kinds as well, so repair can rebuild missing vendored wheels when state.json still holds those fragments (not only uv projects).

For lock shapes that record a wheel hash but no fetchable registry URL (default pdm/poetry file = …, pipenv hashes-only, pip --hash=), recovery returns an explicit message to reinstall and rebuild from the installed copy—instead of uv-specific or misleading “no recoverable fragment” text.

Repair diagnostics in repair_vendor now surfaces the precise PristineFetch::Unverifiable reason from recovery when a pristine fetch cannot proceed, rather than a blanket message that implied the ledger recorded nothing.

Tests cover pdm static_urls wheel recovery and URL-less lock error messaging across poetry/pdm/pipenv.

Reviewed by Cursor Bugbot for commit 22ec0f0. Configure here.

The pypi arm of `recover_lock_entry` only accepted the `uv_lock_package`
wiring kind, so `repair` could not rebuild a missing vendored wheel in
pdm/poetry/pipenv/pip projects even when state.json recorded the full
pre-vendor registry fragment (sha256 included). It also surfaced a false
diagnostic claiming the package "is not installed" and "the ledger
records no recoverable registry fragment" when both were present.

Accept every pypi lock-fragment kind (uv_lock_package, pdm_lock_package,
poetry_lock_package, pipenv_lock_entry, requirements_line). pdm's
`static_urls` locks inline the wheel URL exactly like uv.lock and now
recover cleanly; the URL-less formats get an accurate, actionable message
instead of the false one, and repair_vendor surfaces that precise reason
rather than the blanket "no recoverable registry fragment".

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.

1 participant