diff --git a/crates/puffin/tests/pip_compile_scenarios.rs b/crates/puffin/tests/pip_compile_scenarios.rs index d60cd83a3..1ebd7ccd5 100644 --- a/crates/puffin/tests/pip_compile_scenarios.rs +++ b/crates/puffin/tests/pip_compile_scenarios.rs @@ -1,7 +1,7 @@ //! DO NOT EDIT //! //! Generated with ./scripts/scenarios/update.py -//! Scenarios from +//! Scenarios from //! #![cfg(all(feature = "python", feature = "pypi"))] @@ -44,7 +44,7 @@ fn command(context: &TestContext, python_versions: &[&str]) -> Command { /// resolution. /// /// ```text -/// 006fed96 +/// df9d2d06 /// ├── environment /// │ └── python3.9 /// ├── root @@ -61,11 +61,11 @@ fn requires_incompatible_python_version_compatible_override() -> Result<()> { // In addition to the standard filters, swap out package names for more realistic messages let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"a-006fed96", "albatross")); - filters.push((r"-006fed96", "")); + filters.push((r"a-df9d2d06", "albatross")); + filters.push((r"-df9d2d06", "")); let requirements_in = context.temp_dir.child("requirements.in"); - requirements_in.write_str("a-006fed96==1.0.0")?; + requirements_in.write_str("a-df9d2d06==1.0.0")?; let output = puffin_snapshot!(filters, command(&context, python_versions) .arg("--python-version=3.11") @@ -86,7 +86,7 @@ fn requires_incompatible_python_version_compatible_override() -> Result<()> { output .assert() .success() - .stdout(predicate::str::contains("a-006fed96==1.0.0")); + .stdout(predicate::str::contains("a-df9d2d06==1.0.0")); Ok(()) } @@ -97,7 +97,7 @@ fn requires_incompatible_python_version_compatible_override() -> Result<()> { /// request an incompatible Python version for package resolution. /// /// ```text -/// 8c1b0389 +/// ad14da8a /// ├── environment /// │ └── python3.11 /// ├── root @@ -114,11 +114,11 @@ fn requires_compatible_python_version_incompatible_override() -> Result<()> { // In addition to the standard filters, swap out package names for more realistic messages let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"a-8c1b0389", "albatross")); - filters.push((r"-8c1b0389", "")); + filters.push((r"a-ad14da8a", "albatross")); + filters.push((r"-ad14da8a", "")); let requirements_in = context.temp_dir.child("requirements.in"); - requirements_in.write_str("a-8c1b0389==1.0.0")?; + requirements_in.write_str("a-ad14da8a==1.0.0")?; let output = puffin_snapshot!(filters, command(&context, python_versions) .arg("--python-version=3.9") @@ -147,7 +147,7 @@ fn requires_compatible_python_version_incompatible_override() -> Result<()> { /// source distributions available for the package. /// /// ```text -/// b8ee1c03 +/// 8efa8294 /// ├── environment /// │ └── python3.9 /// ├── root @@ -164,11 +164,11 @@ fn requires_incompatible_python_version_compatible_override_no_wheels() -> Resul // In addition to the standard filters, swap out package names for more realistic messages let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"a-b8ee1c03", "albatross")); - filters.push((r"-b8ee1c03", "")); + filters.push((r"a-8efa8294", "albatross")); + filters.push((r"-8efa8294", "")); let requirements_in = context.temp_dir.child("requirements.in"); - requirements_in.write_str("a-b8ee1c03==1.0.0")?; + requirements_in.write_str("a-8efa8294==1.0.0")?; // Since there are no wheels for the package and it is not compatible with the // local installation, we cannot build the source distribution to determine its @@ -201,7 +201,7 @@ fn requires_incompatible_python_version_compatible_override_no_wheels() -> Resul /// version installed elsewhere on their system. /// /// ```text -/// 23e00318 +/// 6b12f58c /// ├── environment /// │ ├── python3.11 /// │ └── python3.9 (active) @@ -220,11 +220,11 @@ fn requires_incompatible_python_version_compatible_override_no_wheels_available_ // In addition to the standard filters, swap out package names for more realistic messages let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"a-23e00318", "albatross")); - filters.push((r"-23e00318", "")); + filters.push((r"a-6b12f58c", "albatross")); + filters.push((r"-6b12f58c", "")); let requirements_in = context.temp_dir.child("requirements.in"); - requirements_in.write_str("a-23e00318==1.0.0")?; + requirements_in.write_str("a-6b12f58c==1.0.0")?; // Since there is a compatible Python version available on the system, it should be // used to build the source distributions. @@ -246,7 +246,7 @@ fn requires_incompatible_python_version_compatible_override_no_wheels_available_ output .assert() .success() - .stdout(predicate::str::contains("a-23e00318==1.0.0")); + .stdout(predicate::str::contains("a-6b12f58c==1.0.0")); Ok(()) } @@ -258,7 +258,7 @@ fn requires_incompatible_python_version_compatible_override_no_wheels_available_ /// wheel available for the package, but it does not have a compatible tag. /// /// ```text -/// c0ea406a +/// 27672836 /// ├── environment /// │ └── python3.9 /// ├── root @@ -275,11 +275,11 @@ fn requires_incompatible_python_version_compatible_override_no_compatible_wheels // In addition to the standard filters, swap out package names for more realistic messages let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"a-c0ea406a", "albatross")); - filters.push((r"-c0ea406a", "")); + filters.push((r"a-27672836", "albatross")); + filters.push((r"-27672836", "")); let requirements_in = context.temp_dir.child("requirements.in"); - requirements_in.write_str("a-c0ea406a==1.0.0")?; + requirements_in.write_str("a-27672836==1.0.0")?; // Since there are no compatible wheels for the package and it is not compatible // with the local installation, we cannot build the source distribution to @@ -312,7 +312,7 @@ fn requires_incompatible_python_version_compatible_override_no_compatible_wheels /// there is an incompatible version with a wheel available. /// /// ```text -/// 08a4e843 +/// 6413f0ea /// ├── environment /// │ └── python3.9 /// ├── root @@ -332,11 +332,11 @@ fn requires_incompatible_python_version_compatible_override_other_wheel() -> Res // In addition to the standard filters, swap out package names for more realistic messages let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"a-08a4e843", "albatross")); - filters.push((r"-08a4e843", "")); + filters.push((r"a-6413f0ea", "albatross")); + filters.push((r"-6413f0ea", "")); let requirements_in = context.temp_dir.child("requirements.in"); - requirements_in.write_str("a-08a4e843")?; + requirements_in.write_str("a-6413f0ea")?; // Since there are no wheels for the version of the package compatible with the // target and it is not compatible with the local installation, we cannot build the @@ -375,7 +375,7 @@ fn requires_incompatible_python_version_compatible_override_other_wheel() -> Res /// and the user provides a target version without a patch version. /// /// ```text -/// 2e1edfd6 +/// 6e610048 /// ├── environment /// │ └── python3.8.18 /// ├── root @@ -392,11 +392,11 @@ fn requires_python_patch_version_override_no_patch() -> Result<()> { // In addition to the standard filters, swap out package names for more realistic messages let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"a-2e1edfd6", "albatross")); - filters.push((r"-2e1edfd6", "")); + filters.push((r"a-6e610048", "albatross")); + filters.push((r"-6e610048", "")); let requirements_in = context.temp_dir.child("requirements.in"); - requirements_in.write_str("a-2e1edfd6==1.0.0")?; + requirements_in.write_str("a-6e610048==1.0.0")?; // Since the resolver is asked to solve with 3.8, the minimum compatible Python // requirement is treated as 3.8.0. @@ -425,7 +425,7 @@ fn requires_python_patch_version_override_no_patch() -> Result<()> { /// and the user provides a target version with a compatible patch version. /// /// ```text -/// 844899bd +/// 070b52ec /// ├── environment /// │ └── python3.8.18 /// ├── root @@ -442,11 +442,11 @@ fn requires_python_patch_version_override_patch_compatible() -> Result<()> { // In addition to the standard filters, swap out package names for more realistic messages let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"a-844899bd", "albatross")); - filters.push((r"-844899bd", "")); + filters.push((r"a-070b52ec", "albatross")); + filters.push((r"-070b52ec", "")); let requirements_in = context.temp_dir.child("requirements.in"); - requirements_in.write_str("a-844899bd==1.0.0")?; + requirements_in.write_str("a-070b52ec==1.0.0")?; let output = puffin_snapshot!(filters, command(&context, python_versions) .arg("--python-version=3.8.0") @@ -467,7 +467,7 @@ fn requires_python_patch_version_override_patch_compatible() -> Result<()> { output .assert() .success() - .stdout(predicate::str::contains("a-844899bd==1.0.0")); + .stdout(predicate::str::contains("a-070b52ec==1.0.0")); Ok(()) } diff --git a/crates/puffin/tests/pip_install_scenarios.rs b/crates/puffin/tests/pip_install_scenarios.rs index 822ad7c62..5554707e5 100644 --- a/crates/puffin/tests/pip_install_scenarios.rs +++ b/crates/puffin/tests/pip_install_scenarios.rs @@ -1,7 +1,7 @@ //! DO NOT EDIT //! //! Generated with ./scripts/scenarios/update.py -//! Scenarios from +//! Scenarios from //! #![cfg(all(feature = "python", feature = "pypi"))] @@ -1196,7 +1196,7 @@ fn package_only_prereleases_in_range() { /// opted into prereleases globally. /// /// ```text -/// af391f9c +/// ebc4dbde /// ├── environment /// │ └── python3.8 /// ├── root @@ -1212,12 +1212,12 @@ fn requires_package_only_prereleases_in_range_global_opt_in() { // In addition to the standard filters, swap out package names for more realistic messages let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"a-af391f9c", "albatross")); - filters.push((r"-af391f9c", "")); + filters.push((r"a-ebc4dbde", "albatross")); + filters.push((r"-ebc4dbde", "")); puffin_snapshot!(filters, command(&context) .arg("--prerelease=allow") - .arg("a-af391f9c>0.1.0") + .arg("a-ebc4dbde>0.1.0") , @r###" success: true exit_code: 0 @@ -1230,7 +1230,7 @@ fn requires_package_only_prereleases_in_range_global_opt_in() { + albatross==1.0.0a1 "###); - assert_installed(&context.venv, "a_af391f9c", "1.0.0a1", &context.temp_dir); + assert_installed(&context.venv, "a_ebc4dbde", "1.0.0a1", &context.temp_dir); } /// requires-package-prerelease-and-final-any @@ -2452,3 +2452,171 @@ fn no_wheels_with_matching_platform() { + albatross==1.0.0 "###); } + +/// no-wheels-no-build +/// +/// No wheels are available, only source distributions but the user has disabled +/// builds. +/// +/// ```text +/// d5567080 +/// ├── environment +/// │ └── python3.8 +/// ├── root +/// │ └── requires a +/// │ └── satisfied by a-1.0.0 +/// └── a +/// └── a-1.0.0 +/// ``` +#[test] +fn no_wheels_no_build() { + let context = TestContext::new("3.8"); + + // In addition to the standard filters, swap out package names for more realistic messages + let mut filters = INSTA_FILTERS.to_vec(); + filters.push((r"a-d5567080", "albatross")); + filters.push((r"-d5567080", "")); + + puffin_snapshot!(filters, command(&context) + .arg("--only-binary") + .arg("a-d5567080") + .arg("a-d5567080") + , @r###" + success: false + exit_code: 2 + ----- stdout ----- + + ----- stderr ----- + error: Failed to download and build: albatross==1.0.0 + Caused by: Building source distributions is disabled + "###); + + assert_not_installed(&context.venv, "a_d5567080", &context.temp_dir); +} + +/// only-wheels-no-binary +/// +/// No source distributions are available, only wheels but the user has disabled +/// using pre-built binaries. +/// +/// ```text +/// 3850ba71 +/// ├── environment +/// │ └── python3.8 +/// ├── root +/// │ └── requires a +/// │ └── satisfied by a-1.0.0 +/// └── a +/// └── a-1.0.0 +/// ``` +#[test] +fn only_wheels_no_binary() { + let context = TestContext::new("3.8"); + + // In addition to the standard filters, swap out package names for more realistic messages + let mut filters = INSTA_FILTERS.to_vec(); + filters.push((r"a-3850ba71", "albatross")); + filters.push((r"-3850ba71", "")); + + puffin_snapshot!(filters, command(&context) + .arg("--no-binary") + .arg("a-3850ba71") + .arg("a-3850ba71") + , @r###" + success: false + exit_code: 1 + ----- stdout ----- + + ----- stderr ----- + × No solution found when resolving dependencies: + ╰─▶ Because there are no versions of albatross and you require albatross, we can conclude that the requirements are unsatisfiable. + "###); + + assert_not_installed(&context.venv, "a_3850ba71", &context.temp_dir); +} + +/// no-build +/// +/// Both wheels and source distributions are available, and the user has disabled +/// builds. +/// +/// ```text +/// e0451b4c +/// ├── environment +/// │ └── python3.8 +/// ├── root +/// │ └── requires a +/// │ └── satisfied by a-1.0.0 +/// └── a +/// └── a-1.0.0 +/// ``` +#[test] +fn no_build() { + let context = TestContext::new("3.8"); + + // In addition to the standard filters, swap out package names for more realistic messages + let mut filters = INSTA_FILTERS.to_vec(); + filters.push((r"a-e0451b4c", "albatross")); + filters.push((r"-e0451b4c", "")); + + puffin_snapshot!(filters, command(&context) + .arg("--only-binary") + .arg("a-e0451b4c") + .arg("a-e0451b4c") + , @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Resolved 1 package in [TIME] + Downloaded 1 package in [TIME] + Installed 1 package in [TIME] + + albatross==1.0.0 + "###); + + // The wheel should be used for install +} + +/// no-binary +/// +/// Both wheels and source distributions are available, and the user has disabled +/// binaries. +/// +/// ```text +/// 5036ee47 +/// ├── environment +/// │ └── python3.8 +/// ├── root +/// │ └── requires a +/// │ └── satisfied by a-1.0.0 +/// └── a +/// └── a-1.0.0 +/// ``` +#[test] +fn no_binary() { + let context = TestContext::new("3.8"); + + // In addition to the standard filters, swap out package names for more realistic messages + let mut filters = INSTA_FILTERS.to_vec(); + filters.push((r"a-5036ee47", "albatross")); + filters.push((r"-5036ee47", "")); + + puffin_snapshot!(filters, command(&context) + .arg("--no-binary") + .arg("a-5036ee47") + .arg("a-5036ee47") + , @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Resolved 1 package in [TIME] + Downloaded 1 package in [TIME] + Installed 1 package in [TIME] + + albatross==1.0.0 + "###); + + // The source distribution should be used for install +} diff --git a/scripts/scenarios/templates/compile.mustache b/scripts/scenarios/templates/compile.mustache index eef8bf578..c0a65b174 100644 --- a/scripts/scenarios/templates/compile.mustache +++ b/scripts/scenarios/templates/compile.mustache @@ -72,9 +72,17 @@ fn {{module_name}}() -> Result<()> { // {{.}} {{/expected.explanation_lines}} let output = puffin_snapshot!(filters, command(&context, python_versions) - {{#environment.prereleases}} + {{#resolver_options.prereleases}} .arg("--prerelease=allow") - {{/environment.prereleases}} + {{/resolver_options.prereleases}} + {{#resolver_options.no_build}} + .arg("--only-binary") + .arg("{{.}}-{{version}}") + {{/resolver_options.no_build}} + {{#resolver_options.no_binary}} + .arg("--no-binary") + .arg("{{.}}-{{version}}") + {{/resolver_options.no_binary}} {{#resolver_options.python}} .arg("--python-version={{.}}") {{/resolver_options.python}}, @r###" diff --git a/scripts/scenarios/templates/install.mustache b/scripts/scenarios/templates/install.mustache index 56338cdf3..3b621825e 100644 --- a/scripts/scenarios/templates/install.mustache +++ b/scripts/scenarios/templates/install.mustache @@ -82,9 +82,17 @@ fn {{module_name}}() { filters.push((r"-{{version}}", "")); puffin_snapshot!(filters, command(&context) - {{#environment.prereleases}} + {{#resolver_options.prereleases}} .arg("--prerelease=allow") - {{/environment.prereleases}} + {{/resolver_options.prereleases}} + {{#resolver_options.no_build}} + .arg("--only-binary") + .arg("{{.}}-{{version}}") + {{/resolver_options.no_build}} + {{#resolver_options.no_binary}} + .arg("--no-binary") + .arg("{{.}}-{{version}}") + {{/resolver_options.no_binary}} {{#root.requires}} .arg("{{requirement}}") {{/root.requires}}, @r###" diff --git a/scripts/scenarios/update.py b/scripts/scenarios/update.py index 356672674..1038bcc95 100755 --- a/scripts/scenarios/update.py +++ b/scripts/scenarios/update.py @@ -45,7 +45,7 @@ import textwrap from pathlib import Path -PACKSE_COMMIT = "0563417be973397d05b45cd2c5b415d7215161e3" +PACKSE_COMMIT = "a5ce3f9dc5ce0db2b6e99bdfbd25b9d163953121" TOOL_ROOT = Path(__file__).parent TEMPLATES = TOOL_ROOT / "templates" INSTALL_TEMPLATE = TEMPLATES / "install.mustache"