From 460614059272ba0dd914342ce42804be57a44578 Mon Sep 17 00:00:00 2001 From: konstin Date: Tue, 16 Jul 2024 15:08:34 +0200 Subject: [PATCH 1/3] Warn about unconstrained direct deps in lowest resolution Warn when there is a direct dependency without a lower bound and `--resolution lowest` is set. --- crates/uv-resolver/src/resolver/mod.rs | 20 ++++++++++++++++++++ crates/uv/tests/pip_compile.rs | 6 +++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/crates/uv-resolver/src/resolver/mod.rs b/crates/uv-resolver/src/resolver/mod.rs index dd8e724c8012..7e3d125bd788 100644 --- a/crates/uv-resolver/src/resolver/mod.rs +++ b/crates/uv-resolver/src/resolver/mod.rs @@ -37,6 +37,7 @@ use uv_distribution::{ArchiveMetadata, DistributionDatabase}; use uv_git::GitResolver; use uv_normalize::{ExtraName, GroupName, PackageName}; use uv_types::{BuildContext, HashStrategy, InstalledPackagesProvider}; +use uv_warnings::warn_user_once; use crate::candidate_selector::{CandidateDist, CandidateSelector}; use crate::dependency_provider::UvDependencyProvider; @@ -52,6 +53,7 @@ use crate::pubgrub::{ }; use crate::python_requirement::PythonRequirement; use crate::resolution::ResolutionGraph; +use crate::resolution_mode::ResolutionStrategy; pub(crate) use crate::resolver::availability::{ IncompletePackage, ResolverVersion, UnavailablePackage, UnavailableReason, UnavailableVersion, }; @@ -497,6 +499,7 @@ impl ResolverState ResolverState, git: &GitResolver, + resolution_strategy: &ResolutionStrategy, ) -> Result<(), ResolveError> { for dependency in &dependencies { let PubGrubDependency { @@ -2013,6 +2018,7 @@ impl ForkState { local, } = dependency; + let mut has_url = false; if let Some(name) = package.name() { // From the [`Requirement`] to [`PubGrubDependency`] conversion, we get a URL if the // requirement was a URL requirement. `Urls` applies canonicalization to this and @@ -2020,6 +2026,7 @@ impl ForkState { // conflicts using [`ForkUrl`]. if let Some(url) = urls.get_url(name, url.as_ref(), git)? { self.fork_urls.insert(name, url, &self.markers)?; + has_url = true; }; // `PubGrubDependency` also gives us a local version if specified by the user. @@ -2035,6 +2042,19 @@ impl ForkState { } else { // A dependency from the root package or requirements.txt. debug!("Adding direct dependency: {package}{version}"); + + // Warn the user if the direct dependency lacks a lower bound in lowest resolution. + let missing_lower_bound = version + .bounding_range() + .map(|(lowest, _highest)| lowest == Bound::Unbounded) + .unwrap_or(true); + let strategy_lowest = matches!( + resolution_strategy, + ResolutionStrategy::Lowest | ResolutionStrategy::LowestDirect(..) + ); + if !has_url && missing_lower_bound && strategy_lowest { + warn_user_once!("The direct dependency `{package}` is unpinned. Consider setting a lower bound."); + } } // Update the package priorities. diff --git a/crates/uv/tests/pip_compile.rs b/crates/uv/tests/pip_compile.rs index 7637914f620d..cef0f4628123 100644 --- a/crates/uv/tests/pip_compile.rs +++ b/crates/uv/tests/pip_compile.rs @@ -9520,12 +9520,15 @@ fn compile_index_url_unsafe_highest() -> Result<()> { /// In this case, anyio 3.5.0 is hosted on the "extra" index, but older versions are available on /// the "primary" index. We should prefer the older version from the "primary" index, despite the /// "extra" index being the preferred index. +/// +/// We also test here that a warning is raised for missing lower bounds on direct dependencies with +/// `--resolution lowest`. #[test] fn compile_index_url_unsafe_lowest() -> Result<()> { let context = TestContext::new("3.12"); let requirements_in = context.temp_dir.child("requirements.in"); - requirements_in.write_str("anyio")?; + requirements_in.write_str("anyio<100")?; uv_snapshot!(context.pip_compile() .arg("--resolution") @@ -9547,6 +9550,7 @@ fn compile_index_url_unsafe_lowest() -> Result<()> { # via -r requirements.in ----- stderr ----- + warning: The direct dependency `anyio` is unpinned. Consider setting a lower bound. Resolved 1 package in [TIME] "### ); From d5e6dedacb62ae9875a271cc3f455041a74ba8da Mon Sep 17 00:00:00 2001 From: konsti Date: Wed, 17 Jul 2024 21:05:19 +0200 Subject: [PATCH 2/3] Update crates/uv-resolver/src/resolver/mod.rs Co-authored-by: Zanie Blue --- crates/uv-resolver/src/resolver/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/uv-resolver/src/resolver/mod.rs b/crates/uv-resolver/src/resolver/mod.rs index 7e3d125bd788..276c2027fdbc 100644 --- a/crates/uv-resolver/src/resolver/mod.rs +++ b/crates/uv-resolver/src/resolver/mod.rs @@ -2053,7 +2053,7 @@ impl ForkState { ResolutionStrategy::Lowest | ResolutionStrategy::LowestDirect(..) ); if !has_url && missing_lower_bound && strategy_lowest { - warn_user_once!("The direct dependency `{package}` is unpinned. Consider setting a lower bound."); + warn_user_once!("The direct dependency `{package}` is unpinned. Consider setting a lower bound when using `--resolution-strategy lowest` to avoid using outdated versions."); } } From f305af79aa393de848417d78fbc44c6efed51bf2 Mon Sep 17 00:00:00 2001 From: Zanie Blue Date: Wed, 17 Jul 2024 22:36:08 -0500 Subject: [PATCH 3/3] Update snapshots --- crates/uv/tests/pip_compile.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/uv/tests/pip_compile.rs b/crates/uv/tests/pip_compile.rs index cef0f4628123..5a45d7a3a4ad 100644 --- a/crates/uv/tests/pip_compile.rs +++ b/crates/uv/tests/pip_compile.rs @@ -9550,7 +9550,7 @@ fn compile_index_url_unsafe_lowest() -> Result<()> { # via -r requirements.in ----- stderr ----- - warning: The direct dependency `anyio` is unpinned. Consider setting a lower bound. + warning: The direct dependency `anyio` is unpinned. Consider setting a lower bound when using `--resolution-strategy lowest` to avoid using outdated versions. Resolved 1 package in [TIME] "### );