Validate that discovered interpreters meet the Python preference (#7934)

Closes https://github.com/astral-sh/uv/issues/5144

e.g.

```
❯ cargo run -q -- sync --python-preference only-system
Using CPython 3.12.6 interpreter at: /opt/homebrew/opt/python@3.12/bin/python3.12
Removed virtual environment at: .venv
Creating virtual environment at: .venv
Resolved 9 packages in 14ms
Installed 8 packages in 9ms
 + anyio==4.6.0
 + certifi==2024.8.30
 + h11==0.14.0
 + httpcore==1.0.5
 + httpx==0.27.2
 + idna==3.10
 + ruff==0.6.7
 + sniffio==1.3.1

❯ cargo run -q -- sync --python-preference only-managed
Using CPython 3.12.1
Removed virtual environment at: .venv
Creating virtual environment at: .venv
Resolved 9 packages in 14ms
Installed 8 packages in 11ms
 + anyio==4.6.0
 + certifi==2024.8.30
 + h11==0.14.0
 + httpcore==1.0.5
 + httpx==0.27.2
 + idna==3.10
 + ruff==0.6.7
 + sniffio==1.3.1
```
This commit is contained in:
Zanie Blue
2025-07-16 15:31:47 -05:00
parent 2df06ebfbc
commit b98ac8c224
12 changed files with 544 additions and 11 deletions
+18 -5
View File
@@ -271,15 +271,28 @@ impl Interpreter {
///
/// Returns `false` if we cannot determine the path of the uv managed Python interpreters.
pub fn is_managed(&self) -> bool {
if let Ok(test_managed) =
std::env::var(uv_static::EnvVars::UV_INTERNAL__TEST_PYTHON_MANAGED)
{
// During testing, we collect interpreters into an artificial search path and need to
// be able to mock whether an interpreter is managed or not.
return test_managed.split_ascii_whitespace().any(|item| {
let version = <PythonVersion as std::str::FromStr>::from_str(item).expect(
"`UV_INTERNAL__TEST_PYTHON_MANAGED` items should be valid Python versions",
);
if version.patch().is_some() {
version.version() == self.python_version()
} else {
(version.major(), version.minor()) == self.python_tuple()
}
});
}
let Ok(installations) = ManagedPythonInstallations::from_settings(None) else {
return false;
};
installations
.find_all()
.into_iter()
.flatten()
.any(|install| install.path() == self.sys_base_prefix)
self.sys_base_prefix.starts_with(installations.root())
}
/// Returns `Some` if the environment is externally managed, optionally including an error