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 <charlie.r.marsh@gmail.com>
This commit is contained in:
Zanie Blue
2025-03-13 20:09:08 -05:00
committed by GitHub
parent e52cd5c7a5
commit 897508aeb0
2 changed files with 54 additions and 15 deletions
+23 -15
View File
@@ -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(),
});
}
}
}
}
+31
View File
@@ -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