Skip to content

Commit 29cec24

Browse files
authored
fix: Add a hint on uv pip install failure if the --system flag is used to select an externally managed interpreter (#16318)
Hello, # Summary This PR makes the error message clearer when you try to install packages into an externally managed Python environment with the `--system` flag. Now, instead of just failing, the error explains that you're hitting this because you explicitly used `--system`. This closes #15639. # Test plan - I added a new integration test (`install_with_system_interpreter` in `pip_install.rs`) that checks the error message includes the hint. - I tried to run `uv pip install --system -r requirements.txt` to see the actual error message in action, but had permission issues.
1 parent ed65c24 commit 29cec24

File tree

2 files changed

+59
-6
lines changed

2 files changed

+59
-6
lines changed

crates/uv/src/commands/pip/install.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -236,18 +236,30 @@ pub(crate) async fn pip_install(
236236
if break_system_packages {
237237
debug!("Ignoring externally managed environment due to `--break-system-packages`");
238238
} else {
239-
return if let Some(error) = externally_managed.into_error() {
240-
Err(anyhow::anyhow!(
239+
let base_message = match externally_managed.into_error() {
240+
Some(error) => format!(
241241
"The interpreter at {} is externally managed, and indicates the following:\n\n{}\n\nConsider creating a virtual environment with `uv venv`.",
242242
environment.root().user_display().cyan(),
243243
textwrap::indent(&error, " ").green(),
244-
))
245-
} else {
246-
Err(anyhow::anyhow!(
244+
),
245+
None => format!(
247246
"The interpreter at {} is externally managed. Instead, create a virtual environment with `uv venv`.",
248247
environment.root().user_display().cyan()
249-
))
248+
),
249+
};
250+
251+
let error_message = if system {
252+
format!(
253+
"{}\n{}{} This happens because the `--system` flag was used, which selected the system Python interpreter.",
254+
base_message,
255+
"hint".bold().cyan(),
256+
":".bold()
257+
)
258+
} else {
259+
base_message
250260
};
261+
262+
return Err(anyhow::Error::msg(error_message));
251263
}
252264
}
253265

crates/uv/tests/it/pip_install.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12990,3 +12990,44 @@ fn pip_install_no_sources_editable_to_registry_switch() -> Result<()> {
1299012990

1299112991
Ok(())
1299212992
}
12993+
12994+
#[test]
12995+
fn install_with_system_interpreter() -> Result<()> {
12996+
let context = TestContext::new("3.12");
12997+
12998+
// A simple requirements.txt file with pytest
12999+
let requirements_txt = context.temp_dir.child("requirements.txt");
13000+
requirements_txt.write_str("pytest")?;
13001+
13002+
// Add a custom filter to replace the system Python path
13003+
// works on Unix-like systems, Windows and for CPython, PyPy and GraalPy implementations
13004+
let filters: Vec<_> = context
13005+
.filters()
13006+
.into_iter()
13007+
.chain(std::iter::once((
13008+
r"(?:[A-Za-z]:)?([\\/]).+([\\/])python([\\/])(?:cpython|pypy|graalpy)-\d+\.\d+\.\[X\][^\s]+",
13009+
"[PYTHON-PATH]",
13010+
)))
13011+
.collect();
13012+
13013+
uv_snapshot!(filters, context.pip_install()
13014+
.arg("--system")
13015+
.arg("-r")
13016+
.arg("requirements.txt"), @r###"
13017+
success: false
13018+
exit_code: 2
13019+
----- stdout -----
13020+
13021+
----- stderr -----
13022+
Using Python 3.12.[X] environment at: [PYTHON-PATH]
13023+
error: The interpreter at [PYTHON-PATH] is externally managed, and indicates the following:
13024+
13025+
This Python installation is managed by uv and should not be modified.
13026+
13027+
Consider creating a virtual environment with `uv venv`.
13028+
hint: This happens because the `--system` flag was used, which selected the system Python interpreter.
13029+
"###
13030+
);
13031+
13032+
Ok(())
13033+
}

0 commit comments

Comments
 (0)