Validate wheel filenames are normalized during uv publish#17783
Conversation
aa63484 to
62f9dcb
Compare
uv publishuv publish
62f9dcb to
bff8903
Compare
| for group in groups { | ||
| // Check if the filename is normalized (e.g., version `2025.09.4` should be `2025.9.4`). | ||
| let normalized_filename = group.filename.to_string(); | ||
| if group.raw_filename != normalized_filename { |
There was a problem hiding this comment.
I think this has some more implications / raises design questions so I'll do this separately.
|
|
||
| for group in groups { | ||
| // Check if the filename is normalized (e.g., version `2025.09.4` should be `2025.9.4`). | ||
| let normalized_filename = group.filename.to_string(); |
There was a problem hiding this comment.
Curious if people are still using uppercase names in wheel filenames (people do complain when we lowercase), we should get some data from the preview period.
In distribution names, any run of -_. characters (HYPHEN-MINUS, LOW LINE and FULL STOP) should be replaced with _ (LOW LINE), and uppercase characters should be replaced with corresponding lowercase ones. This is equivalent to regular name normalization followed by replacing - with _. Tools consuming wheels must be prepared to accept . (FULL STOP) and uppercase letters, however, as these were allowed by an earlier version of this specification.
There was a problem hiding this comment.
Yeah hopefully the preview period helps.
| "`{}` has a non-normalized filename (expected `{normalized_filename}`), skipping", | ||
| group.raw_filename | ||
| ); | ||
| continue; |
There was a problem hiding this comment.
One scenario where would go wrong: You have a script that changes the filename for let's say mac (inspired by real events), and now you have an upload for the a release on PyPI except that mac is missing.
There was a problem hiding this comment.
Like one of the artifacts is bad?
There was a problem hiding this comment.
We could change the default to fail on bad filenames instead of skip, that seems separate from this change though.
There was a problem hiding this comment.
I'm thinking specifically about the case where multiple packages have the same distribution name, but only one (or any subset) fails a validation pass. For validation passes that can be done before upload, I'd treat at least all packages with the same name/version as the same bucket. It's something we couldn't do in the previous stages, as we don't know the distribution name before parsing it. (The underlying assumption is that it's more likely that people will do something that fails out validation pass(es) than to create an outright non-parsing wheel filename)
There was a problem hiding this comment.
That makes sense. I think I'd prefer to change this behavior separately from this pull request because we currently have skipping and don't implement group-based behaviors.
a6831d7 to
e814434
Compare
e814434 to
4110fa2
Compare
This MR contains the following updates: | Package | Update | Change | |---|---|---| | [uv](https://github.com/astral-sh/uv) | patch | `0.10.4` → `0.10.6` | MR created with the help of [el-capitano/tools/renovate-bot](https://gitlab.com/el-capitano/tools/renovate-bot). **Proposed changes to behavior should be submitted there as MRs.** --- ### Release Notes <details> <summary>astral-sh/uv (uv)</summary> ### [`v0.10.6`](https://github.com/astral-sh/uv/blob/HEAD/CHANGELOG.md#0106) [Compare Source](astral-sh/uv@0.10.5...0.10.6) Released on 2026-02-24. ##### Bug fixes - Apply lockfile marker normalization for fork markers ([#​18116](astral-sh/uv#18116)) - Fix Python version selection for scripts with a `requires-python` conflicting with `.python-version` ([#​18097](astral-sh/uv#18097)) - Preserve file permissions when using reflinks on Linux ([#​18187](astral-sh/uv#18187)) ##### Documentation - Remove verbose documentation from optional dependencies help text ([#​18180](astral-sh/uv#18180)) ### [`v0.10.5`](https://github.com/astral-sh/uv/blob/HEAD/CHANGELOG.md#0105) [Compare Source](astral-sh/uv@0.10.4...0.10.5) Released on 2026-02-23. ##### Enhancements - Add hint when named index is found in a parent config file ([#​18087](astral-sh/uv#18087)) - Add warning for `uv lock --frozen` ([#​17859](astral-sh/uv#17859)) - Attempt to use reflinks by default on Linux ([#​18117](astral-sh/uv#18117)) - Fallback to hardlinks after reflink failure before copying ([#​18104](astral-sh/uv#18104)) - Filter `pylock.toml` wheels by tags and `requires-python` ([#​18081](astral-sh/uv#18081)) - Validate wheel filenames are normalized during `uv publish` ([#​17783](astral-sh/uv#17783)) - Fix message when `exclude-newer` invalidates the lock file ([#​18100](astral-sh/uv#18100)) - Change the missing files log level to debug ([#​18075](astral-sh/uv#18075)) ##### Performance - Improve performance of repeated conflicts with an extra ([#​18094](astral-sh/uv#18094)) ##### Bug fixes - Fix `--no-emit-workspace` with `--all-packages` on single-member workspaces ([#​18098](astral-sh/uv#18098)) - Fix `UV_NO_DEFAULT_GROUPS` rejecting truthy values like `1` ([#​18057](astral-sh/uv#18057)) - Fix iOS detection ([#​17973](astral-sh/uv#17973)) - Propagate project-level conflicts to package extras ([#​18096](astral-sh/uv#18096)) - Use a global build concurrency semaphore ([#​18054](astral-sh/uv#18054)) ##### Documentation - Update documentation heading for environment variable files ([#​18122](astral-sh/uv#18122)) - Fix comment about `uv export` formats ([#​17900](astral-sh/uv#17900)) - Make it clear that Windows is supported in user- and system- level configuration docs ([#​18106](astral-sh/uv#18106)) </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever MR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this MR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box --- This MR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4zMS4xIiwidXBkYXRlZEluVmVyIjoiNDMuMzEuOSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiUmVub3ZhdGUgQm90IiwiYXV0b21hdGlvbjpib3QtYXV0aG9yZWQiLCJkZXBlbmRlbmN5LXR5cGU6OnBhdGNoIl19-->
I noticed this because pyx rejected a wheel that uv did not skip. This warns, e.g., when the version component is not normalized, but still attempts the upload on stable. Under preview we skip the wheel, as we do for other invalid wheel filenames.