Don't warn when dependency is constraint by other dependency (#16149)

Currently, `uv lock --resolution lowest-direct` warns above the setup
below, as we visit the unbounded `anyio[trio]` first.

```toml
[project]
name = "project"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = [
    "anyio[trio]",
    "anyio>=4"
]
```
This commit is contained in:
konsti 2025-10-07 17:59:01 +02:00 committed by GitHub
parent 252f887338
commit 73e62c0c17
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 55 additions and 6 deletions

View file

@ -2938,13 +2938,31 @@ impl ForkState {
resolution_strategy,
ResolutionStrategy::Lowest | ResolutionStrategy::LowestDirect(..)
);
if !has_url && missing_lower_bound && strategy_lowest {
warn_user_once!(
"The direct dependency `{name}` is unpinned. \
Consider setting a lower bound when using `--resolution lowest` \
or `--resolution lowest-direct` to avoid using outdated versions.",
name = package.name_no_root().unwrap(),
);
let name = package.name_no_root().unwrap();
// Handle cases where a package is listed both without and with a lower bound.
// Example:
// ```
// "coverage[toml] ; python_version < '3.11'",
// "coverage >= 7.10.0",
// ```
let bound_on_other_package = dependencies.iter().any(|other| {
Some(name) == other.package.name()
&& !other
.version
.bounding_range()
.map(|(lowest, _highest)| lowest == Bound::Unbounded)
.unwrap_or(true)
});
if !bound_on_other_package {
warn_user_once!(
"The direct dependency `{name}` is unpinned. \
Consider setting a lower bound when using `--resolution lowest` \
or `--resolution lowest-direct` to avoid using outdated versions.",
);
}
}
}

View file

@ -31969,3 +31969,34 @@ fn collapsed_error_with_marker_packages() -> Result<()> {
Ok(())
}
/// <https://github.com/astral-sh/uv/issues/16148>
#[test]
fn no_warning_without_and_with_lower_bound() -> Result<()> {
let context = TestContext::new("3.12");
let pyproject_toml = context.temp_dir.child("pyproject.toml");
pyproject_toml.write_str(
r#"
[project]
name = "project"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = [
"anyio[trio]",
"anyio>=4"
]
"#,
)?;
uv_snapshot!(context.filters(), context.lock().arg("--resolution").arg("lowest-direct"), @r"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
Resolved 10 packages in [TIME]
");
Ok(())
}