From f679987fe1908c8a815dbcbc6a2a112ae49858ba Mon Sep 17 00:00:00 2001 From: Zanie Blue Date: Mon, 16 Sep 2024 22:51:50 -0500 Subject: [PATCH] Include the parent interpreter in Python discovery when `--system` is used (#7440) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes https://github.com/astral-sh/uv/issues/7417 Tested with this epic blurb ``` ❯ uv pip install --python /Users/zb/.local/share/uv/python/cpython-3.13.0rc2-macos-aarch64-none/bin/python3 . --break-system-packages --reinstall Resolved 1 package in 0.91ms Built uv @ file:///Users/zb/workspace/uv Prepared 1 package in 2m 48s Uninstalled 1 package in 1ms Installed 1 package in 1ms - uv==0.4.10 + uv==0.4.10 (from file:///Users/zb/workspace/uv) ❯ /Users/zb/.local/share/uv/python/cpython-3.13.0rc2-macos-aarch64-none/bin/python3 -m uv pip install --system -v httpx DEBUG uv 0.4.10 DEBUG Searching for Python interpreter in system path DEBUG Found `cpython-3.13.0rc2-macos-aarch64-none` at `/Users/zb/.local/share/uv/python/cpython-3.13.0rc2-macos-aarch64-none/bin/python3` (parent interpreter) DEBUG Using Python 3.13.0rc2 environment at /Users/zb/.local/share/uv/python/cpython-3.13.0rc2-macos-aarch64-none/bin/python3 ``` --- crates/uv-python/src/discovery.rs | 35 ++++++++++++++++++------------- crates/uv-python/src/lib.rs | 4 ++-- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/crates/uv-python/src/discovery.rs b/crates/uv-python/src/discovery.rs index 273abfa3d4a8..9715f0decb15 100644 --- a/crates/uv-python/src/discovery.rs +++ b/crates/uv-python/src/discovery.rs @@ -211,7 +211,6 @@ pub enum Error { /// /// The following sources are supported: /// -/// - Spawning interpreter (via `UV_INTERNAL__PARENT_INTERPRETER`) /// - Active virtual environment (via `VIRTUAL_ENV`) /// - Active conda environment (via `CONDA_PREFIX`) /// - Discovered virtual environment (e.g. `.venv` in a parent directory) @@ -219,13 +218,6 @@ pub enum Error { /// Notably, "system" environments are excluded. See [`python_executables_from_installed`]. fn python_executables_from_environments<'a>( ) -> impl Iterator> + 'a { - let from_parent_interpreter = std::iter::once_with(|| { - std::env::var_os("UV_INTERNAL__PARENT_INTERPRETER") - .into_iter() - .map(|path| Ok((PythonSource::ParentInterpreter, PathBuf::from(path)))) - }) - .flatten(); - let from_virtual_environment = std::iter::once_with(|| { virtualenv_from_env() .into_iter() @@ -253,8 +245,7 @@ fn python_executables_from_environments<'a>( }) .flatten_ok(); - from_parent_interpreter - .chain(from_virtual_environment) + from_virtual_environment .chain(from_conda_environment) .chain(from_discovered_environment) } @@ -383,15 +374,31 @@ fn python_executables<'a>( environments: EnvironmentPreference, preference: PythonPreference, ) -> Box> + 'a> { + // Always read from `UV_INTERNAL__PARENT_INTERPRETER` — it could be a system interpreter + let from_parent_interpreter = std::iter::once_with(|| { + std::env::var_os("UV_INTERNAL__PARENT_INTERPRETER") + .into_iter() + .map(|path| Ok((PythonSource::ParentInterpreter, PathBuf::from(path)))) + }) + .flatten(); + let from_environments = python_executables_from_environments(); let from_installed = python_executables_from_installed(version, implementation, preference); + // Limit the search to the relevant environment preference; we later validate that they match + // the preference but queries are expensive and we query less interpreters this way. match environments { - EnvironmentPreference::OnlyVirtual => Box::new(from_environments), - EnvironmentPreference::ExplicitSystem | EnvironmentPreference::Any => { - Box::new(from_environments.chain(from_installed)) + EnvironmentPreference::OnlyVirtual => { + Box::new(from_parent_interpreter.chain(from_environments)) + } + EnvironmentPreference::ExplicitSystem | EnvironmentPreference::Any => Box::new( + from_parent_interpreter + .chain(from_environments) + .chain(from_installed), + ), + EnvironmentPreference::OnlySystem => { + Box::new(from_parent_interpreter.chain(from_installed)) } - EnvironmentPreference::OnlySystem => Box::new(from_installed), } } diff --git a/crates/uv-python/src/lib.rs b/crates/uv-python/src/lib.rs index a47e4243d3ff..dafb3d192f15 100644 --- a/crates/uv-python/src/lib.rs +++ b/crates/uv-python/src/lib.rs @@ -1247,8 +1247,8 @@ mod tests { )??; assert_eq!( python.interpreter().python_full_version().to_string(), - "3.12.3", - "We should prefer the system interpreter" + "3.12.0", + "We should prefer the parent interpreter since it's not virtual" ); // Test with `EnvironmentPreference::OnlyVirtual`