From 897508aeb029ffca382b351bf051fc67412f33a2 Mon Sep 17 00:00:00 2001 From: Zanie Blue Date: Thu, 13 Mar 2025 20:09:08 -0500 Subject: [PATCH] Avoid subsequent index hint when no versions are available on the first index (#9332) As reported in https://github.com/astral-sh/uv/issues/9331, this hint is misleading. --------- Co-authored-by: Charlie Marsh --- crates/uv-resolver/src/pubgrub/report.rs | 38 ++++++++++++++---------- crates/uv/tests/it/pip_compile.rs | 31 +++++++++++++++++++ 2 files changed, 54 insertions(+), 15 deletions(-) diff --git a/crates/uv-resolver/src/pubgrub/report.rs b/crates/uv-resolver/src/pubgrub/report.rs index f3a04a9ab..f4a07b40d 100644 --- a/crates/uv-resolver/src/pubgrub/report.rs +++ b/crates/uv-resolver/src/pubgrub/report.rs @@ -895,21 +895,29 @@ impl PubGrubReportFormatter<'_> { // Add hints due to the package being available on an index, but not at the correct version, // with subsequent indexes that were _not_ queried. if matches!(selector.index_strategy(), IndexStrategy::FirstIndex) { - if let Some(found_index) = available_indexes.get(name).and_then(BTreeSet::first) { - // Determine whether the index is the last-available index. If not, then some - // indexes were not queried, and could contain a compatible version. - if let Some(next_index) = index_locations - .indexes() - .map(Index::url) - .skip_while(|url| *url != found_index) - .nth(1) - { - hints.insert(PubGrubHint::UncheckedIndex { - name: name.clone(), - range: set.clone(), - found_index: found_index.clone(), - next_index: next_index.clone(), - }); + // Do not include the hint if the set is "all versions". This is an unusual but valid + // case in which a package returns a 200 response, but without any versions or + // distributions for the package. + if !set + .iter() + .all(|range| matches!(range, (Bound::Unbounded, Bound::Unbounded))) + { + if let Some(found_index) = available_indexes.get(name).and_then(BTreeSet::first) { + // Determine whether the index is the last-available index. If not, then some + // indexes were not queried, and could contain a compatible version. + if let Some(next_index) = index_locations + .indexes() + .map(Index::url) + .skip_while(|url| *url != found_index) + .nth(1) + { + hints.insert(PubGrubHint::UncheckedIndex { + name: name.clone(), + range: set.clone(), + found_index: found_index.clone(), + next_index: next_index.clone(), + }); + } } } } diff --git a/crates/uv/tests/it/pip_compile.rs b/crates/uv/tests/it/pip_compile.rs index b8147b8c3..c5cf64dfc 100644 --- a/crates/uv/tests/it/pip_compile.rs +++ b/crates/uv/tests/it/pip_compile.rs @@ -12439,6 +12439,37 @@ fn compile_index_url_first_match_marker() -> Result<()> { Ok(()) } +/// Install a package via `--extra-index-url`. +/// +/// If the package "exists" on the "extra" index, but without any versions, the resolution +/// should fail by default (even though a compatible version exists on the "primary" index). +#[test] +fn compile_index_url_first_match_all_versions() -> Result<()> { + let context = TestContext::new("3.12"); + + let requirements_in = context.temp_dir.child("requirements.in"); + requirements_in.write_str("pandas")?; + + uv_snapshot!(context.filters(), context.pip_compile() + .arg("--index-url") + .arg("https://pypi.org/simple") + .arg("--extra-index-url") + .arg("https://test.pypi.org/simple") + .arg("requirements.in") + .arg("--no-deps"), @r###" + success: false + exit_code: 1 + ----- stdout ----- + + ----- stderr ----- + × No solution found when resolving dependencies: + ╰─▶ Because there are no versions of pandas and you require pandas, we can conclude that your requirements are unsatisfiable. + "### + ); + + Ok(()) +} + /// Install a package via `--extra-index-url`. /// /// If the package exists exist on the "extra" index, but at an incompatible version, the