Skip to content

Validate wheel filenames are normalized during uv publish#17783

Merged
zanieb merged 1 commit intomainfrom
zb/publish-validate
Feb 18, 2026
Merged

Validate wheel filenames are normalized during uv publish#17783
zanieb merged 1 commit intomainfrom
zb/publish-validate

Conversation

@zanieb
Copy link
Member

@zanieb zanieb commented Jan 31, 2026

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.

@zanieb zanieb added the error messages Messaging when something goes wrong label Jan 31, 2026
@zanieb zanieb force-pushed the zb/publish-validate branch from aa63484 to 62f9dcb Compare January 31, 2026 19:36
@zanieb zanieb added the preview Experimental behavior label Jan 31, 2026
@zanieb zanieb changed the title Validate version components in wheel filenames during uv publish Validate wheel filenames are normalized during uv publish Jan 31, 2026
@zanieb zanieb force-pushed the zb/publish-validate branch from 62f9dcb to bff8903 Compare January 31, 2026 20:15
@zanieb zanieb marked this pull request as ready for review January 31, 2026 20:19
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 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you also check for pypi/warehouse#18129?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I can look at that.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah hopefully the preview period helps.

"`{}` has a non-normalized filename (expected `{normalized_filename}`), skipping",
group.raw_filename
);
continue;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like one of the artifacts is bad?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could change the default to fail on bad filenames instead of skip, that seems separate from this change though.

Copy link
Member

@konstin konstin Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@zanieb zanieb force-pushed the zb/publish-validate branch 2 times, most recently from a6831d7 to e814434 Compare February 4, 2026 23:15
@zanieb zanieb temporarily deployed to uv-test-publish February 4, 2026 23:19 — with GitHub Actions Inactive
Copy link
Member

@konstin konstin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(needs a rebase)

@zanieb zanieb force-pushed the zb/publish-validate branch from e814434 to 4110fa2 Compare February 18, 2026 15:52
@zanieb zanieb temporarily deployed to uv-test-publish February 18, 2026 15:56 — with GitHub Actions Inactive
@zanieb zanieb merged commit 56ebe1a into main Feb 18, 2026
51 of 52 checks passed
@zanieb zanieb deleted the zb/publish-validate branch February 18, 2026 16:07
tmeijn pushed a commit to tmeijn/dotfiles that referenced this pull request Feb 25, 2026
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 ([#&#8203;18116](astral-sh/uv#18116))
- Fix Python version selection for scripts with a `requires-python` conflicting with `.python-version` ([#&#8203;18097](astral-sh/uv#18097))
- Preserve file permissions when using reflinks on Linux ([#&#8203;18187](astral-sh/uv#18187))

##### Documentation

- Remove verbose documentation from optional dependencies help text ([#&#8203;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 ([#&#8203;18087](astral-sh/uv#18087))
- Add warning for `uv lock --frozen` ([#&#8203;17859](astral-sh/uv#17859))
- Attempt to use reflinks by default on Linux ([#&#8203;18117](astral-sh/uv#18117))
- Fallback to hardlinks after reflink failure before copying ([#&#8203;18104](astral-sh/uv#18104))
- Filter `pylock.toml` wheels by tags and `requires-python` ([#&#8203;18081](astral-sh/uv#18081))
- Validate wheel filenames are normalized during `uv publish` ([#&#8203;17783](astral-sh/uv#17783))
- Fix message when `exclude-newer` invalidates the lock file ([#&#8203;18100](astral-sh/uv#18100))
- Change the missing files log level to debug ([#&#8203;18075](astral-sh/uv#18075))

##### Performance

- Improve performance of repeated conflicts with an extra ([#&#8203;18094](astral-sh/uv#18094))

##### Bug fixes

- Fix `--no-emit-workspace` with `--all-packages` on single-member workspaces ([#&#8203;18098](astral-sh/uv#18098))
- Fix `UV_NO_DEFAULT_GROUPS` rejecting truthy values like `1` ([#&#8203;18057](astral-sh/uv#18057))
- Fix iOS detection ([#&#8203;17973](astral-sh/uv#17973))
- Propagate project-level conflicts to package extras ([#&#8203;18096](astral-sh/uv#18096))
- Use a global build concurrency semaphore ([#&#8203;18054](astral-sh/uv#18054))

##### Documentation

- Update documentation heading for environment variable files ([#&#8203;18122](astral-sh/uv#18122))
- Fix comment about `uv export` formats ([#&#8203;17900](astral-sh/uv#17900))
- Make it clear that Windows is supported in user- and system- level configuration docs ([#&#8203;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-->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

error messages Messaging when something goes wrong preview Experimental behavior

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants