Skip to content

Fix Python variant tagging in the Windows registry#19012

Merged
woodruffw merged 4 commits intomainfrom
ww/triage-18795
Apr 17, 2026
Merged

Fix Python variant tagging in the Windows registry#19012
woodruffw merged 4 commits intomainfrom
ww/triage-18795

Conversation

@woodruffw
Copy link
Copy Markdown
Member

@woodruffw woodruffw commented Apr 15, 2026

Summary

This adds a regression test and fix for #18795. I ran the test and confirmed reproduction before implementing the fix.

The underlying bug here happens only on Windows, and only when exercising the PEP 514 Python installation registration pathway (which the integration tests disable by default, since it involves global mutable state that leaks between tests). The bug itself is just an imprecision in how we compute the "tag" for the Python entry -- we weren't including the variant (the t in 3.14t), so two distinct installs (3.14 and 3.14t) would end up with the same registry tag. For an end user, this surfaces as Python installation entries missing when running uv python list.

One thing to note about the test here is that it does exercise the Windows registry pathway, which means that it intentionally bypasses the guardrail around global mutations in the integration tests. This is "fine" in the sense that there are on other tests observing that state at the moment, but I think it's a risk in terms of isolation (in the sense that devs who run our integration tests will actually observe global changes to their Python installations, plus any failure in the test means we won't clean up our global changes). Two options there:

  • I could try and harden/isolate the registry mutation pathways a bit more, e.g. we could add UV_DEV_WINDOWS_REGISTRY_COMPANY_KEY or something like that to do some more test-level isolation of HKCU writes. This still modifies global state, but at least it'll be more namespaced.
  • I could remove the integration test entirely, now that we've confirmed that the fix itself works. This leaves us without coverage, but given that the fix itself is ~2 lines that might be acceptable.

Fixes #18795.

Test Plan

This PR includes a regression test.

@woodruffw woodruffw self-assigned this Apr 15, 2026
@woodruffw woodruffw added the windows Specific to the Windows platform label Apr 15, 2026
@woodruffw woodruffw requested a review from zanieb April 16, 2026 14:27
@woodruffw woodruffw marked this pull request as ready for review April 16, 2026 14:28
@woodruffw
Copy link
Copy Markdown
Member Author

woodruffw commented Apr 16, 2026

Another thing to note: I'm not sure how this interacts with existing installations -- this fixes the "from scratch" pathway, but there are probably users out there already who have both GIL and freethreaded variants installed and marked in the registry. I'm going to look more into that.

Edit: I think what happens is that users will still see the stale registry/tag state until they explicitly upgrade or reinstall one of the variants. We could probably "fix" that by doing our orphaned registry entry removal on uv python install, but I'm not sure if that's worth it.

Comment thread crates/uv/tests/it/python_install.rs
Comment thread crates/uv-python/src/windows_registry.rs
@zanieb
Copy link
Copy Markdown
Member

zanieb commented Apr 16, 2026

@konstin is the owner of the Windows registry writes, fyi.

@zanieb
Copy link
Copy Markdown
Member

zanieb commented Apr 16, 2026

This is "fine" in the sense that there are no other tests observing that state at the moment

Why aren't other tests observing the state?

@woodruffw
Copy link
Copy Markdown
Member Author

Why aren't other tests observing the state?

The combination of #19012 (review) and UV_TEST_PYTHON_PATH means that all other tests bypass the registry read pathway by default:

.env(EnvVars::UV_TEST_PYTHON_PATH, self.python_path())

(So IIUC UV_PYTHON_INSTALL_REGISTRY controls the write path but separately none of our tests observe this global state because of UV_TEST_PYTHON_PATH. Which feels kind of brittle to me...)

@woodruffw woodruffw changed the title Add a regression test for #18795 Fix Python variant tagging in the Windows registry Apr 16, 2026
@woodruffw woodruffw requested a review from konstin April 16, 2026 14:53
@zanieb
Copy link
Copy Markdown
Member

zanieb commented Apr 16, 2026

I think it'd make sense to add a test-windows-registry feature flag (it can still be on by default)

We'd also need to force the tests to run serially if we ever add more. Alas.

Can we use something like UV_TEST_WINDOWS_REGISTRY_PREFIX and prepend a unique identifier which we then require on all reads and writes? (We don't need to implement it in this pull request, just discussing)

@woodruffw
Copy link
Copy Markdown
Member Author

I think it'd make sense to add a test-windows-registry feature flag (it can still be on by default)

SG, will do 🙂

Can we use something like UV_TEST_WINDOWS_REGISTRY_PREFIX and prepend a unique identifier which we then require on all reads and writes? (We don't need to implement it in this pull request, just discussing)

Yeah, I think so! This is what I meant with the first option in the PR comment:

I could try and harden/isolate the registry mutation pathways a bit more, e.g. we could add UV_DEV_WINDOWS_REGISTRY_COMPANY_KEY or something like that to do some more test-level isolation of HKCU writes. This still modifies global state, but at least it'll be more namespaced.

I can look into that with a follow-up PR, I think it's a good idea regardless (because at some point we'll probably want more coverage on these routes anyways).

@konstin
Copy link
Copy Markdown
Member

konstin commented Apr 17, 2026

I've so far avoided any tests that (intentionally) modify registry. The risk is that we permanently modify a developer machine, as there's no temp dir root or virtual filesystem for the registry. It's helpful if we can run it in CI, but I wouldn't run this test by default on developer machines.

The fix itself looks good.

@woodruffw
Copy link
Copy Markdown
Member Author

Agreed, I'll tweak this so that we only run test-windows-registry tests in CI.

Signed-off-by: William Woodruff <william@astral.sh>
Signed-off-by: William Woodruff <william@astral.sh>
Signed-off-by: William Woodruff <william@astral.sh>
@woodruffw
Copy link
Copy Markdown
Member Author

Done, PTAL!

Signed-off-by: William Woodruff <william@astral.sh>
@woodruffw woodruffw enabled auto-merge (squash) April 17, 2026 15:12
@woodruffw woodruffw merged commit 69e1f5f into main Apr 17, 2026
110 checks passed
@woodruffw woodruffw deleted the ww/triage-18795 branch April 17, 2026 15:24
zanieb pushed a commit to zaniebot/uv that referenced this pull request Apr 17, 2026
This adds a regression test and fix for astral-sh#18795. I ran the test and
confirmed reproduction before implementing the fix.

The underlying bug here happens only on Windows, and only when
exercising the PEP 514 Python installation registration pathway (which
the integration tests disable by default, since it involves global
mutable state that leaks between tests). The bug itself is just an
imprecision in how we compute the "tag" for the Python entry -- we
weren't including the variant (the `t` in `3.14t`), so two distinct
installs (`3.14` and `3.14t`) would end up with the same registry tag.
For an end user, this surfaces as Python installation entries missing
when running `uv python list`.

One thing to note about the test here is that it _does_ exercise the
Windows registry pathway, which means that it intentionally bypasses the
guardrail around global mutations in the integration tests. This is
"fine" in the sense that there are on other tests observing that state
at the moment, but I think it's a risk in terms of isolation (in the
sense that devs who run our integration tests will actually observe
global changes to their Python installations, plus any failure in the
test means we won't clean up our global changes). Two options there:

- I could try and harden/isolate the registry mutation pathways a bit
more, e.g. we could add `UV_DEV_WINDOWS_REGISTRY_COMPANY_KEY` or
something like that to do some more test-level isolation of HKCU writes.
This still modifies global state, but at least it'll be more namespaced.
- I could remove the integration test entirely, now that we've confirmed
that the fix itself works. This leaves us without coverage, but given
that the fix itself is ~2 lines that might be acceptable.

Fixes astral-sh#18795.

This PR includes a regression test.

---------

Signed-off-by: William Woodruff <william@astral.sh>
(cherry picked from commit 69e1f5f)
@zsol zsol added the bug Something isn't working label Apr 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working windows Specific to the Windows platform

Projects

None yet

Development

Successfully merging this pull request may close these issues.

When install the same number of python versions, GIL and no-GIL, installation record is missing.

4 participants