Improve error messages for `uv pip install` with `--extra` or `--all-extras` and invalid sources (#11193)

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

This error message was copied over from `uv pip compile` (presumably)
but makes way more sense there than here.
This commit is contained in:
Zanie Blue 2025-02-03 16:12:39 -06:00 committed by GitHub
parent dd7cd2e86a
commit bb3ffcfe52
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 88 additions and 1 deletions

View File

@ -60,8 +60,18 @@ pub(crate) async fn read_requirements(
// If the user requests `extras` but does not provide a valid source (e.g., a `pyproject.toml`),
// return an error.
if !extras.is_empty() && !requirements.iter().any(RequirementsSource::allows_extras) {
let hint = if requirements.iter().any(|source| {
matches!(
source,
RequirementsSource::Editable(_) | RequirementsSource::SourceTree(_)
)
}) {
"Use `<dir>[extra]` syntax or `-r <file>` instead."
} else {
"Use `package[extra]` syntax instead."
};
return Err(anyhow!(
"Requesting extras requires a `pyproject.toml`, `setup.cfg`, or `setup.py` file."
"Requesting extras requires a `pyproject.toml`, `setup.cfg`, or `setup.py` file. {hint}"
)
.into());
}

View File

@ -1031,6 +1031,83 @@ fn allow_incompatibilities() -> Result<()> {
Ok(())
}
#[test]
fn install_extras() -> Result<()> {
let context = TestContext::new("3.12");
// Request extras for an editable path
uv_snapshot!(context.filters(), context.pip_install()
.arg("--all-extras")
.arg("-e")
.arg(context.workspace_root.join("scripts/packages/poetry_editable")), @r###"
success: false
exit_code: 2
----- stdout -----
----- stderr -----
error: Requesting extras requires a `pyproject.toml`, `setup.cfg`, or `setup.py` file. Use `<dir>[extra]` syntax or `-r <file>` instead.
"###
);
// Request extras for a source tree
uv_snapshot!(context.filters(), context.pip_install()
.arg("--all-extras")
.arg(context.workspace_root.join("scripts/packages/poetry_editable")), @r###"
success: false
exit_code: 2
----- stdout -----
----- stderr -----
error: Requesting extras requires a `pyproject.toml`, `setup.cfg`, or `setup.py` file. Use `package[extra]` syntax instead.
"###
);
let requirements_txt = context.temp_dir.child("requirements.txt");
requirements_txt.write_str("anyio==3.7.0")?;
// Request extras for a requirements file
uv_snapshot!(context.filters(), context.pip_install()
.arg("--all-extras")
.arg("-r").arg("requirements.txt"), @r###"
success: false
exit_code: 2
----- stdout -----
----- stderr -----
error: Requesting extras requires a `pyproject.toml`, `setup.cfg`, or `setup.py` file. Use `package[extra]` syntax instead.
"###
);
let pyproject_toml = context.temp_dir.child("pyproject.toml");
pyproject_toml.write_str(
r#"
[project]
name = "project"
version = "0.1.0"
dependencies = ["anyio==3.7.0"]
"#,
)?;
uv_snapshot!(context.filters(), context.pip_install()
.arg("--all-extras")
.arg("-r").arg("pyproject.toml"), @r###"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
Resolved 3 packages in [TIME]
Prepared 3 packages in [TIME]
Installed 3 packages in [TIME]
+ anyio==3.7.0
+ idna==3.6
+ sniffio==1.3.1
"###
);
Ok(())
}
#[test]
fn install_editable() {
let context = TestContext::new("3.12");