Skip to content

Commit 57ea55d

Browse files
Add a hint for Requires-Python (#4021)
## Summary As requested in the originating PR.
1 parent 8eea470 commit 57ea55d

File tree

2 files changed

+54
-5
lines changed

2 files changed

+54
-5
lines changed

crates/uv-resolver/src/pubgrub/report.rs

+52-5
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,20 @@ use std::collections::{BTreeMap, BTreeSet};
44
use std::ops::Bound;
55

66
use derivative::Derivative;
7-
use distribution_types::IndexLocations;
87
use indexmap::{IndexMap, IndexSet};
98
use owo_colors::OwoColorize;
10-
use pep440_rs::Version;
119
use pubgrub::range::Range;
1210
use pubgrub::report::{DerivationTree, Derived, External, ReportFormatter};
1311
use pubgrub::term::Term;
1412
use pubgrub::type_aliases::Map;
1513
use rustc_hash::FxHashMap;
14+
15+
use distribution_types::IndexLocations;
16+
use pep440_rs::{Version, VersionSpecifiers};
1617
use uv_normalize::PackageName;
1718

1819
use crate::candidate_selector::CandidateSelector;
19-
use crate::python_requirement::PythonRequirement;
20+
use crate::python_requirement::{PythonRequirement, RequiresPython};
2021
use crate::resolver::{IncompletePackage, UnavailablePackage, UnavailableReason};
2122

2223
use super::{PubGrubPackage, PubGrubPackageInner, PubGrubPython};
@@ -534,8 +535,27 @@ impl PubGrubReportFormatter<'_> {
534535
}
535536
}
536537
}
538+
External::FromDependencyOf(package, package_set, dependency, dependency_set) => {
539+
// Check for no versions due to `Requires-Python`.
540+
if matches!(
541+
&**dependency,
542+
PubGrubPackageInner::Python(PubGrubPython::Target)
543+
) {
544+
if let Some(python) = self.python_requirement {
545+
if let Some(RequiresPython::Specifiers(specifiers)) = python.target() {
546+
hints.insert(PubGrubHint::RequiresPython {
547+
requires_python: specifiers.clone(),
548+
package: package.clone(),
549+
package_set: self
550+
.simplify_set(package_set, package)
551+
.into_owned(),
552+
package_requires_python: dependency_set.clone(),
553+
});
554+
}
555+
}
556+
}
557+
}
537558
External::NotRoot(..) => {}
538-
External::FromDependencyOf(..) => {}
539559
},
540560
DerivationTree::Derived(derived) => {
541561
hints.extend(self.hints(
@@ -618,6 +638,16 @@ pub(crate) enum PubGrubHint {
618638
#[derivative(PartialEq = "ignore", Hash = "ignore")]
619639
reason: String,
620640
},
641+
/// The `Requires-Python` requirement was not satisfied.
642+
RequiresPython {
643+
requires_python: VersionSpecifiers,
644+
#[derivative(PartialEq = "ignore", Hash = "ignore")]
645+
package: PubGrubPackage,
646+
#[derivative(PartialEq = "ignore", Hash = "ignore")]
647+
package_set: Range<Version>,
648+
#[derivative(PartialEq = "ignore", Hash = "ignore")]
649+
package_requires_python: Range<Version>,
650+
},
621651
}
622652

623653
impl std::fmt::Display for PubGrubHint {
@@ -709,7 +739,7 @@ impl std::fmt::Display for PubGrubHint {
709739
textwrap::indent(reason, " ")
710740
)
711741
}
712-
PubGrubHint::InconsistentVersionMetadata {
742+
Self::InconsistentVersionMetadata {
713743
package,
714744
version,
715745
reason,
@@ -724,6 +754,23 @@ impl std::fmt::Display for PubGrubHint {
724754
textwrap::indent(reason, " ")
725755
)
726756
}
757+
Self::RequiresPython {
758+
requires_python,
759+
package,
760+
package_set,
761+
package_requires_python,
762+
} => {
763+
write!(
764+
f,
765+
"{}{} The `Requires-Python` requirement ({}) defined in your `pyproject.toml` includes Python versions that are not supported by your dependencies (e.g., {} only supports {}). Consider using a more restrictive `Requires-Python` requirement (like {}).",
766+
"hint".bold().cyan(),
767+
":".bold(),
768+
requires_python.bold(),
769+
PackageRange::compatibility(package, package_set).bold(),
770+
package_requires_python.bold(),
771+
package_requires_python.bold(),
772+
)
773+
}
727774
}
728775
}
729776
}

crates/uv/tests/lock.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1004,6 +1004,8 @@ fn lock_requires_python() -> Result<()> {
10041004
cannot be used, we can conclude that pygls>=1.1.0 cannot be used.
10051005
And because project==0.1.0 depends on pygls>=1.1.0, we can conclude that project==0.1.0 cannot be used.
10061006
And because only project==0.1.0 is available and project depends on project, we can conclude that the requirements are unsatisfiable.
1007+
1008+
hint: The `Requires-Python` requirement (>=3.7) defined in your `pyproject.toml` includes Python versions that are not supported by your dependencies (e.g., pygls>=1.1.0,<=1.2.1 only supports >=3.7.9, <4). Consider using a more restrictive `Requires-Python` requirement (like >=3.7.9, <4).
10071009
"###);
10081010

10091011
// Require >=3.7, and allow locking to a version of `pygls` that is compatible.

0 commit comments

Comments
 (0)