diff --git a/crates/puffin-resolver/src/pubgrub/report.rs b/crates/puffin-resolver/src/pubgrub/report.rs index 95110efd4..b9281e3c1 100644 --- a/crates/puffin-resolver/src/pubgrub/report.rs +++ b/crates/puffin-resolver/src/pubgrub/report.rs @@ -37,11 +37,20 @@ impl ReportFormatter> for PubGrubReportFormatter< } else if set.as_singleton().is_some() { format!("there is no version of {package}{set}") } else { - format!( - "there are no versions of {} that satisfy {}", - package, - PackageRange::compatibility(package, &set) - ) + let complement = set.complement(); + let segments = complement.iter().collect::>().len(); + if segments == 1 { + 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) => { diff --git a/crates/puffin-resolver/tests/resolver.rs b/crates/puffin-resolver/tests/resolver.rs index 74c28fb3d..997dcf77b 100644 --- a/crates/puffin-resolver/tests/resolver.rs +++ b/crates/puffin-resolver/tests/resolver.rs @@ -507,7 +507,7 @@ async fn black_disallow_prerelease() -> Result<()> { .unwrap_err(); 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`) "###); @@ -529,7 +529,7 @@ async fn black_allow_prerelease_if_necessary() -> Result<()> { .unwrap_err(); 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`) "###); @@ -655,7 +655,7 @@ async fn msgraph_sdk() -> Result<()> { .unwrap_err(); 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. 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`) diff --git a/crates/puffin/tests/pip_compile.rs b/crates/puffin/tests/pip_compile.rs index c1f7b09ff..6c01d148d 100644 --- a/crates/puffin/tests/pip_compile.rs +++ b/crates/puffin/tests/pip_compile.rs @@ -687,9 +687,8 @@ fn compile_python_37() -> Result<()> { ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ Because there are no versions of Python that satisfy Python>=3.8 - and black==23.10.1 depends on Python>=3.8, we can conclude that - black==23.10.1 cannot be used. + ╰─▶ Because only Python<3.8 is available and black==23.10.1 depends on + Python>=3.8, we can conclude that black==23.10.1 cannot be used. And because root depends on black==23.10.1 we can conclude that the requirements are unsatisfiable. "###); @@ -1597,9 +1596,8 @@ fn conflicting_transitive_url_dependency() -> Result<()> { ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ Because flask==3.0.0 depends on werkzeug>=3.0.0 and there are no - versions of werkzeug that satisfy werkzeug>=3.0.0, we can conclude that - flask==3.0.0 cannot be used. + ╰─▶ Because flask==3.0.0 depends on werkzeug>=3.0.0 and only werkzeug<3.0.0 + is available, we can conclude that flask==3.0.0 cannot be used. And because root depends on flask==3.0.0 we can conclude that the requirements are unsatisfiable. "###); diff --git a/crates/puffin/tests/pip_install.rs b/crates/puffin/tests/pip_install.rs index 23430fb27..4524ef2ae 100644 --- a/crates/puffin/tests/pip_install.rs +++ b/crates/puffin/tests/pip_install.rs @@ -80,9 +80,9 @@ fn no_solution() -> Result<()> { ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ Because there are no versions of flask that satisfy flask>3.0.0 - and flask==3.0.0 depends on werkzeug>=3.0.0, we can conclude that - flask>=3.0.0 depends on werkzeug>=3.0.0. + ╰─▶ Because only flask<=3.0.0 is available and flask==3.0.0 depends + on werkzeug>=3.0.0, we can conclude that flask>=3.0.0 depends on + werkzeug>=3.0.0. 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. "###); diff --git a/crates/puffin/tests/pip_install_scenarios.rs b/crates/puffin/tests/pip_install_scenarios.rs index e84e531d9..8757223ee 100644 --- a/crates/puffin/tests/pip_install_scenarios.rs +++ b/crates/puffin/tests/pip_install_scenarios.rs @@ -191,7 +191,7 @@ fn requires_greater_version_does_not_exist() -> Result<()> { ----- stderr ----- × 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 ----- × 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 ----- × No solution found when resolving dependencies: - ╰─▶ Because there are no versions of albatross that satisfy any of: - albatross<1.0.0 - albatross>1.0.0 - and root depends on one of: + ╰─▶ Because only albatross==1.0.0 is available and root depends on one of: albatross<1.0.0 albatross>1.0.0 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 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: bluebird<=1.0.0 bluebird>=3.0.0 @@ -974,14 +971,8 @@ fn extra_incompatible_with_extra() -> Result<()> { ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ Because there are no versions of albatross[extra-c] that satisfy any of: - albatross[extra-c]<1.0.0 - 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. + ╰─▶ 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. + 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. 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 ----- × 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: - 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. + ╰─▶ 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. 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 ----- × 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: - albatross<1.0.0 - albatross>1.0.0 - we can conclude that all versions of albatross depend on bluebird==2.0.0. + ╰─▶ 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. 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 ----- × No solution found when resolving dependencies: - ╰─▶ Because there are no versions of bluebird that satisfy any of: - bluebird<1.0.0 - 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. + ╰─▶ 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. + 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. 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 ----- × 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`) "###); @@ -2083,11 +2062,8 @@ fn transitive_package_only_prereleases_in_range() -> Result<()> { ----- stderr ----- × 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. - And because there are no versions of albatross that satisfy any of: - albatross<0.1.0 - albatross>0.1.0 - and root depends on albatross, we can conclude that the requirements are unsatisfiable. + ╰─▶ 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 only albatross==0.1.0 is available 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`) "###); @@ -2233,10 +2209,7 @@ fn transitive_prerelease_and_stable_dependency() -> Result<()> { ----- stderr ----- × 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. - And because there are no versions of albatross that satisfy any of: - albatross<1.0.0 - albatross>1.0.0 - and root depends on albatross, we can conclude that the requirements are unsatisfiable. + And because only albatross==1.0.0 is available 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`) "###); @@ -2415,15 +2388,9 @@ fn transitive_prerelease_and_stable_dependency_many_versions() -> Result<()> { ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ Because there are no versions of bluebird that satisfy any of: - bluebird<1.0.0 - bluebird>1.0.0 - 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. + ╰─▶ 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. + And because only crow<2.0.0b1 is available 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 only albatross==1.0.0 is available, 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. 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.0b1,<2.0.0b5 we can conclude that albatross==1.0.0 cannot be used. - And because there are no versions of albatross that satisfy any of: - albatross<1.0.0 - albatross>1.0.0 - and root depends on albatross, we can conclude that the requirements are unsatisfiable. + And because only albatross==1.0.0 is available 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: crow>1.0.0,<2.0.0a5 @@ -2590,7 +2554,7 @@ fn requires_python_version_does_not_exist() -> Result<()> { ----- stderr ----- × 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. "###); }); @@ -2647,7 +2611,7 @@ fn requires_python_version_less_than_current() -> Result<()> { ----- stderr ----- × 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. "###); }); @@ -2704,7 +2668,7 @@ fn requires_python_version_greater_than_current() -> Result<()> { ----- stderr ----- × 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. "###); }); @@ -2912,7 +2876,7 @@ fn requires_python_version_greater_than_current_excluded() -> Result<()> { ----- stderr ----- × 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.12 are incompatible. @@ -2923,11 +2887,11 @@ fn requires_python_version_greater_than_current_excluded() -> Result<()> { albatross>4.0.0 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 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 root depends on albatross>=2.0.0 we can conclude that the requirements are unsatisfiable. "###);