diff --git a/crates/puffin-cli/tests/pip_compile.rs b/crates/puffin-cli/tests/pip_compile.rs index 980a19bf9..053844c99 100644 --- a/crates/puffin-cli/tests/pip_compile.rs +++ b/crates/puffin-cli/tests/pip_compile.rs @@ -687,11 +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. - And because root depends on black==23.10.1 we can conclude that the - requirements are unsatisfiable. + ╰─▶ Because black==23.10.1 depends on Python>=3.8 and root depends on + black==23.10.1, we can conclude that the requirements are unsatisfiable. "###); }); @@ -1442,9 +1439,7 @@ fn conflicting_direct_url_dependency() -> Result<()> { ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ Because there is no version of werkzeug==3.0.0 and root depends - on werkzeug==3.0.0, we can conclude that the requirements are - unsatisfiable. + ╰─▶ root depends on werkzeug==3.0.0 "###); }); @@ -1597,11 +1592,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. - And because root depends on flask==3.0.0 we can conclude that the - requirements are unsatisfiable. + ╰─▶ Because flask==3.0.0 depends on werkzeug>=3.0.0 and root depends on + flask==3.0.0, we can conclude that the requirements are unsatisfiable. "###); }); @@ -1950,9 +1942,7 @@ dependencies = ["django==300.1.4"] ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ Because there is no version of django==300.1.4 and my-project - depends on django==300.1.4, we can conclude that the requirements are - unsatisfiable. + ╰─▶ my-project depends on django==300.1.4 "###); }); @@ -2285,9 +2275,7 @@ fn compile_yanked_version_indirect() -> Result<()> { ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ Because there are no versions of attrs that satisfy attrs>20.3.0,<21.2.0 - and root depends on attrs>20.3.0,<21.2.0, we can conclude that the - requirements are unsatisfiable. + ╰─▶ root depends on attrs>20.3.0,<21.2.0 "###); }); diff --git a/crates/puffin-cli/tests/pip_install.rs b/crates/puffin-cli/tests/pip_install.rs index 1ef1dac96..3a0c90fad 100644 --- a/crates/puffin-cli/tests/pip_install.rs +++ b/crates/puffin-cli/tests/pip_install.rs @@ -80,11 +80,10 @@ 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. - 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. + ╰─▶ Because flask>=3.0.0 depends on werkzeug>=3.0.0 and root depends on + flask>=3.0.0, we can conclude that root depends on werkzeug>=3.0.0. + And because root depends on werkzeug<1.0.0 we can conclude that the + requirements are unsatisfiable. "###); Ok(()) diff --git a/crates/puffin-cli/tests/pip_install_scenarios.rs b/crates/puffin-cli/tests/pip_install_scenarios.rs index c6d91243f..f5c2f5138 100644 --- a/crates/puffin-cli/tests/pip_install_scenarios.rs +++ b/crates/puffin-cli/tests/pip_install_scenarios.rs @@ -134,7 +134,7 @@ fn requires_exact_version_does_not_exist() -> Result<()> { ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ Because there is no version of a==2.0.0 and root depends on a==2.0.0, we can conclude that the requirements are unsatisfiable. + ╰─▶ root depends on a==2.0.0 "###); }); @@ -189,7 +189,7 @@ fn requires_greater_version_does_not_exist() -> Result<()> { ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ Because there are no versions of a that satisfy a>1.0.0 and root depends on a>1.0.0, we can conclude that the requirements are unsatisfiable. + ╰─▶ root depends on a>1.0.0 "###); }); @@ -245,7 +245,7 @@ fn requires_less_version_does_not_exist() -> Result<()> { ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ Because there are no versions of a that satisfy a<2.0.0 and root depends on a<2.0.0, we can conclude that the requirements are unsatisfiable. + ╰─▶ root depends on a<2.0.0 "###); }); @@ -353,13 +353,10 @@ fn excluded_only_version() -> Result<()> { ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ Because there are no versions of a that satisfy any of: + ╰─▶ root depends on one of: a<1.0.0 a>1.0.0 - and root depends on one of: - a<1.0.0 - a>1.0.0 - we can conclude that the requirements are unsatisfiable. + "###); }); @@ -430,13 +427,7 @@ fn excluded_only_compatible_version() -> Result<()> { ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ Because there are no versions of a that satisfy any of: - a<1.0.0 - a>1.0.0,<2.0.0 - a>2.0.0,<3.0.0 - a>3.0.0 - and a==1.0.0 depends on b==1.0.0, we can conclude that a<2.0.0 depends on b==1.0.0. - And because a==3.0.0 depends on b==3.0.0 we can conclude that any of: + ╰─▶ Because a<2.0.0 depends on b==1.0.0 and a==3.0.0 depends on b==3.0.0, we can conclude that any of: a<2.0.0 a>2.0.0 depends on one of: @@ -544,23 +535,11 @@ fn dependency_excludes_range_of_compatible_versions() -> Result<()> { ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ Because there are no versions of a that satisfy any of: - a<1.0.0 - a>1.0.0,<2.0.0 - a>3.0.0 - and a==1.0.0 depends on b==1.0.0, we can conclude that a<2.0.0 depends on b==1.0.0. (1) - - Because there are no versions of c that satisfy any of: - c<1.0.0 - c>1.0.0,<2.0.0 - c>2.0.0 - and c==1.0.0 depends on a<2.0.0, we can conclude that c<2.0.0 depends on a<2.0.0. - And because c==2.0.0 depends on a>=3.0.0 we can conclude that all versions of c depends on one of: + ╰─▶ Because c==2.0.0 depends on a>=3.0.0 and c<2.0.0 depends on a<2.0.0, we can conclude that all versions of c depends on one of: a<2.0.0 a>=3.0.0 - And because we know from (1) that a<2.0.0 depends on b==1.0.0, we can conclude that a!=3.0.0, b!=1.0.0, all versions of c are incompatible. - And because a==3.0.0 depends on b==3.0.0 we can conclude that all versions of c depends on one of: + And because a<2.0.0 depends on b==1.0.0 and a==3.0.0 depends on b==3.0.0, we can conclude that all versions of c depends on one of: b<=1.0.0 b>=3.0.0 @@ -674,21 +653,8 @@ fn dependency_excludes_non_contiguous_range_of_compatible_versions() -> Result<( ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ Because there are no versions of c that satisfy any of: - c<1.0.0 - c>1.0.0,<2.0.0 - c>2.0.0 - and c==1.0.0 depends on a<2.0.0, we can conclude that c<2.0.0 depends on a<2.0.0. (1) - - Because a==1.0.0 depends on b==1.0.0 and there are no versions of a that satisfy any of: - a<1.0.0 - a>1.0.0,<2.0.0 - we can conclude that a<2.0.0 depends on b==1.0.0. - And because we know from (1) that c<2.0.0 depends on a<2.0.0, we can conclude that c<2.0.0 depends on b==1.0.0. - And because c==2.0.0 depends on a>=3.0.0 we can conclude that all versions of c, b!=1.0.0, !( a>=3.0.0 ) are incompatible. (2) - - Because a==3.0.0 depends on b==3.0.0 and there are no versions of a that satisfy a>3.0.0, we can conclude that a>=3.0.0 depends on b==3.0.0. - And because we know from (2) that all versions of c, b!=1.0.0, !( a>=3.0.0 ) are incompatible, we can conclude that all versions of c depends on one of: + ╰─▶ Because c<2.0.0 depends on a<2.0.0 and a<2.0.0 depends on b==1.0.0, we can conclude that c<2.0.0 depends on b==1.0.0. + And because c==2.0.0 depends on a>=3.0.0 and a>=3.0.0 depends on b==3.0.0, we can conclude that all versions of c depends on one of: b<=1.0.0 b>=3.0.0 @@ -953,14 +919,7 @@ fn extra_incompatible_with_extra() -> Result<()> { ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ Because there are no versions of a[extra-c] that satisfy any of: - a[extra-c]<1.0.0 - a[extra-c]>1.0.0 - and a[extra-c]==1.0.0 depends on b==2.0.0, we can conclude that all versions of a[extra-c] depends on b==2.0.0. - And because a[extra-b]==1.0.0 depends on b==1.0.0 and there are no versions of a[extra-b] that satisfy any of: - a[extra-b]<1.0.0 - a[extra-b]>1.0.0 - we can conclude that all versions of a[extra-b] and all versions of a[extra-c] are incompatible. + ╰─▶ Because all versions of a[extra-c] depends on b==2.0.0 and a[extra-b]==1.0.0 depends on b==1.0.0, we can conclude that a[extra-b]==1.0.0 and all versions of a[extra-c] are incompatible. And because root depends on a[extra-c] and root depends on a[extra-b], we can conclude that the requirements are unsatisfiable. "###); }); @@ -1097,11 +1056,8 @@ fn extra_incompatible_with_root() -> Result<()> { ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ Because a[extra]==1.0.0 depends on b==1.0.0 and there are no versions of a[extra] that satisfy any of: - a[extra]<1.0.0 - a[extra]>1.0.0 - we can conclude that all versions of a[extra] depends on b==1.0.0. - And because root depends on a[extra] and root depends on b==2.0.0, we can conclude that the requirements are unsatisfiable. + ╰─▶ Because all versions of a[extra] depends on b==1.0.0 and root depends on a[extra], we can conclude that root depends on b==1.0.0. + And because root depends on b==2.0.0 we can conclude that the requirements are unsatisfiable. "###); }); @@ -1292,11 +1248,8 @@ fn transitive_incompatible_with_root_version() -> Result<()> { ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ Because a==1.0.0 depends on b==2.0.0 and there are no versions of a that satisfy any of: - a<1.0.0 - a>1.0.0 - we can conclude that all versions of a depends on b==2.0.0. - And because root depends on b==1.0.0 and root depends on a, we can conclude that the requirements are unsatisfiable. + ╰─▶ Because all versions of a depends on b==2.0.0 and root depends on b==1.0.0, we can conclude that root==0a0.dev0 and all versions of a are incompatible. + And because root depends on a we can conclude that the requirements are unsatisfiable. "###); }); @@ -1363,14 +1316,7 @@ fn transitive_incompatible_with_transitive() -> Result<()> { ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ Because there are no versions of b that satisfy any of: - b<1.0.0 - b>1.0.0 - and b==1.0.0 depends on c==2.0.0, we can conclude that all versions of b depends on c==2.0.0. - And because a==1.0.0 depends on c==1.0.0 and there are no versions of a that satisfy any of: - a<1.0.0 - a>1.0.0 - we can conclude that all versions of b and all versions of a are incompatible. + ╰─▶ Because all versions of b depends on c==2.0.0 and a==1.0.0 depends on c==1.0.0, we can conclude that all versions of b and a==1.0.0 are incompatible. And because root depends on b and root depends on a, we can conclude that the requirements are unsatisfiable. "###); }); @@ -1485,7 +1431,7 @@ fn package_only_prereleases_in_range() -> Result<()> { ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ Because there are no versions of a that satisfy a>0.1.0 and root depends on a>0.1.0, we can conclude that the requirements are unsatisfiable. + ╰─▶ root depends on a>0.1.0 hint: Pre-releases are available for a in the requested range (e.g., 1.0.0a1), but pre-releases weren't enabled (try: `--prerelease=allow`) "###); @@ -2037,11 +1983,7 @@ fn transitive_package_only_prereleases_in_range() -> Result<()> { ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ Because there are no versions of b that satisfy b>0.1 and a==0.1.0 depends on b>0.1, we can conclude that a==0.1.0 cannot be used. - And because there are no versions of a that satisfy any of: - a<0.1.0 - a>0.1.0 - and root depends on a, we can conclude that the requirements are unsatisfiable. + ╰─▶ Because all versions of a depends on b>0.1 and root depends on a, we can conclude that the requirements are unsatisfiable. hint: Pre-releases are available for b in the requested range (e.g., 1.0.0a1), but pre-releases weren't enabled (try: `--prerelease=allow`) "###); @@ -2181,11 +2123,7 @@ fn transitive_prerelease_and_stable_dependency() -> Result<()> { ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ Because there is no version of c==2.0.0b1 and a==1.0.0 depends on c==2.0.0b1, we can conclude that a==1.0.0 cannot be used. - And because there are no versions of a that satisfy any of: - a<1.0.0 - a>1.0.0 - and root depends on a, we can conclude that the requirements are unsatisfiable. + ╰─▶ Because all versions of a depends on c==2.0.0b1 and root depends on a, we can conclude that the requirements are unsatisfiable. hint: c was requested with a pre-release marker (e.g., c==2.0.0b1), but pre-releases weren't enabled (try: `--prerelease=allow`) "###); @@ -2358,15 +2296,7 @@ fn transitive_prerelease_and_stable_dependency_many_versions() -> Result<()> { ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ Because there are no versions of b that satisfy any of: - b<1.0.0 - b>1.0.0 - and b==1.0.0 depends on c, we can conclude that all versions of b depends on c. - And because there are no versions of c that satisfy c>=2.0.0b1 we can conclude that all versions of b depends on c<2.0.0b1. - And because a==1.0.0 depends on c>=2.0.0b1 and there are no versions of a that satisfy any of: - a<1.0.0 - a>1.0.0 - we can conclude that all versions of b and all versions of a are incompatible. + ╰─▶ Because all versions of b depends on c and a==1.0.0 depends on c>=2.0.0b1, we can conclude that all versions of b and a==1.0.0 are incompatible. And because root depends on b and root depends on a, we can conclude that the requirements are unsatisfiable. hint: c was requested with a pre-release marker (e.g., c>=2.0.0b1), but pre-releases weren't enabled (try: `--prerelease=allow`) @@ -2455,18 +2385,10 @@ fn transitive_prerelease_and_stable_dependency_many_versions_holes() -> Result<( ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ Because there are no versions of c that satisfy any of: + ╰─▶ Because all versions of a depends on one of: c>1.0.0,<2.0.0a5 c>2.0.0a7,<2.0.0b1 c>2.0.0b1,<2.0.0b5 - and a==1.0.0 depends on one of: - c>1.0.0,<2.0.0a5 - c>2.0.0a7,<2.0.0b1 - c>2.0.0b1,<2.0.0b5 - we can conclude that a==1.0.0 cannot be used. - And because there are no versions of a that satisfy any of: - a<1.0.0 - a>1.0.0 and root depends on a, we can conclude that the requirements are unsatisfiable. hint: c was requested with a pre-release marker (e.g., any of: @@ -2529,8 +2451,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 a==1.0.0 depends on Python>=4.0, we can conclude that a==1.0.0 cannot be used. - And because root depends on a==1.0.0 we can conclude that the requirements are unsatisfiable. + ╰─▶ Because a==1.0.0 depends on Python>=4.0 and root depends on a==1.0.0, we can conclude that the requirements are unsatisfiable. "###); }); @@ -2585,8 +2506,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 a==1.0.0 depends on Python<=3.8, we can conclude that a==1.0.0 cannot be used. - And because root depends on a==1.0.0 we can conclude that the requirements are unsatisfiable. + ╰─▶ Because a==1.0.0 depends on Python<=3.8 and root depends on a==1.0.0, we can conclude that the requirements are unsatisfiable. "###); }); @@ -2641,8 +2561,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 a==1.0.0 depends on Python>=3.10, we can conclude that a==1.0.0 cannot be used. - And because root depends on a==1.0.0 we can conclude that the requirements are unsatisfiable. + ╰─▶ Because a==1.0.0 depends on Python>=3.10 and root depends on a==1.0.0, we can conclude that the requirements are unsatisfiable. "###); }); @@ -2719,7 +2638,7 @@ fn requires_python_version_greater_than_current_many() -> Result<()> { ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ Because there is no version of a==1.0.0 and root depends on a==1.0.0, we can conclude that the requirements are unsatisfiable. + ╰─▶ root depends on a==1.0.0 "###); }); @@ -2846,24 +2765,11 @@ 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: - 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 a==2.0.0 depends on Python>=3.10 and there are no versions of a that satisfy any of: - a>2.0.0,<3.0.0 - a>3.0.0,<4.0.0 - a>4.0.0 - we can conclude that a>=2.0.0,<3.0.0 cannot be used. (1) + ╰─▶ Because there are no versions of Python that satisfy Python>=3.10 and a==2.0.0 depends on Python>=3.10, we can conclude that a==2.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. - And because a==3.0.0 depends on Python>=3.11 we can conclude that a==3.0.0 cannot be used. - And because we know from (1) that a>=2.0.0,<3.0.0 cannot be used, we can conclude that a>=2.0.0,<4.0.0 cannot be used. (2) - - Because there are no versions of Python that satisfy Python>=3.12 and a==4.0.0 depends on Python>=3.12, we can conclude that a==4.0.0 cannot be used. - And because we know from (2) that a>=2.0.0,<4.0.0 cannot be used, we can conclude that a>=2.0.0 cannot be used. - And because root depends on a>=2.0.0 we can conclude that the requirements are unsatisfiable. + Because there are no versions of Python that satisfy Python>=3.11 and a==3.0.0 depends on Python>=3.11, we can conclude that a==3.0.0 cannot be used. + And because we know from (1) that a==2.0.0 cannot be used, we can conclude that a>=2.0.0,<4.0.0 cannot be used. + And because a==4.0.0 depends on Python>=3.12 and root depends on a>=2.0.0, we can conclude that the requirements are unsatisfiable. "###); }); diff --git a/crates/puffin-resolver/src/error.rs b/crates/puffin-resolver/src/error.rs index 71fdac554..9ccc83ab1 100644 --- a/crates/puffin-resolver/src/error.rs +++ b/crates/puffin-resolver/src/error.rs @@ -138,8 +138,11 @@ impl std::fmt::Display for NoSolutionError { let formatter = PubGrubReportFormatter { available_versions: &self.available_versions, }; - let report = - DefaultStringReporter::report_with_formatter(&self.derivation_tree, &formatter); + + let mut derivation_tree = self.derivation_tree.clone(); + derivation_tree.collapse_no_versions(); + + let report = DefaultStringReporter::report_with_formatter(&derivation_tree, &formatter); write!(f, "{report}")?; // Include any additional hints. diff --git a/crates/puffin-resolver/tests/resolver.rs b/crates/puffin-resolver/tests/resolver.rs index 74c28fb3d..4ccbc9da3 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. + root depends on black<=20.0 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. + root depends on black<=20.0 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,8 +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. - And because root depends on msgraph-sdk==1.0.0 we can conclude that the requirements are unsatisfiable. + Because msgraph-sdk==1.0.0 depends on msgraph-core>=1.0.0a2 and 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`) "###);