diff --git a/crates/puffin-cli/tests/pip_install_scenarios.rs b/crates/puffin-cli/tests/pip_install_scenarios.rs index 6aa9b9b64b62..9c6db4f4bc20 100644 --- a/crates/puffin-cli/tests/pip_install_scenarios.rs +++ b/crates/puffin-cli/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 versions of albatross matching albatross<=1.0.0 are 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 versions of albatross matching albatross>=2.0.0 are 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 1.0.0 is the only available version of albatross and root depends on one of: albatross<1.0.0 albatross>1.0.0 we can conclude that the requirements are unsatisfiable. @@ -437,11 +434,10 @@ fn excluded_only_compatible_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,<2.0.0 - albatross>2.0.0,<3.0.0 - albatross>3.0.0 + ╰─▶ Because the only versions of albatross are one of: + albatross==1.0.0 + albatross==2.0.0 + albatross==3.0.0 and albatross==1.0.0 depends on bluebird==1.0.0, we can conclude that albatross<2.0.0 depends on bluebird==1.0.0. And because albatross==3.0.0 depends on bluebird==3.0.0 we can conclude that any of: albatross<2.0.0 @@ -554,16 +550,14 @@ fn dependency_excludes_range_of_compatible_versions() -> 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,<2.0.0 - albatross>3.0.0 + ╰─▶ Because the only versions of albatross are one of: + albatross==1.0.0 + albatross>=2.0.0,<=3.0.0 and albatross==1.0.0 depends on bluebird==1.0.0, we can conclude that albatross<2.0.0 depends on bluebird==1.0.0. (1) - Because there are no versions of crow that satisfy any of: - crow<1.0.0 - crow>1.0.0,<2.0.0 - crow>2.0.0 + Because the only versions of crow are one of: + crow==1.0.0 + crow==2.0.0 and crow==1.0.0 depends on albatross<2.0.0, we can conclude that crow<2.0.0 depends on albatross<2.0.0. And because crow==2.0.0 depends on albatross>=3.0.0 we can conclude that all versions of crow depends on one of: albatross<2.0.0 @@ -687,20 +681,19 @@ fn dependency_excludes_non_contiguous_range_of_compatible_versions() -> Result<( ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ Because there are no versions of crow that satisfy any of: - crow<1.0.0 - crow>1.0.0,<2.0.0 - crow>2.0.0 + ╰─▶ Because the only versions of crow are one of: + crow==1.0.0 + crow==2.0.0 and crow==1.0.0 depends on albatross<2.0.0, we can conclude that crow<2.0.0 depends on albatross<2.0.0. (1) - Because albatross==1.0.0 depends on bluebird==1.0.0 and there are no versions of albatross that satisfy any of: - albatross<1.0.0 - albatross>1.0.0,<2.0.0 + Because albatross==1.0.0 depends on bluebird==1.0.0 and the only versions of albatross are one of: + albatross==1.0.0 + albatross>=2.0.0 we can conclude that albatross<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) - 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 versions of albatross matching albatross<=3.0.0 are 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 depends on one of: bluebird<=1.0.0 bluebird>=3.0.0 @@ -974,14 +967,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] depends 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 1.0.0 is the only available version of albatross[extra-c] and albatross[extra-c]==1.0.0 depends on bluebird==2.0.0, we can conclude that all versions of albatross[extra-c] depends on bluebird==2.0.0. + And because albatross[extra-b]==1.0.0 depends on bluebird==1.0.0 and 1.0.0 is the only available version of albatross[extra-b], 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 +1109,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] depends on bluebird==1.0.0. + ╰─▶ Because albatross[extra]==1.0.0 depends on bluebird==1.0.0 and 1.0.0 is the only available version of albatross[extra], we can conclude that all versions of albatross[extra] depends 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 +1306,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 depends on bluebird==2.0.0. + ╰─▶ Because albatross==1.0.0 depends on bluebird==2.0.0 and 1.0.0 is the only available version of albatross, we can conclude that all versions of albatross depends 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 +1377,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 depends 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 1.0.0 is the only available version of bluebird and bluebird==1.0.0 depends on crow==2.0.0, we can conclude that all versions of bluebird depends on crow==2.0.0. + And because albatross==1.0.0 depends on crow==1.0.0 and 1.0.0 is the only available version of albatross, 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 +1495,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 versions of albatross matching albatross<=0.1.0 are 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 +2058,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 versions of bluebird matching bluebird<=0.1 are available and albatross==0.1.0 depends on bluebird>0.1, we can conclude that albatross==0.1.0 cannot be used. + And because 0.1.0 is the only available version of albatross 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 +2205,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 1.0.0 is the only available version of albatross 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 +2384,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 depends on crow. - And because there are no versions of crow that satisfy crow>=2.0.0b1 we can conclude that all versions of bluebird depends 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 1.0.0 is the only available version of bluebird and bluebird==1.0.0 depends on crow, we can conclude that all versions of bluebird depends on crow. + And because only versions of crow matching crow<2.0.0b1 are available we can conclude that all versions of bluebird depends on crow<2.0.0b1. + And because albatross==1.0.0 depends on crow>=2.0.0b1 and 1.0.0 is the only available version of albatross, 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`) @@ -2515,19 +2478,17 @@ fn transitive_prerelease_and_stable_dependency_many_versions_holes() -> Result<( ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ 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 + ╰─▶ Because the only versions of crow are one of: + crow<=1.0.0 + crow>=2.0.0a5,<=2.0.0a7 + crow==2.0.0b1 + crow>=2.0.0b5 and albatross==1.0.0 depends on one of: crow>1.0.0,<2.0.0a5 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 1.0.0 is the only available version of albatross 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 +2551,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 versions of Python matching Python<4.0 are 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 +2608,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 versions of Python matching Python>3.8 are 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 +2665,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 versions of Python matching Python<3.10 are 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,22 +2873,31 @@ 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 the only versions of Python are one of: + Python<3.10 + Python>=3.11 + and only versions of Python matching Python<3.12 are available, we can conclude that any of: Python>=3.10,<3.11 Python>=3.12 are incompatible. - And because there are no versions of Python that satisfy Python>=3.11,<3.12 we can conclude that Python>=3.10 are incompatible. - And because albatross==2.0.0 depends on Python>=3.10 and there are no versions of albatross that satisfy any of: - albatross>2.0.0,<3.0.0 - albatross>3.0.0,<4.0.0 - albatross>4.0.0 + And because the only versions of Python are one of: + Python<3.11 + Python>=3.12 + we can conclude that Python>=3.10 are incompatible. + And because albatross==2.0.0 depends on Python>=3.10 and the only versions of albatross are one of: + albatross<=2.0.0 + albatross==3.0.0 + 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 the only versions of Python are one of: + Python<3.11 + Python>=3.12 + and only versions of Python matching Python<3.12 are 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 versions of Python matching Python<3.12 are 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. "###); diff --git a/crates/puffin-resolver/src/pubgrub/report.rs b/crates/puffin-resolver/src/pubgrub/report.rs index e428b2dfdf59..5cf175ddc841 100644 --- a/crates/puffin-resolver/src/pubgrub/report.rs +++ b/crates/puffin-resolver/src/pubgrub/report.rs @@ -31,17 +31,30 @@ impl ReportFormatter> for PubGrubReportFormatter< format!("we are solving dependencies of {package} {version}") } External::NoVersions(package, set) => { - let set = self.simplify_set(set, package); + let set = self.simplify_set(&set, package); if set.as_ref() == &Range::full() { format!("there are no versions of {package}") } 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(); + if let Some(version) = complement.as_singleton() { + format!("{version} is the only available version of {package}") + } else { + let segments = complement.iter().collect::>().len(); + if segments == 1 { + format!( + "only versions of {package} matching {} are available", + PackageRange::compatibility(package, &complement) + ) + } else { + format!( + "the only versions of {} are {}", + package, + PackageRange::dependency(package, &complement) + ) + } + } } } External::UnavailableDependencies(package, set) => { diff --git a/crates/puffin-resolver/tests/resolver.rs b/crates/puffin-resolver/tests/resolver.rs index 74c28fb3d5ac..3bb675e5a0e8 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 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. 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 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. 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 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. 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`)