mirror of
https://github.com/astral-sh/uv.git
synced 2025-11-19 11:35:36 +00:00
Avoid 'are incompatible' for singular bounded versions (#4003)
## Summary Not sure if this is worth the complexity, but it does read better.
This commit is contained in:
parent
365ca637c7
commit
420333a40e
3 changed files with 41 additions and 11 deletions
|
|
@ -194,7 +194,15 @@ impl ReportFormatter<PubGrubPackage, Range<Version>, UnavailableReason>
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result.push_str(" are incompatible");
|
if let [(p, t)] = slice {
|
||||||
|
if PackageTerm::new(p, t).plural() {
|
||||||
|
result.push_str(" are incompatible");
|
||||||
|
} else {
|
||||||
|
result.push_str(" is incompatible");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result.push_str(" are incompatible");
|
||||||
|
}
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -749,13 +757,28 @@ impl std::fmt::Display for PackageTerm<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PackageTerm<'_> {
|
impl PackageTerm<'_> {
|
||||||
|
/// Create a new [`PackageTerm`] from a [`PubGrubPackage`] and a [`Term`].
|
||||||
fn new<'a>(package: &'a PubGrubPackage, term: &'a Term<Range<Version>>) -> PackageTerm<'a> {
|
fn new<'a>(package: &'a PubGrubPackage, term: &'a Term<Range<Version>>) -> PackageTerm<'a> {
|
||||||
PackageTerm { package, term }
|
PackageTerm { package, term }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if the predicate following this package term should be singular or plural.
|
||||||
|
fn plural(&self) -> bool {
|
||||||
|
match self.term {
|
||||||
|
Term::Positive(set) => PackageRange::compatibility(self.package, set).plural(),
|
||||||
|
Term::Negative(set) => {
|
||||||
|
if set.as_singleton().is_some() {
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
PackageRange::compatibility(self.package, &set.complement()).plural()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The kind of version ranges being displayed in [`PackageRange`]
|
/// The kind of version ranges being displayed in [`PackageRange`]
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
enum PackageRangeKind {
|
enum PackageRangeKind {
|
||||||
Dependency,
|
Dependency,
|
||||||
Compatibility,
|
Compatibility,
|
||||||
|
|
@ -775,12 +798,19 @@ impl PackageRange<'_> {
|
||||||
/// be singular or plural e.g. if false use "<range> depends on <...>" and
|
/// be singular or plural e.g. if false use "<range> depends on <...>" and
|
||||||
/// if true use "<range> depend on <...>"
|
/// if true use "<range> depend on <...>"
|
||||||
fn plural(&self) -> bool {
|
fn plural(&self) -> bool {
|
||||||
if self.range.is_empty() {
|
let mut segments = self.range.iter();
|
||||||
false
|
if let Some(segment) = segments.next() {
|
||||||
|
// A single unbounded compatibility segment is always plural ("all versions of").
|
||||||
|
if self.kind == PackageRangeKind::Compatibility {
|
||||||
|
if matches!(segment, (Bound::Unbounded, Bound::Unbounded)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Otherwise, multiple segments are always plural.
|
||||||
|
segments.next().is_some()
|
||||||
} else {
|
} else {
|
||||||
let segments: Vec<_> = self.range.iter().collect();
|
// An empty range is always singular.
|
||||||
// "all versions of" is the only plural case
|
false
|
||||||
matches!(segments.as_slice(), [(Bound::Unbounded, Bound::Unbounded)])
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -991,7 +991,7 @@ fn lock_requires_python() -> Result<()> {
|
||||||
----- stderr -----
|
----- stderr -----
|
||||||
warning: `uv lock` is experimental and may change without warning.
|
warning: `uv lock` is experimental and may change without warning.
|
||||||
× No solution found when resolving dependencies:
|
× No solution found when resolving dependencies:
|
||||||
╰─▶ Because the requested Python version (>=3.7) does not satisfy Python>=3.8 and the requested Python version (>=3.7) does not satisfy Python>=3.7.9,<3.8, we can conclude that Python>=3.7.9 are incompatible.
|
╰─▶ Because the requested Python version (>=3.7) does not satisfy Python>=3.8 and the requested Python version (>=3.7) does not satisfy Python>=3.7.9,<3.8, we can conclude that Python>=3.7.9 is incompatible.
|
||||||
And because pygls>=1.1.0,<=1.2.1 depends on Python>=3.7.9,<4 and only pygls<=1.3.0 is available, we can conclude that any of:
|
And because pygls>=1.1.0,<=1.2.1 depends on Python>=3.7.9,<4 and only pygls<=1.3.0 is available, we can conclude that any of:
|
||||||
pygls>=1.1.0,<1.3.0
|
pygls>=1.1.0,<1.3.0
|
||||||
pygls>1.3.0
|
pygls>1.3.0
|
||||||
|
|
|
||||||
|
|
@ -359,7 +359,7 @@ fn excluded_only_compatible_version() {
|
||||||
And because package-a==3.0.0 depends on package-b==3.0.0, we can conclude that any of:
|
And because package-a==3.0.0 depends on package-b==3.0.0, we can conclude that any of:
|
||||||
package-a<2.0.0
|
package-a<2.0.0
|
||||||
package-a>2.0.0
|
package-a>2.0.0
|
||||||
depends on one of:
|
depend on one of:
|
||||||
package-b==1.0.0
|
package-b==1.0.0
|
||||||
package-b==3.0.0
|
package-b==3.0.0
|
||||||
|
|
||||||
|
|
@ -4011,14 +4011,14 @@ fn python_greater_than_current_excluded() {
|
||||||
Python>=3.10,<3.11
|
Python>=3.10,<3.11
|
||||||
Python>=3.12
|
Python>=3.12
|
||||||
are incompatible.
|
are incompatible.
|
||||||
And because the current Python version (3.9.[X]) does not satisfy Python>=3.11,<3.12, we can conclude that Python>=3.10 are incompatible.
|
And because the current Python version (3.9.[X]) does not satisfy Python>=3.11,<3.12, we can conclude that Python>=3.10 is incompatible.
|
||||||
And because package-a==2.0.0 depends on Python>=3.10 and only the following versions of package-a are available:
|
And because package-a==2.0.0 depends on Python>=3.10 and only the following versions of package-a are available:
|
||||||
package-a<=2.0.0
|
package-a<=2.0.0
|
||||||
package-a==3.0.0
|
package-a==3.0.0
|
||||||
package-a==4.0.0
|
package-a==4.0.0
|
||||||
we can conclude that package-a>=2.0.0,<3.0.0 cannot be used. (1)
|
we can conclude that package-a>=2.0.0,<3.0.0 cannot be used. (1)
|
||||||
|
|
||||||
Because the current Python version (3.9.[X]) does not satisfy Python>=3.11,<3.12 and the current Python version (3.9.[X]) does not satisfy Python>=3.12, we can conclude that Python>=3.11 are incompatible.
|
Because the current Python version (3.9.[X]) does not satisfy Python>=3.11,<3.12 and the current Python version (3.9.[X]) does not satisfy Python>=3.12, we can conclude that Python>=3.11 is incompatible.
|
||||||
And because package-a==3.0.0 depends on Python>=3.11, we can conclude that package-a==3.0.0 cannot be used.
|
And because package-a==3.0.0 depends on Python>=3.11, we can conclude that package-a==3.0.0 cannot be used.
|
||||||
And because we know from (1) that package-a>=2.0.0,<3.0.0 cannot be used, we can conclude that package-a>=2.0.0,<4.0.0 cannot be used. (2)
|
And because we know from (1) that package-a>=2.0.0,<3.0.0 cannot be used, we can conclude that package-a>=2.0.0,<4.0.0 cannot be used. (2)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue