Skip to content

fix(wheelfile): resolve .dist-info path case-insensitively when reading wheels#686

Merged
agronholm merged 5 commits intopypa:mainfrom
armorbreak001:fix/normalize-dist-info-unpack
Apr 22, 2026
Merged

fix(wheelfile): resolve .dist-info path case-insensitively when reading wheels#686
agronholm merged 5 commits intopypa:mainfrom
armorbreak001:fix/normalize-dist-info-unpack

Conversation

@armorbreak001
Copy link
Copy Markdown
Contributor

Summary

A wheel filename may contain non-lowercase characters (e.g.Django-3.2.5.whl) while the .dist-info directory inside uses normalized lowercase naming (django-3.2.5.dist-info/). WheelFile previously derived dist_info_path strictly from the filename, causing a Missing RECORD file error on open.

Fixes #411

Details

When opening a wheel in read mode, if the expected .dist-info/RECORD path is not found in the zip namelist, search for a case-insensitive match and use the resolved path for all subsequent operations (RECORD parsing, hash skipping).

The fix is confined to WheelFile.__init__ and only activates when the exact-path lookup fails, so there is no performance impact on wheels that already match.

…ng wheels

A wheel filename may contain non-lowercase characters (e.g. Django-3.2.5.whl)
while the .dist-info directory inside uses normalized lowercase naming
(django-3.2.5.dist-info/). WheelFile previously derived dist_info_path
strictly from the filename, causing a 'Missing RECORD file' error on open.

Resolve the actual .dist-info/RECORD path case-insensitively from the zip
namelist when the expected path is not found.

Fixes pypa#411
@agronholm
Copy link
Copy Markdown
Contributor

This requires an accompanying regression test and a changelog entry. Will you add those?

Add test_mixed_case_dist_info that creates a wheel with uppercase
filename (MixedCase-1.0-py3-none-any.whl) but lowercase .dist-info
directory inside, verifying WheelFile resolves RECORD correctly.

Also fix the case-insensitive search term to use lowercase '/record'
instead of '/RECORD' when comparing with name.lower().

Add changelog entry in docs/news.rst.
@armorbreak001
Copy link
Copy Markdown
Contributor Author

Thanks for the review! Added regression test + changelog entry. Also fixed a secondary bug in the case-insensitive search term (was /RECORD, now /record to match .lower() comparison). All 21 tests pass.

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 22, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 55.39%. Comparing base (5718957) to head (c6303cb).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #686      +/-   ##
==========================================
+ Coverage   55.14%   55.39%   +0.25%     
==========================================
  Files          15       15              
  Lines        1206     1213       +7     
==========================================
+ Hits          665      672       +7     
  Misses        541      541              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@agronholm agronholm merged commit d5a1763 into pypa:main Apr 22, 2026
16 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.

wheel unpack does not accept an archive with normalized .dist-info directory name

2 participants