Skip to content

fix(python): link uv.lock dependents to the locked version they name - #5351

Merged
wagoodman merged 2 commits into
anchore:mainfrom
devtechedge:fix/uv-lock-locked-versions
Sep 29, 2026
Merged

wagoodman merged 2 commits into
anchore:mainfrom
devtechedge:fix/uv-lock-locked-versions

Conversation

@devtechedge

Copy link
Copy Markdown
Contributor

Description

When a uv.lock locks several versions of one package, dependents were linked to every locked version of a dependency instead of the versions they name.

The lock file records a version on each dependency entry in that forked case, but the parser never read the field, so provides and requires were bare names and Resolve paired every combination.

The fix reads the entry version and carries it through as a name@version ref on both sides. Entries without a version keep the bare name, so unique locks resolve exactly as before. Marker text is unchanged, and the poetry, pdm, and pip parsers are untouched.

The new Version field on PythonUvLockDependencyEntry is json:"-" on purpose. It only pairs relationships in memory, so no schema version bump or regenerated schema file is needed.

Type of change

  • Bug fix (non-breaking change which fixes an issue)

Checklist

  • I have added unit tests that cover changed behavior
  • I have tested my code in common scenarios and confirmed there are no regressions
  • I have added comments to my code, particularly in hard-to-understand sections

Testing

New fixture testdata/uv/forked-versions/uv.lock locks pandas 2.3.3 and 3.0.6 against numpy 1.26.4 and 2.2.6. TestParseUvLockForkedVersions fails on main with 4 relationships (both pandas depend on both numpy) and passes with 2 after the fix. All uv, poetry, pdm, pip, and requirements parser tests pass locally.

Fixes #5340

A forked uv.lock can lock several versions of one package, and uv records the version on each dependency entry in that case. The parser dropped that field, so every pandas version depended on every numpy version. Carry the locked version through provides and requires as name@version (bare name stays for unique locks) and keep marker text unchanged.

Fixes #5340

Signed-off-by: Dev M <devtechedge@gmail.com>
devtechedge added a commit to devtechedge/oss-contributions that referenced this pull request Sep 29, 2026
- the locked version on a uv dependency entry is only needed to pair relationships, and the relationships already carry it, so it stays on the internal toml struct instead of `pkg.PythonUvLockDependencyEntry`. The previous approach hid it from JSON but still hashed it into package IDs.
- dependency specs are now built from the raw lock entries at parse time rather than read back off package metadata
- optional-dependencies get the same version pairing, so an extra that names one locked version no longer links to all of them

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
@wagoodman wagoodman self-assigned this Sep 29, 2026
@wagoodman wagoodman added this to OSS Sep 29, 2026
@wagoodman wagoodman moved this to In Review in OSS Sep 29, 2026
@wagoodman
wagoodman enabled auto-merge (squash) September 29, 2026 21:07
@wagoodman
wagoodman disabled auto-merge September 29, 2026 21:23
@wagoodman
wagoodman merged commit 37d45de into anchore:main Sep 29, 2026
15 checks passed
@devtechedge

Copy link
Copy Markdown
Contributor Author

Alex, I appreciate the quick review and merge.

Digging into how uv stamps a version on each dependency entry when a name locks twice made the name@version pairing feel obvious in hindsight.

Keeping bare-name edges for unique locks while requiring the locked ref for forked ones kept the change small.

This one was genuinely fun to work through!

spiffcs added a commit that referenced this pull request Sep 30, 2026
* main: (91 commits)
  feat: catalog CPAN distributions installed by perl clients (#5131)
  fix(binary): correct traefik version detection on big-endian arches (#5281)
  Fix hang when scanning a Java resource adapter (.rar) file (#5348)
  chore(deps): update SPDX license list (#5315)
  fix: match opensource.org license URLs across SPDX URL forms (#5361)
  Speed up unit tests in CI (#5360)
  Fix missing file hashes when running on windows system (#5341)
  Stop reading the mount table for every single-file source (#5257)
  fix: conan expat CPE (#5259)
  fix(spdx): write a name for the root package when the source has none (#5349)
  fix(python): link uv.lock dependents to the locked version they name (#5351)
  fix: suppress misleading upstream CPE for PHP extension binaries (#5102)
  fix: report scanner errors and raise the line cap in metadata parsers (#5353)
  Harden cataloger parsers against truncated input (do not panic) (#5355)
  fix(cpe): bound CPE candidate generation for pathological package metadata (#5356)
  test(golang): make the UPX fixture exercise loader padding (#5354)
  fix(golang): account for UPX's loader padding when unpacking Go binaries (#5347)
  test(snap): bound the kernel changelog bomb fixture by ratio, not a fixed 1MB (#5352)
  test(debian): bound the bomb fixture by ratio, not a fixed 1MB (#5350)
  fix(ai): handle malformed GGUF headers without panicking (#5345)
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

uv.lock: dependents are linked to every locked version of a dependency

2 participants