Repository navigation
Conversation
An unclean upgrade can leave a stale `.dist-info` beside the installed one, and because the order of `os.listdir` is arbitrary, which of them answered a query was a matter of chance. Consider the children in reverse lexicographic order so the greater one is found first. The ordering is lexicographic on the directory name and not on the parsed version, so it only approximates a preference for the newer version, but it needs no version parser and so is available to the stdlib. Ref python/cpython#100666. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Addresses python/cpython#100666.
An unclean upgrade can leave a stale
.dist-infobeside the installed one.Lookupbuilds its per-name buckets straight fromos.listdir, whose order is arbitrary, so which of the two answeredversion('torch')was a matter of chance.Lookup.__init__now considers the children in reverse lexicographic order (case-insensitively), the ordering preferred in the issue discussion. Because the buckets are built in that order andDistribution._prefer_validpartitions stably, the composition is: valid distributions first, and among those, the greater directory name first.The sort lives in
Lookuprather thanFastPath.children()so that zip-backed children, which come back as a dict, are covered too.Limitation
The ordering is lexicographic on the directory name, not on the parsed version, so
foo-1.9.0still sorts abovefoo-1.13.1. It therefore only approximates a preference for the newer version and won't resolve every instance of the reported condition. Parsing versions would require a version parser unavailable to the stdlib, so this is the heuristic on offer; theLookup.__init__docstring says so plainly rather than letting the change imply more than it delivers.Tests
MultipleVersionsTestsuses versions chosen so that lexicographic and version order disagree, which both exercises the heuristic and documents its limit:test_greater_version_preferred— retrieval by name resolves to the greatesttest_discovery_order— the full discovered sequence, so preferring one doesn't hide the resttest_greater_version_preferred_in_eggs— the same for legacy.egg-infotest_validity_preferred_to_version— a valid older distribution still beats an invalid newer one, the exact condition in the report (regression guard for Ensure stale empty python module directories don't break the build #489)The first three fail with the sort reverted. An earlier two-version form of them passed without the fix by luck of the APFS listing order, hence the four versions and the exact-sequence assertion.
toxpasses locally: 225 tests, mypy and ruff clean, perf within noise. Run with--ignore=.claude, as a stale git worktree under.claude/worktrees/in my checkout gets collected by pytest and breaks the run independently of this change.🤖 Generated with Claude Code