From 53a55d7a11b1d382f120a0e3497ebb6916b6520c Mon Sep 17 00:00:00 2001 From: Zanie Date: Thu, 18 Jan 2024 17:35:47 -0600 Subject: [PATCH] Improve simple no version messages using complement of range --- .../puffin-cli/tests/pip_install_scenarios.rs | 112 +++++++++--------- crates/puffin-resolver/src/pubgrub/report.rs | 8 +- 2 files changed, 57 insertions(+), 63 deletions(-) diff --git a/crates/puffin-cli/tests/pip_install_scenarios.rs b/crates/puffin-cli/tests/pip_install_scenarios.rs index 9c6db4f4bc20..9964f561daa7 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 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. + ╰─▶ 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 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. + ╰─▶ 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,7 +358,7 @@ fn excluded_only_version() -> Result<()> { ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ Because 1.0.0 is the only available version of albatross and root depends on one of: + ╰─▶ Because albatross==1.0.0 is the only available version and root depends on one of: albatross<1.0.0 albatross>1.0.0 we can conclude that the requirements are unsatisfiable. @@ -434,10 +434,11 @@ fn excluded_only_compatible_version() -> Result<()> { ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ Because the only versions of albatross are one of: - albatross==1.0.0 - albatross==2.0.0 - albatross==3.0.0 + ╰─▶ 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 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 @@ -550,14 +551,16 @@ fn dependency_excludes_range_of_compatible_versions() -> Result<()> { ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ Because the only versions of albatross are one of: - albatross==1.0.0 - albatross>=2.0.0,<=3.0.0 + ╰─▶ 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 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 the only versions of crow are one of: - crow==1.0.0 - crow==2.0.0 + 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 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 @@ -681,19 +684,20 @@ fn dependency_excludes_non_contiguous_range_of_compatible_versions() -> Result<( ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ Because the only versions of crow are one of: - crow==1.0.0 - crow==2.0.0 + ╰─▶ 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 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 the only versions of albatross are one of: - albatross==1.0.0 - albatross>=2.0.0 + 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 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 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. + 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 depends on one of: bluebird<=1.0.0 bluebird>=3.0.0 @@ -967,8 +971,8 @@ fn extra_incompatible_with_extra() -> Result<()> { ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ 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. + ╰─▶ Because albatross[extra-c]==1.0.0 is the only available version 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 albatross[extra-b]==1.0.0 is the only available version, 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. "###); }); @@ -1109,7 +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 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. + ╰─▶ Because albatross[extra]==1.0.0 depends on bluebird==1.0.0 and albatross[extra]==1.0.0 is the only available version, 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. "###); }); @@ -1306,7 +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 1.0.0 is the only available version of albatross, 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 albatross==1.0.0 is the only available version, 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. "###); }); @@ -1377,8 +1381,8 @@ fn transitive_incompatible_with_transitive() -> Result<()> { ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ 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. + ╰─▶ Because bluebird==1.0.0 is the only available version 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 albatross==1.0.0 is the only available version, 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. "###); }); @@ -1495,7 +1499,7 @@ fn package_only_prereleases_in_range() -> Result<()> { ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ 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. + ╰─▶ 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`) "###); @@ -2058,8 +2062,8 @@ fn transitive_package_only_prereleases_in_range() -> Result<()> { ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ 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. + ╰─▶ 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 albatross==0.1.0 is the only available version 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`) "###); @@ -2205,7 +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 1.0.0 is the only available version of albatross and root depends on albatross, we can conclude that the requirements are unsatisfiable. + And because albatross==1.0.0 is the only available version 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`) "###); @@ -2384,9 +2388,9 @@ fn transitive_prerelease_and_stable_dependency_many_versions() -> Result<()> { ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ 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. + ╰─▶ Because bluebird==1.0.0 is the only available version and bluebird==1.0.0 depends on crow, we can conclude that all versions of bluebird depends on crow. + And because only crow<2.0.0b1 is 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 albatross==1.0.0 is the only available version, 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`) @@ -2478,17 +2482,16 @@ fn transitive_prerelease_and_stable_dependency_many_versions_holes() -> Result<( ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ 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 + ╰─▶ 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 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 1.0.0 is the only available version of albatross and root depends on albatross, we can conclude that the requirements are unsatisfiable. + And because albatross==1.0.0 is the only available version 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 @@ -2551,7 +2554,7 @@ fn requires_python_version_does_not_exist() -> Result<()> { ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ 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. + ╰─▶ 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. "###); }); @@ -2608,7 +2611,7 @@ fn requires_python_version_less_than_current() -> Result<()> { ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ 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. + ╰─▶ 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. "###); }); @@ -2665,7 +2668,7 @@ fn requires_python_version_greater_than_current() -> Result<()> { ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ 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. + ╰─▶ 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. "###); }); @@ -2873,31 +2876,22 @@ fn requires_python_version_greater_than_current_excluded() -> Result<()> { ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ 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: + ╰─▶ 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. - 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 + 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 we can conclude that albatross>=2.0.0,<3.0.0 cannot be used. (1) - 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. + 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 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. + 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. "###); diff --git a/crates/puffin-resolver/src/pubgrub/report.rs b/crates/puffin-resolver/src/pubgrub/report.rs index 5cf175ddc841..2e657c931c5c 100644 --- a/crates/puffin-resolver/src/pubgrub/report.rs +++ b/crates/puffin-resolver/src/pubgrub/report.rs @@ -39,19 +39,19 @@ impl ReportFormatter> for PubGrubReportFormatter< } else { let complement = set.complement(); if let Some(version) = complement.as_singleton() { - format!("{version} is the only available version of {package}") + format!("{package}=={version} is the only available version") } else { let segments = complement.iter().collect::>().len(); if segments == 1 { format!( - "only versions of {package} matching {} are available", + "only {} is available", PackageRange::compatibility(package, &complement) ) } else { format!( - "the only versions of {} are {}", + "there are no versions of {} that satisfy {}", package, - PackageRange::dependency(package, &complement) + PackageRange::compatibility(package, &set) ) } }