mirror of
https://github.com/astral-sh/uv.git
synced 2025-07-07 21:35:00 +00:00

## Summary In preview mode on windows, register und un-register the managed python build standalone installations in the Windows registry following PEP 514. We write the values defined in the PEP plus the download URL and hash. We add an entry when installing a version, remove an entry when uninstalling and removing all values when uninstalling with `--all`. We update entries only by overwriting existing values, there is no "syncing" involved. Since they are not official builds, pbs gets a prefix. `py -V:Astral/CPython3.13.1` works, `py -3.13` doesn't. ``` $ py --list-paths -V:3.12 * C:\Users\Konsti\AppData\Local\Programs\Python\Python312\python.exe -V:3.11.9 C:\Users\Konsti\.pyenv\pyenv-win\versions\3.11.9\python.exe -V:3.11 C:\Users\micro\AppData\Local\Programs\Python\Python311\python.exe -V:3.8 C:\Users\micro\AppData\Local\Programs\Python\Python38\python.exe -V:Astral/CPython3.13.1 C:\Users\Konsti\AppData\Roaming\uv\data\python\cpython-3.13.1-windows-x86_64-none\python.exe ``` Registry errors are reported but not fatal, except for operations on the company key since it's not bound to any specific python interpreter. On uninstallation, we prune registry entries that have no matching Python installation (i.e. broken entries). The code uses the official `windows_registry` crate of the `winreg` crate. Best reviewed commit-by-commit. ## Test Plan We're reusing an existing system check to test different (un)installation scenarios.
119 lines
4 KiB
Rust
119 lines
4 KiB
Rust
//! Microsoft Store Pythons don't register themselves in the registry, so we have to look for them
|
|
//! in known locations.
|
|
//!
|
|
//! Effectively a port of <https://github.com/python/cpython/blob/58ce131037ecb34d506a613f21993cde2056f628/PC/launcher2.c#L1744>
|
|
|
|
use crate::windows_registry::WindowsPython;
|
|
use crate::PythonVersion;
|
|
use itertools::Either;
|
|
use std::env;
|
|
use std::path::PathBuf;
|
|
use std::str::FromStr;
|
|
use tracing::debug;
|
|
use uv_static::EnvVars;
|
|
|
|
#[derive(Debug)]
|
|
struct MicrosoftStorePython {
|
|
family_name: &'static str,
|
|
version: &'static str,
|
|
}
|
|
|
|
/// List of known Microsoft Store Pythons.
|
|
///
|
|
/// Copied from <https://github.com/python/cpython/blob/58ce131037ecb34d506a613f21993cde2056f628/PC/launcher2.c#L1963-L1985>,
|
|
/// please update when upstream changes.
|
|
const MICROSOFT_STORE_PYTHONS: &[MicrosoftStorePython] = &[
|
|
// Releases made through the Store
|
|
MicrosoftStorePython {
|
|
family_name: "PythonSoftwareFoundation.Python.3.13_qbz5n2kfra8p0",
|
|
version: "3.13",
|
|
},
|
|
MicrosoftStorePython {
|
|
family_name: "PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0",
|
|
version: "3.12",
|
|
},
|
|
MicrosoftStorePython {
|
|
family_name: "PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0",
|
|
version: "3.11",
|
|
},
|
|
MicrosoftStorePython {
|
|
family_name: "PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0",
|
|
version: "3.10",
|
|
},
|
|
MicrosoftStorePython {
|
|
family_name: "PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0",
|
|
version: "3.9",
|
|
},
|
|
MicrosoftStorePython {
|
|
family_name: "PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0",
|
|
version: "3.8",
|
|
},
|
|
// Side-loadable releases
|
|
MicrosoftStorePython {
|
|
family_name: "PythonSoftwareFoundation.Python.3.13_3847v3x7pw1km",
|
|
version: "3.13",
|
|
},
|
|
MicrosoftStorePython {
|
|
family_name: "PythonSoftwareFoundation.Python.3.12_3847v3x7pw1km",
|
|
version: "3.12",
|
|
},
|
|
MicrosoftStorePython {
|
|
family_name: "PythonSoftwareFoundation.Python.3.11_3847v3x7pw1km",
|
|
version: "3.11",
|
|
},
|
|
MicrosoftStorePython {
|
|
family_name: "PythonSoftwareFoundation.Python.3.11_hd69rhyc2wevp",
|
|
version: "3.11",
|
|
},
|
|
MicrosoftStorePython {
|
|
family_name: "PythonSoftwareFoundation.Python.3.10_3847v3x7pw1km",
|
|
version: "3.10",
|
|
},
|
|
MicrosoftStorePython {
|
|
family_name: "PythonSoftwareFoundation.Python.3.10_hd69rhyc2wevp",
|
|
version: "3.10",
|
|
},
|
|
MicrosoftStorePython {
|
|
family_name: "PythonSoftwareFoundation.Python.3.9_3847v3x7pw1km",
|
|
version: "3.9",
|
|
},
|
|
MicrosoftStorePython {
|
|
family_name: "PythonSoftwareFoundation.Python.3.9_hd69rhyc2wevp",
|
|
version: "3.9",
|
|
},
|
|
MicrosoftStorePython {
|
|
family_name: "PythonSoftwareFoundation.Python.3.8_hd69rhyc2wevp",
|
|
version: "3.8",
|
|
},
|
|
];
|
|
|
|
/// Microsoft Store Pythons don't register themselves in the registry, so we have to look for them
|
|
/// in known locations.
|
|
///
|
|
/// Effectively a port of <https://github.com/python/cpython/blob/58ce131037ecb34d506a613f21993cde2056f628/PC/launcher2.c#L1744>
|
|
pub(crate) fn find_microsoft_store_pythons() -> impl Iterator<Item = WindowsPython> {
|
|
let Ok(local_app_data) = env::var(EnvVars::LOCALAPPDATA) else {
|
|
debug!("`LOCALAPPDATA` not set, ignoring Microsoft store Pythons");
|
|
return Either::Left(std::iter::empty());
|
|
};
|
|
|
|
let windows_apps = PathBuf::from(local_app_data)
|
|
.join("Microsoft")
|
|
.join("WindowsApps");
|
|
|
|
Either::Right(
|
|
MICROSOFT_STORE_PYTHONS
|
|
.iter()
|
|
.map(move |store_python| {
|
|
let path = windows_apps
|
|
.join(store_python.family_name)
|
|
.join("python.exe");
|
|
WindowsPython {
|
|
path,
|
|
// All versions are constants, we know they are valid.
|
|
version: Some(PythonVersion::from_str(store_python.version).unwrap()),
|
|
}
|
|
})
|
|
.filter(|windows_python| windows_python.path.is_file()),
|
|
)
|
|
}
|