Improve simple no version messages using complement of range (#979)

Improves some of the "no versions of <package> are available" messages
by showing the complement or inversion of the package.

Does not address cases like

```
Because there are no versions of crow that satisfy any of:
    crow>1.0.0,<2.0.0a5
    crow>2.0.0a7,<2.0.0b1
    crow>2.0.0b1,<2.0.0b5
...
```

which are a bit more complicated; I'll focus on those cases in a
follow-up.
This commit is contained in:
Zanie Blue 2024-01-19 10:48:20 -06:00 committed by GitHub
parent 7bb4fda8af
commit 02ed195982
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 48 additions and 77 deletions

View file

@ -37,11 +37,20 @@ impl ReportFormatter<PubGrubPackage, Range<Version>> for PubGrubReportFormatter<
} else if set.as_singleton().is_some() { } else if set.as_singleton().is_some() {
format!("there is no version of {package}{set}") format!("there is no version of {package}{set}")
} else { } else {
format!( let complement = set.complement();
"there are no versions of {} that satisfy {}", let segments = complement.iter().collect::<Vec<_>>().len();
package, if segments == 1 {
PackageRange::compatibility(package, &set) format!(
) "only {} is available",
PackageRange::compatibility(package, &complement)
)
} else {
format!(
"there are no versions of {} that satisfy {}",
package,
PackageRange::compatibility(package, &set)
)
}
} }
} }
External::UnavailableDependencies(package, set) => { External::UnavailableDependencies(package, set) => {

View file

@ -507,7 +507,7 @@ async fn black_disallow_prerelease() -> Result<()> {
.unwrap_err(); .unwrap_err();
assert_snapshot!(err, @r###" assert_snapshot!(err, @r###"
Because there are no versions of black that satisfy black<=20.0 and root depends on black<=20.0, we can conclude that the requirements are unsatisfiable. Because only black>20.0 is available and root depends on black<=20.0, we can conclude that the requirements are unsatisfiable.
hint: Pre-releases are available for black in the requested range (e.g., 19.10b0), but pre-releases weren't enabled (try: `--prerelease=allow`) hint: Pre-releases are available for black in the requested range (e.g., 19.10b0), but pre-releases weren't enabled (try: `--prerelease=allow`)
"###); "###);
@ -529,7 +529,7 @@ async fn black_allow_prerelease_if_necessary() -> Result<()> {
.unwrap_err(); .unwrap_err();
assert_snapshot!(err, @r###" assert_snapshot!(err, @r###"
Because there are no versions of black that satisfy black<=20.0 and root depends on black<=20.0, we can conclude that the requirements are unsatisfiable. Because only black>20.0 is available and root depends on black<=20.0, we can conclude that the requirements are unsatisfiable.
hint: Pre-releases are available for black in the requested range (e.g., 19.10b0), but pre-releases weren't enabled (try: `--prerelease=allow`) hint: Pre-releases are available for black in the requested range (e.g., 19.10b0), but pre-releases weren't enabled (try: `--prerelease=allow`)
"###); "###);
@ -655,7 +655,7 @@ async fn msgraph_sdk() -> Result<()> {
.unwrap_err(); .unwrap_err();
assert_snapshot!(err, @r###" assert_snapshot!(err, @r###"
Because there are no versions of msgraph-core that satisfy msgraph-core>=1.0.0a2 and msgraph-sdk==1.0.0 depends on msgraph-core>=1.0.0a2, we can conclude that msgraph-sdk==1.0.0 cannot be used. Because only msgraph-core<1.0.0a2 is available and msgraph-sdk==1.0.0 depends on msgraph-core>=1.0.0a2, we can conclude that msgraph-sdk==1.0.0 cannot be used.
And because root depends on msgraph-sdk==1.0.0 we can conclude that the requirements are unsatisfiable. And because root depends on msgraph-sdk==1.0.0 we can conclude that the requirements are unsatisfiable.
hint: msgraph-core was requested with a pre-release marker (e.g., msgraph-core>=1.0.0a2), but pre-releases weren't enabled (try: `--prerelease=allow`) hint: msgraph-core was requested with a pre-release marker (e.g., msgraph-core>=1.0.0a2), but pre-releases weren't enabled (try: `--prerelease=allow`)

View file

@ -687,9 +687,8 @@ fn compile_python_37() -> Result<()> {
----- stderr ----- ----- stderr -----
× No solution found when resolving dependencies: × No solution found when resolving dependencies:
Because there are no versions of Python that satisfy Python>=3.8 Because only Python<3.8 is available and black==23.10.1 depends on
and black==23.10.1 depends on Python>=3.8, we can conclude that Python>=3.8, we can conclude that black==23.10.1 cannot be used.
black==23.10.1 cannot be used.
And because root depends on black==23.10.1 we can conclude that the And because root depends on black==23.10.1 we can conclude that the
requirements are unsatisfiable. requirements are unsatisfiable.
"###); "###);
@ -1597,9 +1596,8 @@ fn conflicting_transitive_url_dependency() -> Result<()> {
----- stderr ----- ----- stderr -----
× No solution found when resolving dependencies: × No solution found when resolving dependencies:
Because flask==3.0.0 depends on werkzeug>=3.0.0 and there are no Because flask==3.0.0 depends on werkzeug>=3.0.0 and only werkzeug<3.0.0
versions of werkzeug that satisfy werkzeug>=3.0.0, we can conclude that is available, we can conclude that flask==3.0.0 cannot be used.
flask==3.0.0 cannot be used.
And because root depends on flask==3.0.0 we can conclude that the And because root depends on flask==3.0.0 we can conclude that the
requirements are unsatisfiable. requirements are unsatisfiable.
"###); "###);

View file

@ -80,9 +80,9 @@ fn no_solution() -> Result<()> {
----- stderr ----- ----- stderr -----
× No solution found when resolving dependencies: × No solution found when resolving dependencies:
Because there are no versions of flask that satisfy flask>3.0.0 Because only flask<=3.0.0 is available and flask==3.0.0 depends
and flask==3.0.0 depends on werkzeug>=3.0.0, we can conclude that on werkzeug>=3.0.0, we can conclude that flask>=3.0.0 depends on
flask>=3.0.0 depends on werkzeug>=3.0.0. werkzeug>=3.0.0.
And because root depends on flask>=3.0.0 and root depends on And because root depends on flask>=3.0.0 and root depends on
werkzeug<1.0.0, we can conclude that the requirements are unsatisfiable. werkzeug<1.0.0, we can conclude that the requirements are unsatisfiable.
"###); "###);

View file

@ -191,7 +191,7 @@ fn requires_greater_version_does_not_exist() -> Result<()> {
----- stderr ----- ----- stderr -----
× No solution found when resolving dependencies: × No solution found when resolving dependencies:
Because there are no versions of albatross that satisfy albatross>1.0.0 and root depends on albatross>1.0.0, we can conclude that the requirements are unsatisfiable. Because only albatross<=1.0.0 is available and root depends on albatross>1.0.0, we can conclude that the requirements are unsatisfiable.
"###); "###);
}); });
@ -248,7 +248,7 @@ fn requires_less_version_does_not_exist() -> Result<()> {
----- stderr ----- ----- stderr -----
× No solution found when resolving dependencies: × No solution found when resolving dependencies:
Because there are no versions of albatross that satisfy albatross<2.0.0 and root depends on albatross<2.0.0, we can conclude that the requirements are unsatisfiable. Because only albatross>=2.0.0 is available and root depends on albatross<2.0.0, we can conclude that the requirements are unsatisfiable.
"###); "###);
}); });
@ -358,10 +358,7 @@ fn excluded_only_version() -> Result<()> {
----- stderr ----- ----- stderr -----
× No solution found when resolving dependencies: × No solution found when resolving dependencies:
Because there are no versions of albatross that satisfy any of: Because only albatross==1.0.0 is available and root depends on one of:
albatross<1.0.0
albatross>1.0.0
and root depends on one of:
albatross<1.0.0 albatross<1.0.0
albatross>1.0.0 albatross>1.0.0
we can conclude that the requirements are unsatisfiable. we can conclude that the requirements are unsatisfiable.
@ -700,7 +697,7 @@ fn dependency_excludes_non_contiguous_range_of_compatible_versions() -> Result<(
And because we know from (1) that crow<2.0.0 depends on albatross<2.0.0, we can conclude that crow<2.0.0 depends on bluebird==1.0.0. And because we know from (1) that crow<2.0.0 depends on albatross<2.0.0, we can conclude that crow<2.0.0 depends on bluebird==1.0.0.
And because crow==2.0.0 depends on albatross>=3.0.0 we can conclude that all versions of crow, bluebird!=1.0.0, !( albatross>=3.0.0 ) are incompatible. (2) And because crow==2.0.0 depends on albatross>=3.0.0 we can conclude that all versions of crow, bluebird!=1.0.0, !( albatross>=3.0.0 ) are incompatible. (2)
Because albatross==3.0.0 depends on bluebird==3.0.0 and there are no versions of albatross that satisfy albatross>3.0.0, we can conclude that albatross>=3.0.0 depends on bluebird==3.0.0. Because albatross==3.0.0 depends on bluebird==3.0.0 and only albatross<=3.0.0 is available, we can conclude that albatross>=3.0.0 depends on bluebird==3.0.0.
And because we know from (2) that all versions of crow, bluebird!=1.0.0, !( albatross>=3.0.0 ) are incompatible, we can conclude that all versions of crow depend on one of: And because we know from (2) that all versions of crow, bluebird!=1.0.0, !( albatross>=3.0.0 ) are incompatible, we can conclude that all versions of crow depend on one of:
bluebird<=1.0.0 bluebird<=1.0.0
bluebird>=3.0.0 bluebird>=3.0.0
@ -974,14 +971,8 @@ fn extra_incompatible_with_extra() -> Result<()> {
----- stderr ----- ----- stderr -----
× No solution found when resolving dependencies: × No solution found when resolving dependencies:
Because there are no versions of albatross[extra-c] that satisfy any of: Because only albatross[extra-c]==1.0.0 is available and albatross[extra-c]==1.0.0 depends on bluebird==2.0.0, we can conclude that all versions of albatross[extra-c] depend on bluebird==2.0.0.
albatross[extra-c]<1.0.0 And because albatross[extra-b]==1.0.0 depends on bluebird==1.0.0 and only albatross[extra-b]==1.0.0 is available, we can conclude that all versions of albatross[extra-b] and all versions of albatross[extra-c] are incompatible.
albatross[extra-c]>1.0.0
and albatross[extra-c]==1.0.0 depends on bluebird==2.0.0, we can conclude that all versions of albatross[extra-c] depend on bluebird==2.0.0.
And because albatross[extra-b]==1.0.0 depends on bluebird==1.0.0 and there are no versions of albatross[extra-b] that satisfy any of:
albatross[extra-b]<1.0.0
albatross[extra-b]>1.0.0
we can conclude that all versions of albatross[extra-b] and all versions of albatross[extra-c] are incompatible.
And because root depends on albatross[extra-c] and root depends on albatross[extra-b], we can conclude that the requirements are unsatisfiable. And because root depends on albatross[extra-c] and root depends on albatross[extra-b], we can conclude that the requirements are unsatisfiable.
"###); "###);
}); });
@ -1122,10 +1113,7 @@ fn extra_incompatible_with_root() -> Result<()> {
----- stderr ----- ----- stderr -----
× No solution found when resolving dependencies: × No solution found when resolving dependencies:
Because albatross[extra]==1.0.0 depends on bluebird==1.0.0 and there are no versions of albatross[extra] that satisfy any of: Because albatross[extra]==1.0.0 depends on bluebird==1.0.0 and only albatross[extra]==1.0.0 is available, we can conclude that all versions of albatross[extra] depend on bluebird==1.0.0.
albatross[extra]<1.0.0
albatross[extra]>1.0.0
we can conclude that all versions of albatross[extra] depend on bluebird==1.0.0.
And because root depends on albatross[extra] and root depends on bluebird==2.0.0, we can conclude that the requirements are unsatisfiable. And because root depends on albatross[extra] and root depends on bluebird==2.0.0, we can conclude that the requirements are unsatisfiable.
"###); "###);
}); });
@ -1322,10 +1310,7 @@ fn transitive_incompatible_with_root_version() -> Result<()> {
----- stderr ----- ----- stderr -----
× No solution found when resolving dependencies: × No solution found when resolving dependencies:
Because albatross==1.0.0 depends on bluebird==2.0.0 and there are no versions of albatross that satisfy any of: Because albatross==1.0.0 depends on bluebird==2.0.0 and only albatross==1.0.0 is available, we can conclude that all versions of albatross depend on bluebird==2.0.0.
albatross<1.0.0
albatross>1.0.0
we can conclude that all versions of albatross depend on bluebird==2.0.0.
And because root depends on bluebird==1.0.0 and root depends on albatross, we can conclude that the requirements are unsatisfiable. And because root depends on bluebird==1.0.0 and root depends on albatross, we can conclude that the requirements are unsatisfiable.
"###); "###);
}); });
@ -1396,14 +1381,8 @@ fn transitive_incompatible_with_transitive() -> Result<()> {
----- stderr ----- ----- stderr -----
× No solution found when resolving dependencies: × No solution found when resolving dependencies:
Because there are no versions of bluebird that satisfy any of: Because only bluebird==1.0.0 is available and bluebird==1.0.0 depends on crow==2.0.0, we can conclude that all versions of bluebird depend on crow==2.0.0.
bluebird<1.0.0 And because albatross==1.0.0 depends on crow==1.0.0 and only albatross==1.0.0 is available, we can conclude that all versions of bluebird and all versions of albatross are incompatible.
bluebird>1.0.0
and bluebird==1.0.0 depends on crow==2.0.0, we can conclude that all versions of bluebird depend on crow==2.0.0.
And because albatross==1.0.0 depends on crow==1.0.0 and there are no versions of albatross that satisfy any of:
albatross<1.0.0
albatross>1.0.0
we can conclude that all versions of bluebird and all versions of albatross are incompatible.
And because root depends on bluebird and root depends on albatross, we can conclude that the requirements are unsatisfiable. And because root depends on bluebird and root depends on albatross, we can conclude that the requirements are unsatisfiable.
"###); "###);
}); });
@ -1520,7 +1499,7 @@ fn package_only_prereleases_in_range() -> Result<()> {
----- stderr ----- ----- stderr -----
× No solution found when resolving dependencies: × No solution found when resolving dependencies:
Because there are no versions of albatross that satisfy albatross>0.1.0 and root depends on albatross>0.1.0, we can conclude that the requirements are unsatisfiable. Because only albatross<=0.1.0 is available and root depends on albatross>0.1.0, we can conclude that the requirements are unsatisfiable.
hint: Pre-releases are available for albatross in the requested range (e.g., 1.0.0a1), but pre-releases weren't enabled (try: `--prerelease=allow`) hint: Pre-releases are available for albatross in the requested range (e.g., 1.0.0a1), but pre-releases weren't enabled (try: `--prerelease=allow`)
"###); "###);
@ -2083,11 +2062,8 @@ fn transitive_package_only_prereleases_in_range() -> Result<()> {
----- stderr ----- ----- stderr -----
× No solution found when resolving dependencies: × No solution found when resolving dependencies:
Because there are no versions of bluebird that satisfy bluebird>0.1 and albatross==0.1.0 depends on bluebird>0.1, we can conclude that albatross==0.1.0 cannot be used. Because only bluebird<=0.1 is available and albatross==0.1.0 depends on bluebird>0.1, we can conclude that albatross==0.1.0 cannot be used.
And because there are no versions of albatross that satisfy any of: And because only albatross==0.1.0 is available and root depends on albatross, we can conclude that the requirements are unsatisfiable.
albatross<0.1.0
albatross>0.1.0
and root depends on albatross, we can conclude that the requirements are unsatisfiable.
hint: Pre-releases are available for bluebird in the requested range (e.g., 1.0.0a1), but pre-releases weren't enabled (try: `--prerelease=allow`) hint: Pre-releases are available for bluebird in the requested range (e.g., 1.0.0a1), but pre-releases weren't enabled (try: `--prerelease=allow`)
"###); "###);
@ -2233,10 +2209,7 @@ fn transitive_prerelease_and_stable_dependency() -> Result<()> {
----- stderr ----- ----- stderr -----
× No solution found when resolving dependencies: × No solution found when resolving dependencies:
Because there is no version of crow==2.0.0b1 and albatross==1.0.0 depends on crow==2.0.0b1, we can conclude that albatross==1.0.0 cannot be used. Because there is no version of crow==2.0.0b1 and albatross==1.0.0 depends on crow==2.0.0b1, we can conclude that albatross==1.0.0 cannot be used.
And because there are no versions of albatross that satisfy any of: And because only albatross==1.0.0 is available and root depends on albatross, we can conclude that the requirements are unsatisfiable.
albatross<1.0.0
albatross>1.0.0
and root depends on albatross, we can conclude that the requirements are unsatisfiable.
hint: crow was requested with a pre-release marker (e.g., crow==2.0.0b1), but pre-releases weren't enabled (try: `--prerelease=allow`) hint: crow was requested with a pre-release marker (e.g., crow==2.0.0b1), but pre-releases weren't enabled (try: `--prerelease=allow`)
"###); "###);
@ -2415,15 +2388,9 @@ fn transitive_prerelease_and_stable_dependency_many_versions() -> Result<()> {
----- stderr ----- ----- stderr -----
× No solution found when resolving dependencies: × No solution found when resolving dependencies:
Because there are no versions of bluebird that satisfy any of: Because only bluebird==1.0.0 is available and bluebird==1.0.0 depends on crow, we can conclude that all versions of bluebird depend on crow.
bluebird<1.0.0 And because only crow<2.0.0b1 is available we can conclude that all versions of bluebird depend on crow<2.0.0b1.
bluebird>1.0.0 And because albatross==1.0.0 depends on crow>=2.0.0b1 and only albatross==1.0.0 is available, we can conclude that all versions of bluebird and all versions of albatross are incompatible.
and bluebird==1.0.0 depends on crow, we can conclude that all versions of bluebird depend on crow.
And because there are no versions of crow that satisfy crow>=2.0.0b1 we can conclude that all versions of bluebird depend on crow<2.0.0b1.
And because albatross==1.0.0 depends on crow>=2.0.0b1 and there are no versions of albatross that satisfy any of:
albatross<1.0.0
albatross>1.0.0
we can conclude that all versions of bluebird and all versions of albatross are incompatible.
And because root depends on bluebird and root depends on albatross, we can conclude that the requirements are unsatisfiable. And because root depends on bluebird and root depends on albatross, we can conclude that the requirements are unsatisfiable.
hint: crow was requested with a pre-release marker (e.g., crow>=2.0.0b1), but pre-releases weren't enabled (try: `--prerelease=allow`) hint: crow was requested with a pre-release marker (e.g., crow>=2.0.0b1), but pre-releases weren't enabled (try: `--prerelease=allow`)
@ -2524,10 +2491,7 @@ fn transitive_prerelease_and_stable_dependency_many_versions_holes() -> Result<(
crow>2.0.0a7,<2.0.0b1 crow>2.0.0a7,<2.0.0b1
crow>2.0.0b1,<2.0.0b5 crow>2.0.0b1,<2.0.0b5
we can conclude that albatross==1.0.0 cannot be used. we can conclude that albatross==1.0.0 cannot be used.
And because there are no versions of albatross that satisfy any of: And because only albatross==1.0.0 is available and root depends on albatross, we can conclude that the requirements are unsatisfiable.
albatross<1.0.0
albatross>1.0.0
and root depends on albatross, we can conclude that the requirements are unsatisfiable.
hint: crow was requested with a pre-release marker (e.g., any of: hint: crow was requested with a pre-release marker (e.g., any of:
crow>1.0.0,<2.0.0a5 crow>1.0.0,<2.0.0a5
@ -2590,7 +2554,7 @@ fn requires_python_version_does_not_exist() -> Result<()> {
----- stderr ----- ----- stderr -----
× No solution found when resolving dependencies: × No solution found when resolving dependencies:
Because there are no versions of Python that satisfy Python>=4.0 and albatross==1.0.0 depends on Python>=4.0, we can conclude that albatross==1.0.0 cannot be used. Because only Python<4.0 is available and albatross==1.0.0 depends on Python>=4.0, we can conclude that albatross==1.0.0 cannot be used.
And because root depends on albatross==1.0.0 we can conclude that the requirements are unsatisfiable. And because root depends on albatross==1.0.0 we can conclude that the requirements are unsatisfiable.
"###); "###);
}); });
@ -2647,7 +2611,7 @@ fn requires_python_version_less_than_current() -> Result<()> {
----- stderr ----- ----- stderr -----
× No solution found when resolving dependencies: × No solution found when resolving dependencies:
Because there are no versions of Python that satisfy Python<=3.8 and albatross==1.0.0 depends on Python<=3.8, we can conclude that albatross==1.0.0 cannot be used. Because only Python>3.8 is available and albatross==1.0.0 depends on Python<=3.8, we can conclude that albatross==1.0.0 cannot be used.
And because root depends on albatross==1.0.0 we can conclude that the requirements are unsatisfiable. And because root depends on albatross==1.0.0 we can conclude that the requirements are unsatisfiable.
"###); "###);
}); });
@ -2704,7 +2668,7 @@ fn requires_python_version_greater_than_current() -> Result<()> {
----- stderr ----- ----- stderr -----
× No solution found when resolving dependencies: × No solution found when resolving dependencies:
Because there are no versions of Python that satisfy Python>=3.10 and albatross==1.0.0 depends on Python>=3.10, we can conclude that albatross==1.0.0 cannot be used. Because only Python<3.10 is available and albatross==1.0.0 depends on Python>=3.10, we can conclude that albatross==1.0.0 cannot be used.
And because root depends on albatross==1.0.0 we can conclude that the requirements are unsatisfiable. And because root depends on albatross==1.0.0 we can conclude that the requirements are unsatisfiable.
"###); "###);
}); });
@ -2912,7 +2876,7 @@ fn requires_python_version_greater_than_current_excluded() -> Result<()> {
----- stderr ----- ----- stderr -----
× No solution found when resolving dependencies: × No solution found when resolving dependencies:
Because there are no versions of Python that satisfy Python>=3.10,<3.11 and there are no versions of Python that satisfy Python>=3.12, we can conclude that any of: Because there are no versions of Python that satisfy Python>=3.10,<3.11 and only Python<3.12 is available, we can conclude that any of:
Python>=3.10,<3.11 Python>=3.10,<3.11
Python>=3.12 Python>=3.12
are incompatible. are incompatible.
@ -2923,11 +2887,11 @@ fn requires_python_version_greater_than_current_excluded() -> Result<()> {
albatross>4.0.0 albatross>4.0.0
we can conclude that albatross>=2.0.0,<3.0.0 cannot be used. (1) we can conclude that albatross>=2.0.0,<3.0.0 cannot be used. (1)
Because there are no versions of Python that satisfy Python>=3.11,<3.12 and there are no versions of Python that satisfy Python>=3.12, we can conclude that Python>=3.11 are incompatible. Because there are no versions of Python that satisfy Python>=3.11,<3.12 and only Python<3.12 is available, we can conclude that Python>=3.11 are incompatible.
And because albatross==3.0.0 depends on Python>=3.11 we can conclude that albatross==3.0.0 cannot be used. And because albatross==3.0.0 depends on Python>=3.11 we can conclude that albatross==3.0.0 cannot be used.
And because we know from (1) that albatross>=2.0.0,<3.0.0 cannot be used, we can conclude that albatross>=2.0.0,<4.0.0 cannot be used. (2) And because we know from (1) that albatross>=2.0.0,<3.0.0 cannot be used, we can conclude that albatross>=2.0.0,<4.0.0 cannot be used. (2)
Because there are no versions of Python that satisfy Python>=3.12 and albatross==4.0.0 depends on Python>=3.12, we can conclude that albatross==4.0.0 cannot be used. Because only Python<3.12 is available and albatross==4.0.0 depends on Python>=3.12, we can conclude that albatross==4.0.0 cannot be used.
And because we know from (2) that albatross>=2.0.0,<4.0.0 cannot be used, we can conclude that albatross>=2.0.0 cannot be used. And because we know from (2) that albatross>=2.0.0,<4.0.0 cannot be used, we can conclude that albatross>=2.0.0 cannot be used.
And because root depends on albatross>=2.0.0 we can conclude that the requirements are unsatisfiable. And because root depends on albatross>=2.0.0 we can conclude that the requirements are unsatisfiable.
"###); "###);