diff --git a/crates/puffin-cli/tests/pip_install_scenarios.rs b/crates/puffin-cli/tests/pip_install_scenarios.rs index 2b542f1ef..c6d91243f 100644 --- a/crates/puffin-cli/tests/pip_install_scenarios.rs +++ b/crates/puffin-cli/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"))] @@ -44,21 +44,23 @@ fn assert_not_installed(venv: &Path, package: &'static str, temp_dir: &Path) { /// /// The user requires any version of package `a` which does not exist. /// -/// s57cd4136 +/// ```text +/// 57cd4136 /// ├── environment /// │ └── python3.7 /// └── root /// └── requires a /// └── unsatisfied: no versions for package +/// ``` #[test] fn requires_package_does_not_exist() -> Result<()> { let temp_dir = assert_fs::TempDir::new()?; let cache_dir = assert_fs::TempDir::new()?; let venv = create_venv(&temp_dir, &cache_dir, "python3.7"); - // In addition to the standard filters, remove the scenario prefix + // In addition to the standard filters, remove the scenario version let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"s57cd4136-", "")); + filters.push((r"-57cd4136", "")); insta::with_settings!({ filters => filters @@ -66,7 +68,7 @@ fn requires_package_does_not_exist() -> Result<()> { assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) .arg("pip") .arg("install") - .arg("s57cd4136-a") + .arg("a-57cd4136") .arg("--extra-index-url") .arg("https://test.pypi.org/simple") .arg("--cache-dir") @@ -83,7 +85,7 @@ fn requires_package_does_not_exist() -> Result<()> { "###); }); - assert_not_installed(&venv, "s57cd4136_a", &temp_dir); + assert_not_installed(&venv, "a_57cd4136", &temp_dir); Ok(()) } @@ -92,7 +94,8 @@ fn requires_package_does_not_exist() -> Result<()> { /// /// The user requires an exact version of package `a` but only other versions exist /// -/// seaa03067 +/// ```text +/// eaa03067 /// ├── environment /// │ └── python3.7 /// ├── root @@ -100,15 +103,16 @@ fn requires_package_does_not_exist() -> Result<()> { /// │ └── unsatisfied: no matching version /// └── a /// └── a-1.0.0 +/// ``` #[test] fn requires_exact_version_does_not_exist() -> Result<()> { let temp_dir = assert_fs::TempDir::new()?; let cache_dir = assert_fs::TempDir::new()?; let venv = create_venv(&temp_dir, &cache_dir, "python3.7"); - // In addition to the standard filters, remove the scenario prefix + // In addition to the standard filters, remove the scenario version let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"seaa03067-", "")); + filters.push((r"-eaa03067", "")); insta::with_settings!({ filters => filters @@ -116,7 +120,7 @@ fn requires_exact_version_does_not_exist() -> Result<()> { assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) .arg("pip") .arg("install") - .arg("seaa03067-a==2.0.0") + .arg("a-eaa03067==2.0.0") .arg("--extra-index-url") .arg("https://test.pypi.org/simple") .arg("--cache-dir") @@ -134,7 +138,7 @@ fn requires_exact_version_does_not_exist() -> Result<()> { "###); }); - assert_not_installed(&venv, "seaa03067_a", &temp_dir); + assert_not_installed(&venv, "a_eaa03067", &temp_dir); Ok(()) } @@ -144,7 +148,8 @@ fn requires_exact_version_does_not_exist() -> Result<()> { /// The user requires a version of `a` greater than `1.0.0` but only smaller or /// equal versions exist /// -/// s6e8e01df +/// ```text +/// 6e8e01df /// ├── environment /// │ └── python3.7 /// ├── root @@ -153,15 +158,16 @@ fn requires_exact_version_does_not_exist() -> Result<()> { /// └── a /// ├── a-0.1.0 /// └── a-1.0.0 +/// ``` #[test] fn requires_greater_version_does_not_exist() -> Result<()> { let temp_dir = assert_fs::TempDir::new()?; let cache_dir = assert_fs::TempDir::new()?; let venv = create_venv(&temp_dir, &cache_dir, "python3.7"); - // In addition to the standard filters, remove the scenario prefix + // In addition to the standard filters, remove the scenario version let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"s6e8e01df-", "")); + filters.push((r"-6e8e01df", "")); insta::with_settings!({ filters => filters @@ -169,7 +175,7 @@ fn requires_greater_version_does_not_exist() -> Result<()> { assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) .arg("pip") .arg("install") - .arg("s6e8e01df-a>1.0.0") + .arg("a-6e8e01df>1.0.0") .arg("--extra-index-url") .arg("https://test.pypi.org/simple") .arg("--cache-dir") @@ -187,7 +193,7 @@ fn requires_greater_version_does_not_exist() -> Result<()> { "###); }); - assert_not_installed(&venv, "s6e8e01df_a", &temp_dir); + assert_not_installed(&venv, "a_6e8e01df", &temp_dir); Ok(()) } @@ -197,7 +203,8 @@ fn requires_greater_version_does_not_exist() -> Result<()> { /// The user requires a version of `a` less than `1.0.0` but only larger versions /// exist /// -/// se45cec3c +/// ```text +/// e45cec3c /// ├── environment /// │ └── python3.7 /// ├── root @@ -207,15 +214,16 @@ fn requires_greater_version_does_not_exist() -> Result<()> { /// ├── a-2.0.0 /// ├── a-3.0.0 /// └── a-4.0.0 +/// ``` #[test] fn requires_less_version_does_not_exist() -> Result<()> { let temp_dir = assert_fs::TempDir::new()?; let cache_dir = assert_fs::TempDir::new()?; let venv = create_venv(&temp_dir, &cache_dir, "python3.7"); - // In addition to the standard filters, remove the scenario prefix + // In addition to the standard filters, remove the scenario version let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"se45cec3c-", "")); + filters.push((r"-e45cec3c", "")); insta::with_settings!({ filters => filters @@ -223,7 +231,7 @@ fn requires_less_version_does_not_exist() -> Result<()> { assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) .arg("pip") .arg("install") - .arg("se45cec3c-a<2.0.0") + .arg("a-e45cec3c<2.0.0") .arg("--extra-index-url") .arg("https://test.pypi.org/simple") .arg("--cache-dir") @@ -241,7 +249,7 @@ fn requires_less_version_does_not_exist() -> Result<()> { "###); }); - assert_not_installed(&venv, "se45cec3c_a", &temp_dir); + assert_not_installed(&venv, "a_e45cec3c", &temp_dir); Ok(()) } @@ -250,7 +258,8 @@ fn requires_less_version_does_not_exist() -> Result<()> { /// /// The user requires package `a` but `a` requires package `b` which does not exist /// -/// saca2796a +/// ```text +/// aca2796a /// ├── environment /// │ └── python3.7 /// ├── root @@ -260,15 +269,16 @@ fn requires_less_version_does_not_exist() -> Result<()> { /// └── a-1.0.0 /// └── requires b /// └── unsatisfied: no versions for package +/// ``` #[test] fn transitive_requires_package_does_not_exist() -> Result<()> { let temp_dir = assert_fs::TempDir::new()?; let cache_dir = assert_fs::TempDir::new()?; let venv = create_venv(&temp_dir, &cache_dir, "python3.7"); - // In addition to the standard filters, remove the scenario prefix + // In addition to the standard filters, remove the scenario version let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"saca2796a-", "")); + filters.push((r"-aca2796a", "")); insta::with_settings!({ filters => filters @@ -276,7 +286,7 @@ fn transitive_requires_package_does_not_exist() -> Result<()> { assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) .arg("pip") .arg("install") - .arg("saca2796a-a") + .arg("a-aca2796a") .arg("--extra-index-url") .arg("https://test.pypi.org/simple") .arg("--cache-dir") @@ -293,7 +303,7 @@ fn transitive_requires_package_does_not_exist() -> Result<()> { "###); }); - assert_not_installed(&venv, "saca2796a_a", &temp_dir); + assert_not_installed(&venv, "a_aca2796a", &temp_dir); Ok(()) } @@ -303,7 +313,8 @@ fn transitive_requires_package_does_not_exist() -> Result<()> { /// Only one version of the requested package is available, but the user has banned /// that version. /// -/// s7a9ed79c +/// ```text +/// 7a9ed79c /// ├── environment /// │ └── python3.7 /// ├── root @@ -311,15 +322,16 @@ fn transitive_requires_package_does_not_exist() -> Result<()> { /// │ └── unsatisfied: no matching version /// └── a /// └── a-1.0.0 +/// ``` #[test] fn excluded_only_version() -> Result<()> { let temp_dir = assert_fs::TempDir::new()?; let cache_dir = assert_fs::TempDir::new()?; let venv = create_venv(&temp_dir, &cache_dir, "python3.7"); - // In addition to the standard filters, remove the scenario prefix + // In addition to the standard filters, remove the scenario version let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"s7a9ed79c-", "")); + filters.push((r"-7a9ed79c", "")); insta::with_settings!({ filters => filters @@ -327,7 +339,7 @@ fn excluded_only_version() -> Result<()> { assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) .arg("pip") .arg("install") - .arg("s7a9ed79c-a!=1.0.0") + .arg("a-7a9ed79c!=1.0.0") .arg("--extra-index-url") .arg("https://test.pypi.org/simple") .arg("--cache-dir") @@ -352,7 +364,7 @@ fn excluded_only_version() -> Result<()> { }); // Only `a==1.0.0` is available but the user excluded it. - assert_not_installed(&venv, "s7a9ed79c_a", &temp_dir); + assert_not_installed(&venv, "a_7a9ed79c", &temp_dir); Ok(()) } @@ -362,14 +374,15 @@ fn excluded_only_version() -> Result<()> { /// Only one version of the requested package `a` is compatible, but the user has /// banned that version. /// -/// sd28c9e3c +/// ```text +/// b6b89642 /// ├── environment /// │ └── python3.7 /// ├── root /// │ ├── requires a!=2.0.0 /// │ │ ├── satisfied by a-1.0.0 /// │ │ └── satisfied by a-3.0.0 -/// │ └── requires b>=2.0.0,<3.0.0 +/// │ └── requires b<3.0.0,>=2.0.0 /// │ └── satisfied by b-2.0.0 /// ├── a /// │ ├── a-1.0.0 @@ -385,15 +398,16 @@ fn excluded_only_version() -> Result<()> { /// ├── b-1.0.0 /// ├── b-2.0.0 /// └── b-3.0.0 +/// ``` #[test] fn excluded_only_compatible_version() -> Result<()> { let temp_dir = assert_fs::TempDir::new()?; let cache_dir = assert_fs::TempDir::new()?; let venv = create_venv(&temp_dir, &cache_dir, "python3.7"); - // In addition to the standard filters, remove the scenario prefix + // In addition to the standard filters, remove the scenario version let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"sd28c9e3c-", "")); + filters.push((r"-b6b89642", "")); insta::with_settings!({ filters => filters @@ -401,8 +415,8 @@ fn excluded_only_compatible_version() -> Result<()> { assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) .arg("pip") .arg("install") - .arg("sd28c9e3c-a!=2.0.0") - .arg("sd28c9e3c-b>=2.0.0,<3.0.0") + .arg("a-b6b89642!=2.0.0") + .arg("b-b6b89642<3.0.0,>=2.0.0") .arg("--extra-index-url") .arg("https://test.pypi.org/simple") .arg("--cache-dir") @@ -429,18 +443,18 @@ fn excluded_only_compatible_version() -> Result<()> { b<=1.0.0 b>=3.0.0 - And because root depends on b>=2.0.0,<3.0.0 and root depends on one of: + And because root depends on one of: a<2.0.0 a>2.0.0 - we can conclude that the requirements are unsatisfiable. + and root depends on b>=2.0.0,<3.0.0, we can conclude that the requirements are unsatisfiable. "###); }); // Only `a==1.2.0` is available since `a==1.0.0` and `a==3.0.0` require // incompatible versions of `b`. The user has excluded that version of `a` so // resolution fails. - assert_not_installed(&venv, "sd28c9e3c_a", &temp_dir); - assert_not_installed(&venv, "sd28c9e3c_b", &temp_dir); + assert_not_installed(&venv, "a_b6b89642", &temp_dir); + assert_not_installed(&venv, "b_b6b89642", &temp_dir); Ok(()) } @@ -450,7 +464,8 @@ fn excluded_only_compatible_version() -> Result<()> { /// There is a range of compatible versions for the requested package `a`, but /// another dependency `c` excludes that range. /// -/// s2023222f +/// ```text +/// 1cd99bd0 /// ├── environment /// │ └── python3.7 /// ├── root @@ -461,7 +476,7 @@ fn excluded_only_compatible_version() -> Result<()> { /// │ │ ├── satisfied by a-2.2.0 /// │ │ ├── satisfied by a-2.3.0 /// │ │ └── satisfied by a-3.0.0 -/// │ ├── requires b>=2.0.0,<3.0.0 +/// │ ├── requires b<3.0.0,>=2.0.0 /// │ │ └── satisfied by b-2.0.0 /// │ └── requires c /// │ ├── satisfied by c-1.0.0 @@ -496,15 +511,16 @@ fn excluded_only_compatible_version() -> Result<()> { /// └── c-2.0.0 /// └── requires a>=3.0.0 /// └── satisfied by a-3.0.0 +/// ``` #[test] fn dependency_excludes_range_of_compatible_versions() -> Result<()> { let temp_dir = assert_fs::TempDir::new()?; let cache_dir = assert_fs::TempDir::new()?; let venv = create_venv(&temp_dir, &cache_dir, "python3.7"); - // In addition to the standard filters, remove the scenario prefix + // In addition to the standard filters, remove the scenario version let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"s2023222f-", "")); + filters.push((r"-1cd99bd0", "")); insta::with_settings!({ filters => filters @@ -512,9 +528,9 @@ fn dependency_excludes_range_of_compatible_versions() -> Result<()> { assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) .arg("pip") .arg("install") - .arg("s2023222f-a") - .arg("s2023222f-b>=2.0.0,<3.0.0") - .arg("s2023222f-c") + .arg("a-1cd99bd0") + .arg("b-1cd99bd0<3.0.0,>=2.0.0") + .arg("c-1cd99bd0") .arg("--extra-index-url") .arg("https://test.pypi.org/simple") .arg("--cache-dir") @@ -528,18 +544,11 @@ fn dependency_excludes_range_of_compatible_versions() -> Result<()> { ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ Because a==1.0.0 depends on b==1.0.0 and there are no versions of a that satisfy any of: + ╰─▶ 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 - 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: - a<2.0.0 - a>=3.0.0 - depends on one of: - b<=1.0.0 - b>=3.0.0 - (1) + 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 @@ -550,13 +559,8 @@ fn dependency_excludes_range_of_compatible_versions() -> Result<()> { a<2.0.0 a>=3.0.0 - And because we know from (1) that any of: - a<2.0.0 - a>=3.0.0 - depends on one of: - b<=1.0.0 - b>=3.0.0 - we can conclude that all versions of c depends on one of: + 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: b<=1.0.0 b>=3.0.0 @@ -567,9 +571,9 @@ fn dependency_excludes_range_of_compatible_versions() -> Result<()> { // Only the `2.x` versions of `a` are available since `a==1.0.0` and `a==3.0.0` // require incompatible versions of `b`, but all available versions of `c` exclude // that range of `a` so resolution fails. - assert_not_installed(&venv, "s2023222f_a", &temp_dir); - assert_not_installed(&venv, "s2023222f_b", &temp_dir); - assert_not_installed(&venv, "s2023222f_c", &temp_dir); + assert_not_installed(&venv, "a_1cd99bd0", &temp_dir); + assert_not_installed(&venv, "b_1cd99bd0", &temp_dir); + assert_not_installed(&venv, "c_1cd99bd0", &temp_dir); Ok(()) } @@ -582,7 +586,8 @@ fn dependency_excludes_range_of_compatible_versions() -> Result<()> { /// `a` are incompatible for another reason e.g. dependency on non-existant package /// `d`. /// -/// saece4208 +/// ```text +/// 0fd25b39 /// ├── environment /// │ └── python3.7 /// ├── root @@ -594,7 +599,7 @@ fn dependency_excludes_range_of_compatible_versions() -> Result<()> { /// │ │ ├── satisfied by a-2.3.0 /// │ │ ├── satisfied by a-2.4.0 /// │ │ └── satisfied by a-3.0.0 -/// │ ├── requires b>=2.0.0,<3.0.0 +/// │ ├── requires b<3.0.0,>=2.0.0 /// │ │ └── satisfied by b-2.0.0 /// │ └── requires c /// │ ├── satisfied by c-1.0.0 @@ -636,15 +641,16 @@ fn dependency_excludes_range_of_compatible_versions() -> Result<()> { /// └── c-2.0.0 /// └── requires a>=3.0.0 /// └── satisfied by a-3.0.0 +/// ``` #[test] fn dependency_excludes_non_contiguous_range_of_compatible_versions() -> Result<()> { let temp_dir = assert_fs::TempDir::new()?; let cache_dir = assert_fs::TempDir::new()?; let venv = create_venv(&temp_dir, &cache_dir, "python3.7"); - // In addition to the standard filters, remove the scenario prefix + // In addition to the standard filters, remove the scenario version let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"saece4208-", "")); + filters.push((r"-0fd25b39", "")); insta::with_settings!({ filters => filters @@ -652,9 +658,9 @@ fn dependency_excludes_non_contiguous_range_of_compatible_versions() -> Result<( assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) .arg("pip") .arg("install") - .arg("saece4208-a") - .arg("saece4208-b>=2.0.0,<3.0.0") - .arg("saece4208-c") + .arg("a-0fd25b39") + .arg("b-0fd25b39<3.0.0,>=2.0.0") + .arg("c-0fd25b39") .arg("--extra-index-url") .arg("https://test.pypi.org/simple") .arg("--cache-dir") @@ -679,10 +685,10 @@ fn dependency_excludes_non_contiguous_range_of_compatible_versions() -> Result<( 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 !( a>=3.0.0 ), all versions of c, b!=1.0.0 are incompatible. (2) + 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 !( a>=3.0.0 ), all versions of c, b!=1.0.0 are incompatible, we can conclude that all versions of c depends on one of: + 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: b<=1.0.0 b>=3.0.0 @@ -693,9 +699,484 @@ fn dependency_excludes_non_contiguous_range_of_compatible_versions() -> Result<( // Only the `2.x` versions of `a` are available since `a==1.0.0` and `a==3.0.0` // require incompatible versions of `b`, but all available versions of `c` exclude // that range of `a` so resolution fails. - assert_not_installed(&venv, "saece4208_a", &temp_dir); - assert_not_installed(&venv, "saece4208_b", &temp_dir); - assert_not_installed(&venv, "saece4208_c", &temp_dir); + assert_not_installed(&venv, "a_0fd25b39", &temp_dir); + assert_not_installed(&venv, "b_0fd25b39", &temp_dir); + assert_not_installed(&venv, "c_0fd25b39", &temp_dir); + + Ok(()) +} + +/// extra-required +/// +/// Optional dependencies are requested for the package. +/// +/// ```text +/// 76e5355c +/// ├── environment +/// │ └── python3.7 +/// ├── root +/// │ └── requires a[extra] +/// │ ├── satisfied by a-1.0.0 +/// │ └── satisfied by a-1.0.0[extra] +/// ├── a +/// │ ├── a-1.0.0 +/// │ └── a-1.0.0[extra] +/// │ └── requires b +/// │ └── satisfied by b-1.0.0 +/// └── b +/// └── b-1.0.0 +/// ``` +#[test] +fn extra_required() -> Result<()> { + let temp_dir = assert_fs::TempDir::new()?; + let cache_dir = assert_fs::TempDir::new()?; + let venv = create_venv(&temp_dir, &cache_dir, "python3.7"); + + // In addition to the standard filters, remove the scenario version + let mut filters = INSTA_FILTERS.to_vec(); + filters.push((r"-76e5355c", "")); + + insta::with_settings!({ + filters => filters + }, { + assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) + .arg("pip") + .arg("install") + .arg("a-76e5355c[extra]") + .arg("--extra-index-url") + .arg("https://test.pypi.org/simple") + .arg("--cache-dir") + .arg(cache_dir.path()) + .env("VIRTUAL_ENV", venv.as_os_str()) + .env("PUFFIN_NO_WRAP", "1") + .current_dir(&temp_dir), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Resolved 2 packages in [TIME] + Downloaded 2 packages in [TIME] + Installed 2 packages in [TIME] + + a==1.0.0 + + b==1.0.0 + "###); + }); + + assert_installed(&venv, "a_76e5355c", "1.0.0", &temp_dir); + assert_installed(&venv, "b_76e5355c", "1.0.0", &temp_dir); + + Ok(()) +} + +/// missing-extra +/// +/// Optional dependencies are requested for the package, but the extra does not +/// exist. +/// +/// ```text +/// 06e7489c +/// ├── environment +/// │ └── python3.7 +/// ├── root +/// │ └── requires a[extra] +/// │ └── satisfied by a-1.0.0 +/// └── a +/// └── a-1.0.0 +/// ``` +#[test] +fn missing_extra() -> Result<()> { + let temp_dir = assert_fs::TempDir::new()?; + let cache_dir = assert_fs::TempDir::new()?; + let venv = create_venv(&temp_dir, &cache_dir, "python3.7"); + + // In addition to the standard filters, remove the scenario version + let mut filters = INSTA_FILTERS.to_vec(); + filters.push((r"-06e7489c", "")); + + insta::with_settings!({ + filters => filters + }, { + assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) + .arg("pip") + .arg("install") + .arg("a-06e7489c[extra]") + .arg("--extra-index-url") + .arg("https://test.pypi.org/simple") + .arg("--cache-dir") + .arg(cache_dir.path()) + .env("VIRTUAL_ENV", venv.as_os_str()) + .env("PUFFIN_NO_WRAP", "1") + .current_dir(&temp_dir), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Resolved 1 package in [TIME] + Downloaded 1 package in [TIME] + Installed 1 package in [TIME] + + a==1.0.0 + "###); + }); + + // Missing extras are ignored during resolution. + assert_installed(&venv, "a_06e7489c", "1.0.0", &temp_dir); + + Ok(()) +} + +/// multiple-extras-required +/// +/// Multiple optional dependencies are requested for the package. +/// +/// ```text +/// e55f15c4 +/// ├── environment +/// │ └── python3.7 +/// ├── root +/// │ └── requires a[extra_b,extra_c] +/// │ ├── satisfied by a-1.0.0 +/// │ ├── satisfied by a-1.0.0[extra_b] +/// │ └── satisfied by a-1.0.0[extra_c] +/// ├── a +/// │ ├── a-1.0.0 +/// │ ├── a-1.0.0[extra_b] +/// │ │ └── requires b +/// │ │ └── satisfied by b-1.0.0 +/// │ └── a-1.0.0[extra_c] +/// │ └── requires c +/// │ └── satisfied by c-1.0.0 +/// ├── b +/// │ └── b-1.0.0 +/// └── c +/// └── c-1.0.0 +/// ``` +#[test] +fn multiple_extras_required() -> Result<()> { + let temp_dir = assert_fs::TempDir::new()?; + let cache_dir = assert_fs::TempDir::new()?; + let venv = create_venv(&temp_dir, &cache_dir, "python3.7"); + + // In addition to the standard filters, remove the scenario version + let mut filters = INSTA_FILTERS.to_vec(); + filters.push((r"-e55f15c4", "")); + + insta::with_settings!({ + filters => filters + }, { + assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) + .arg("pip") + .arg("install") + .arg("a-e55f15c4[extra_b,extra_c]") + .arg("--extra-index-url") + .arg("https://test.pypi.org/simple") + .arg("--cache-dir") + .arg(cache_dir.path()) + .env("VIRTUAL_ENV", venv.as_os_str()) + .env("PUFFIN_NO_WRAP", "1") + .current_dir(&temp_dir), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Resolved 3 packages in [TIME] + Downloaded 3 packages in [TIME] + Installed 3 packages in [TIME] + + a==1.0.0 + + b==1.0.0 + + c==1.0.0 + "###); + }); + + assert_installed(&venv, "a_e55f15c4", "1.0.0", &temp_dir); + assert_installed(&venv, "b_e55f15c4", "1.0.0", &temp_dir); + assert_installed(&venv, "c_e55f15c4", "1.0.0", &temp_dir); + + Ok(()) +} + +/// extra-incompatible-with-extra +/// +/// Multiple optional dependencies are requested for the package, but they have +/// conflicting requirements with each other. +/// +/// ```text +/// 492741b0 +/// ├── environment +/// │ └── python3.7 +/// ├── root +/// │ └── requires a[extra_b,extra_c] +/// │ ├── satisfied by a-1.0.0 +/// │ ├── satisfied by a-1.0.0[extra_b] +/// │ └── satisfied by a-1.0.0[extra_c] +/// ├── a +/// │ ├── a-1.0.0 +/// │ ├── a-1.0.0[extra_b] +/// │ │ └── requires b==1.0.0 +/// │ │ └── satisfied by b-1.0.0 +/// │ └── a-1.0.0[extra_c] +/// │ └── requires b==2.0.0 +/// │ └── satisfied by b-2.0.0 +/// └── b +/// ├── b-1.0.0 +/// └── b-2.0.0 +/// ``` +#[test] +fn extra_incompatible_with_extra() -> Result<()> { + let temp_dir = assert_fs::TempDir::new()?; + let cache_dir = assert_fs::TempDir::new()?; + let venv = create_venv(&temp_dir, &cache_dir, "python3.7"); + + // In addition to the standard filters, remove the scenario version + let mut filters = INSTA_FILTERS.to_vec(); + filters.push((r"-492741b0", "")); + + insta::with_settings!({ + filters => filters + }, { + assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) + .arg("pip") + .arg("install") + .arg("a-492741b0[extra_b,extra_c]") + .arg("--extra-index-url") + .arg("https://test.pypi.org/simple") + .arg("--cache-dir") + .arg(cache_dir.path()) + .env("VIRTUAL_ENV", venv.as_os_str()) + .env("PUFFIN_NO_WRAP", "1") + .current_dir(&temp_dir), @r###" + success: false + exit_code: 1 + ----- stdout ----- + + ----- 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. + And because root depends on a[extra-c] and root depends on a[extra-b], we can conclude that the requirements are unsatisfiable. + "###); + }); + + // Because both `extra_b` and `extra_c` are requested and they require incompatible + // versions of `b`, `a` cannot be installed. + assert_not_installed(&venv, "a_492741b0", &temp_dir); + + Ok(()) +} + +/// extra-incompatible-with-extra-not-requested +/// +/// One of two incompatible optional dependencies are requested for the package. +/// +/// ```text +/// f0b0089a +/// ├── environment +/// │ └── python3.7 +/// ├── root +/// │ └── requires a[extra_c] +/// │ ├── satisfied by a-1.0.0 +/// │ ├── satisfied by a-1.0.0[extra_b] +/// │ └── satisfied by a-1.0.0[extra_c] +/// ├── a +/// │ ├── a-1.0.0 +/// │ ├── a-1.0.0[extra_b] +/// │ │ └── requires b==1.0.0 +/// │ │ └── satisfied by b-1.0.0 +/// │ └── a-1.0.0[extra_c] +/// │ └── requires b==2.0.0 +/// │ └── satisfied by b-2.0.0 +/// └── b +/// ├── b-1.0.0 +/// └── b-2.0.0 +/// ``` +#[test] +fn extra_incompatible_with_extra_not_requested() -> Result<()> { + let temp_dir = assert_fs::TempDir::new()?; + let cache_dir = assert_fs::TempDir::new()?; + let venv = create_venv(&temp_dir, &cache_dir, "python3.7"); + + // In addition to the standard filters, remove the scenario version + let mut filters = INSTA_FILTERS.to_vec(); + filters.push((r"-f0b0089a", "")); + + insta::with_settings!({ + filters => filters + }, { + assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) + .arg("pip") + .arg("install") + .arg("a-f0b0089a[extra_c]") + .arg("--extra-index-url") + .arg("https://test.pypi.org/simple") + .arg("--cache-dir") + .arg(cache_dir.path()) + .env("VIRTUAL_ENV", venv.as_os_str()) + .env("PUFFIN_NO_WRAP", "1") + .current_dir(&temp_dir), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Resolved 2 packages in [TIME] + Downloaded 2 packages in [TIME] + Installed 2 packages in [TIME] + + a==1.0.0 + + b==2.0.0 + "###); + }); + + // Because the user does not request both extras, it is okay that one is + // incompatible with the other. + assert_installed(&venv, "a_f0b0089a", "1.0.0", &temp_dir); + assert_installed(&venv, "b_f0b0089a", "2.0.0", &temp_dir); + + Ok(()) +} + +/// extra-incompatible-with-root +/// +/// Optional dependencies are requested for the package, but the extra is not +/// compatible with other requested versions. +/// +/// ```text +/// 9d588075 +/// ├── environment +/// │ └── python3.7 +/// ├── root +/// │ ├── requires a[extra] +/// │ │ ├── satisfied by a-1.0.0 +/// │ │ └── satisfied by a-1.0.0[extra] +/// │ └── requires b==2.0.0 +/// │ └── satisfied by b-2.0.0 +/// ├── a +/// │ ├── a-1.0.0 +/// │ └── a-1.0.0[extra] +/// │ └── requires b==1.0.0 +/// │ └── satisfied by b-1.0.0 +/// └── b +/// ├── b-1.0.0 +/// └── b-2.0.0 +/// ``` +#[test] +fn extra_incompatible_with_root() -> Result<()> { + let temp_dir = assert_fs::TempDir::new()?; + let cache_dir = assert_fs::TempDir::new()?; + let venv = create_venv(&temp_dir, &cache_dir, "python3.7"); + + // In addition to the standard filters, remove the scenario version + let mut filters = INSTA_FILTERS.to_vec(); + filters.push((r"-9d588075", "")); + + insta::with_settings!({ + filters => filters + }, { + assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) + .arg("pip") + .arg("install") + .arg("a-9d588075[extra]") + .arg("b-9d588075==2.0.0") + .arg("--extra-index-url") + .arg("https://test.pypi.org/simple") + .arg("--cache-dir") + .arg(cache_dir.path()) + .env("VIRTUAL_ENV", venv.as_os_str()) + .env("PUFFIN_NO_WRAP", "1") + .current_dir(&temp_dir), @r###" + success: false + exit_code: 1 + ----- stdout ----- + + ----- 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 the user requested `b==2.0.0` but the requested extra requires + // `b==1.0.0`, the dependencies cannot be satisfied. + assert_not_installed(&venv, "a_9d588075", &temp_dir); + assert_not_installed(&venv, "b_9d588075", &temp_dir); + + Ok(()) +} + +/// extra-does-not-exist-backtrack +/// +/// Optional dependencies are requested for the package, the extra is only available +/// on an older version. +/// +/// ```text +/// f1877db3 +/// ├── environment +/// │ └── python3.7 +/// ├── root +/// │ └── requires a[extra] +/// │ ├── satisfied by a-1.0.0 +/// │ ├── satisfied by a-1.0.0[extra] +/// │ ├── satisfied by a-2.0.0 +/// │ └── satisfied by a-3.0.0 +/// ├── a +/// │ ├── a-1.0.0 +/// │ ├── a-1.0.0[extra] +/// │ │ └── requires b==1.0.0 +/// │ │ └── satisfied by b-1.0.0 +/// │ ├── a-2.0.0 +/// │ └── a-3.0.0 +/// └── b +/// └── b-1.0.0 +/// ``` +#[test] +fn extra_does_not_exist_backtrack() -> Result<()> { + let temp_dir = assert_fs::TempDir::new()?; + let cache_dir = assert_fs::TempDir::new()?; + let venv = create_venv(&temp_dir, &cache_dir, "python3.7"); + + // In addition to the standard filters, remove the scenario version + let mut filters = INSTA_FILTERS.to_vec(); + filters.push((r"-f1877db3", "")); + + insta::with_settings!({ + filters => filters + }, { + assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) + .arg("pip") + .arg("install") + .arg("a-f1877db3[extra]") + .arg("--extra-index-url") + .arg("https://test.pypi.org/simple") + .arg("--cache-dir") + .arg(cache_dir.path()) + .env("VIRTUAL_ENV", venv.as_os_str()) + .env("PUFFIN_NO_WRAP", "1") + .current_dir(&temp_dir), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Resolved 1 package in [TIME] + Downloaded 1 package in [TIME] + Installed 1 package in [TIME] + + a==3.0.0 + "###); + }); + + // The resolver should not backtrack to `a==1.0.0` because missing extras are + // allowed during resolution. `b` should not be installed. + assert_installed(&venv, "a_f1877db3", "3.0.0", &temp_dir); Ok(()) } @@ -704,7 +1185,8 @@ fn dependency_excludes_non_contiguous_range_of_compatible_versions() -> Result<( /// /// The user requires two incompatible, existing versions of package `a` /// -/// s80d82ee8 +/// ```text +/// 80d82ee8 /// ├── environment /// │ └── python3.7 /// ├── root @@ -715,15 +1197,16 @@ fn dependency_excludes_non_contiguous_range_of_compatible_versions() -> Result<( /// └── a /// ├── a-1.0.0 /// └── a-2.0.0 +/// ``` #[test] fn direct_incompatible_versions() -> Result<()> { let temp_dir = assert_fs::TempDir::new()?; let cache_dir = assert_fs::TempDir::new()?; let venv = create_venv(&temp_dir, &cache_dir, "python3.7"); - // In addition to the standard filters, remove the scenario prefix + // In addition to the standard filters, remove the scenario version let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"s80d82ee8-", "")); + filters.push((r"-80d82ee8", "")); insta::with_settings!({ filters => filters @@ -731,8 +1214,8 @@ fn direct_incompatible_versions() -> Result<()> { assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) .arg("pip") .arg("install") - .arg("s80d82ee8-a==1.0.0") - .arg("s80d82ee8-a==2.0.0") + .arg("a-80d82ee8==1.0.0") + .arg("a-80d82ee8==2.0.0") .arg("--extra-index-url") .arg("https://test.pypi.org/simple") .arg("--cache-dir") @@ -750,8 +1233,8 @@ fn direct_incompatible_versions() -> Result<()> { "###); }); - assert_not_installed(&venv, "s80d82ee8_a", &temp_dir); - assert_not_installed(&venv, "s80d82ee8_a", &temp_dir); + assert_not_installed(&venv, "a_80d82ee8", &temp_dir); + assert_not_installed(&venv, "a_80d82ee8", &temp_dir); Ok(()) } @@ -761,7 +1244,8 @@ fn direct_incompatible_versions() -> Result<()> { /// The user requires packages `a` and `b` but `a` requires a different version of /// `b` /// -/// sa967e815 +/// ```text +/// a967e815 /// ├── environment /// │ └── python3.7 /// ├── root @@ -776,15 +1260,16 @@ fn direct_incompatible_versions() -> Result<()> { /// └── b /// ├── b-1.0.0 /// └── b-2.0.0 +/// ``` #[test] fn transitive_incompatible_with_root_version() -> Result<()> { let temp_dir = assert_fs::TempDir::new()?; let cache_dir = assert_fs::TempDir::new()?; let venv = create_venv(&temp_dir, &cache_dir, "python3.7"); - // In addition to the standard filters, remove the scenario prefix + // In addition to the standard filters, remove the scenario version let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"sa967e815-", "")); + filters.push((r"-a967e815", "")); insta::with_settings!({ filters => filters @@ -792,8 +1277,8 @@ fn transitive_incompatible_with_root_version() -> Result<()> { assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) .arg("pip") .arg("install") - .arg("sa967e815-a") - .arg("sa967e815-b==1.0.0") + .arg("a-a967e815") + .arg("b-a967e815==1.0.0") .arg("--extra-index-url") .arg("https://test.pypi.org/simple") .arg("--cache-dir") @@ -815,8 +1300,8 @@ fn transitive_incompatible_with_root_version() -> Result<()> { "###); }); - assert_not_installed(&venv, "sa967e815_a", &temp_dir); - assert_not_installed(&venv, "sa967e815_b", &temp_dir); + assert_not_installed(&venv, "a_a967e815", &temp_dir); + assert_not_installed(&venv, "b_a967e815", &temp_dir); Ok(()) } @@ -826,7 +1311,8 @@ fn transitive_incompatible_with_root_version() -> Result<()> { /// The user requires package `a` and `b`; `a` and `b` require different versions of /// `c` /// -/// s6866d8dc +/// ```text +/// 6866d8dc /// ├── environment /// │ └── python3.7 /// ├── root @@ -845,15 +1331,16 @@ fn transitive_incompatible_with_root_version() -> Result<()> { /// └── c /// ├── c-1.0.0 /// └── c-2.0.0 +/// ``` #[test] fn transitive_incompatible_with_transitive() -> Result<()> { let temp_dir = assert_fs::TempDir::new()?; let cache_dir = assert_fs::TempDir::new()?; let venv = create_venv(&temp_dir, &cache_dir, "python3.7"); - // In addition to the standard filters, remove the scenario prefix + // In addition to the standard filters, remove the scenario version let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"s6866d8dc-", "")); + filters.push((r"-6866d8dc", "")); insta::with_settings!({ filters => filters @@ -861,8 +1348,8 @@ fn transitive_incompatible_with_transitive() -> Result<()> { assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) .arg("pip") .arg("install") - .arg("s6866d8dc-a") - .arg("s6866d8dc-b") + .arg("a-6866d8dc") + .arg("b-6866d8dc") .arg("--extra-index-url") .arg("https://test.pypi.org/simple") .arg("--cache-dir") @@ -876,20 +1363,20 @@ fn transitive_incompatible_with_transitive() -> 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 - and a==1.0.0 depends on c==1.0.0, we can conclude that all versions of a depends on c==1.0.0. - And because b==1.0.0 depends on c==2.0.0 and there are no versions of b that satisfy any of: + ╰─▶ Because there are no versions of b that satisfy any of: b<1.0.0 b>1.0.0 - we can conclude that all versions of a and all versions of b are incompatible. - And because root depends on a and root depends on b, we can conclude that the requirements are unsatisfiable. + 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. + And because root depends on b and root depends on a, we can conclude that the requirements are unsatisfiable. "###); }); - assert_not_installed(&venv, "s6866d8dc_a", &temp_dir); - assert_not_installed(&venv, "s6866d8dc_b", &temp_dir); + assert_not_installed(&venv, "a_6866d8dc", &temp_dir); + assert_not_installed(&venv, "b_6866d8dc", &temp_dir); Ok(()) } @@ -899,7 +1386,8 @@ fn transitive_incompatible_with_transitive() -> Result<()> { /// The user requires any version of package `a` which only has prerelease versions /// available. /// -/// s9a1b3dda +/// ```text +/// 9a1b3dda /// ├── environment /// │ └── python3.7 /// ├── root @@ -907,15 +1395,16 @@ fn transitive_incompatible_with_transitive() -> Result<()> { /// │ └── unsatisfied: no matching version /// └── a /// └── a-1.0.0a1 +/// ``` #[test] fn package_only_prereleases() -> Result<()> { let temp_dir = assert_fs::TempDir::new()?; let cache_dir = assert_fs::TempDir::new()?; let venv = create_venv(&temp_dir, &cache_dir, "python3.7"); - // In addition to the standard filters, remove the scenario prefix + // In addition to the standard filters, remove the scenario version let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"s9a1b3dda-", "")); + filters.push((r"-9a1b3dda", "")); insta::with_settings!({ filters => filters @@ -923,7 +1412,7 @@ fn package_only_prereleases() -> Result<()> { assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) .arg("pip") .arg("install") - .arg("s9a1b3dda-a") + .arg("a-9a1b3dda") .arg("--extra-index-url") .arg("https://test.pypi.org/simple") .arg("--cache-dir") @@ -945,7 +1434,7 @@ fn package_only_prereleases() -> Result<()> { // Since there are only prerelease versions of `a` available, it should be // installed even though the user did not include a prerelease specifier. - assert_installed(&venv, "s9a1b3dda_a", "1.0.0a1", &temp_dir); + assert_installed(&venv, "a_9a1b3dda", "1.0.0a1", &temp_dir); Ok(()) } @@ -955,7 +1444,8 @@ fn package_only_prereleases() -> Result<()> { /// The user requires a version of package `a` which only matches prerelease /// versions but they did not include a prerelease specifier. /// -/// s19673198 +/// ```text +/// 19673198 /// ├── environment /// │ └── python3.7 /// ├── root @@ -964,15 +1454,16 @@ fn package_only_prereleases() -> Result<()> { /// └── a /// ├── a-0.1.0 /// └── a-1.0.0a1 +/// ``` #[test] fn package_only_prereleases_in_range() -> Result<()> { let temp_dir = assert_fs::TempDir::new()?; let cache_dir = assert_fs::TempDir::new()?; let venv = create_venv(&temp_dir, &cache_dir, "python3.7"); - // In addition to the standard filters, remove the scenario prefix + // In addition to the standard filters, remove the scenario version let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"s19673198-", "")); + filters.push((r"-19673198", "")); insta::with_settings!({ filters => filters @@ -980,7 +1471,7 @@ fn package_only_prereleases_in_range() -> Result<()> { assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) .arg("pip") .arg("install") - .arg("s19673198-a>0.1.0") + .arg("a-19673198>0.1.0") .arg("--extra-index-url") .arg("https://test.pypi.org/simple") .arg("--cache-dir") @@ -1002,7 +1493,7 @@ fn package_only_prereleases_in_range() -> Result<()> { // Since there are stable versions of `a` available, prerelease versions should not // be selected without explicit opt-in. - assert_not_installed(&venv, "s19673198_a", &temp_dir); + assert_not_installed(&venv, "a_19673198", &temp_dir); Ok(()) } @@ -1013,7 +1504,8 @@ fn package_only_prereleases_in_range() -> Result<()> { /// versions. They did not include a prerelease specifier for the package, but they /// opted into prereleases globally. /// -/// s51f94da2 +/// ```text +/// 51f94da2 /// ├── environment /// │ └── python3.7 /// ├── root @@ -1022,15 +1514,16 @@ fn package_only_prereleases_in_range() -> Result<()> { /// └── a /// ├── a-0.1.0 /// └── a-1.0.0a1 +/// ``` #[test] fn requires_package_only_prereleases_in_range_global_opt_in() -> Result<()> { let temp_dir = assert_fs::TempDir::new()?; let cache_dir = assert_fs::TempDir::new()?; let venv = create_venv(&temp_dir, &cache_dir, "python3.7"); - // In addition to the standard filters, remove the scenario prefix + // In addition to the standard filters, remove the scenario version let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"s51f94da2-", "")); + filters.push((r"-51f94da2", "")); insta::with_settings!({ filters => filters @@ -1038,7 +1531,7 @@ fn requires_package_only_prereleases_in_range_global_opt_in() -> Result<()> { assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) .arg("pip") .arg("install") - .arg("s51f94da2-a>0.1.0") + .arg("a-51f94da2>0.1.0") .arg("--prerelease=allow") .arg("--extra-index-url") .arg("https://test.pypi.org/simple") @@ -1059,7 +1552,7 @@ fn requires_package_only_prereleases_in_range_global_opt_in() -> Result<()> { "###); }); - assert_installed(&venv, "s51f94da2_a", "1.0.0a1", &temp_dir); + assert_installed(&venv, "a_51f94da2", "1.0.0a1", &temp_dir); Ok(()) } @@ -1069,7 +1562,8 @@ fn requires_package_only_prereleases_in_range_global_opt_in() -> Result<()> { /// The user requires any version of package `a` has a prerelease version available /// and an older non-prerelease version. /// -/// seebe53a6 +/// ```text +/// eebe53a6 /// ├── environment /// │ └── python3.7 /// ├── root @@ -1078,15 +1572,16 @@ fn requires_package_only_prereleases_in_range_global_opt_in() -> Result<()> { /// └── a /// ├── a-0.1.0 /// └── a-1.0.0a1 +/// ``` #[test] fn requires_package_prerelease_and_final_any() -> Result<()> { let temp_dir = assert_fs::TempDir::new()?; let cache_dir = assert_fs::TempDir::new()?; let venv = create_venv(&temp_dir, &cache_dir, "python3.7"); - // In addition to the standard filters, remove the scenario prefix + // In addition to the standard filters, remove the scenario version let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"seebe53a6-", "")); + filters.push((r"-eebe53a6", "")); insta::with_settings!({ filters => filters @@ -1094,7 +1589,7 @@ fn requires_package_prerelease_and_final_any() -> Result<()> { assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) .arg("pip") .arg("install") - .arg("seebe53a6-a") + .arg("a-eebe53a6") .arg("--extra-index-url") .arg("https://test.pypi.org/simple") .arg("--cache-dir") @@ -1116,7 +1611,7 @@ fn requires_package_prerelease_and_final_any() -> Result<()> { // Since the user did not provide a prerelease specifier, the older stable version // should be selected. - assert_installed(&venv, "seebe53a6_a", "0.1.0", &temp_dir); + assert_installed(&venv, "a_eebe53a6", "0.1.0", &temp_dir); Ok(()) } @@ -1126,7 +1621,8 @@ fn requires_package_prerelease_and_final_any() -> Result<()> { /// The user requires a version of `a` with a prerelease specifier and only stable /// releases are available. /// -/// s9d4725eb +/// ```text +/// 9d4725eb /// ├── environment /// │ └── python3.7 /// ├── root @@ -1138,15 +1634,16 @@ fn requires_package_prerelease_and_final_any() -> Result<()> { /// ├── a-0.1.0 /// ├── a-0.2.0 /// └── a-0.3.0 +/// ``` #[test] fn package_prerelease_specified_only_final_available() -> Result<()> { let temp_dir = assert_fs::TempDir::new()?; let cache_dir = assert_fs::TempDir::new()?; let venv = create_venv(&temp_dir, &cache_dir, "python3.7"); - // In addition to the standard filters, remove the scenario prefix + // In addition to the standard filters, remove the scenario version let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"s9d4725eb-", "")); + filters.push((r"-9d4725eb", "")); insta::with_settings!({ filters => filters @@ -1154,7 +1651,7 @@ fn package_prerelease_specified_only_final_available() -> Result<()> { assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) .arg("pip") .arg("install") - .arg("s9d4725eb-a>=0.1.0a1") + .arg("a-9d4725eb>=0.1.0a1") .arg("--extra-index-url") .arg("https://test.pypi.org/simple") .arg("--cache-dir") @@ -1175,7 +1672,7 @@ fn package_prerelease_specified_only_final_available() -> Result<()> { }); // The latest stable version should be selected. - assert_installed(&venv, "s9d4725eb_a", "0.3.0", &temp_dir); + assert_installed(&venv, "a_9d4725eb", "0.3.0", &temp_dir); Ok(()) } @@ -1185,7 +1682,8 @@ fn package_prerelease_specified_only_final_available() -> Result<()> { /// The user requires a version of `a` with a prerelease specifier and only /// prerelease releases are available. /// -/// s6cc95bc8 +/// ```text +/// 6cc95bc8 /// ├── environment /// │ └── python3.7 /// ├── root @@ -1197,15 +1695,16 @@ fn package_prerelease_specified_only_final_available() -> Result<()> { /// ├── a-0.1.0a1 /// ├── a-0.2.0a1 /// └── a-0.3.0a1 +/// ``` #[test] fn package_prerelease_specified_only_prerelease_available() -> Result<()> { let temp_dir = assert_fs::TempDir::new()?; let cache_dir = assert_fs::TempDir::new()?; let venv = create_venv(&temp_dir, &cache_dir, "python3.7"); - // In addition to the standard filters, remove the scenario prefix + // In addition to the standard filters, remove the scenario version let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"s6cc95bc8-", "")); + filters.push((r"-6cc95bc8", "")); insta::with_settings!({ filters => filters @@ -1213,7 +1712,7 @@ fn package_prerelease_specified_only_prerelease_available() -> Result<()> { assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) .arg("pip") .arg("install") - .arg("s6cc95bc8-a>=0.1.0a1") + .arg("a-6cc95bc8>=0.1.0a1") .arg("--extra-index-url") .arg("https://test.pypi.org/simple") .arg("--cache-dir") @@ -1234,7 +1733,7 @@ fn package_prerelease_specified_only_prerelease_available() -> Result<()> { }); // The latest prerelease version should be selected. - assert_installed(&venv, "s6cc95bc8_a", "0.3.0a1", &temp_dir); + assert_installed(&venv, "a_6cc95bc8", "0.3.0a1", &temp_dir); Ok(()) } @@ -1244,7 +1743,8 @@ fn package_prerelease_specified_only_prerelease_available() -> Result<()> { /// The user requires a version of `a` with a prerelease specifier and both /// prerelease and stable releases are available. /// -/// sc97845e2 +/// ```text +/// c97845e2 /// ├── environment /// │ └── python3.7 /// ├── root @@ -1258,15 +1758,16 @@ fn package_prerelease_specified_only_prerelease_available() -> Result<()> { /// ├── a-0.2.0a1 /// ├── a-0.3.0 /// └── a-1.0.0a1 +/// ``` #[test] fn package_prerelease_specified_mixed_available() -> Result<()> { let temp_dir = assert_fs::TempDir::new()?; let cache_dir = assert_fs::TempDir::new()?; let venv = create_venv(&temp_dir, &cache_dir, "python3.7"); - // In addition to the standard filters, remove the scenario prefix + // In addition to the standard filters, remove the scenario version let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"sc97845e2-", "")); + filters.push((r"-c97845e2", "")); insta::with_settings!({ filters => filters @@ -1274,7 +1775,7 @@ fn package_prerelease_specified_mixed_available() -> Result<()> { assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) .arg("pip") .arg("install") - .arg("sc97845e2-a>=0.1.0a1") + .arg("a-c97845e2>=0.1.0a1") .arg("--extra-index-url") .arg("https://test.pypi.org/simple") .arg("--cache-dir") @@ -1296,7 +1797,7 @@ fn package_prerelease_specified_mixed_available() -> Result<()> { // Since the user provided a prerelease specifier, the latest prerelease version // should be selected. - assert_installed(&venv, "sc97845e2_a", "1.0.0a1", &temp_dir); + assert_installed(&venv, "a_c97845e2", "1.0.0a1", &temp_dir); Ok(()) } @@ -1306,7 +1807,8 @@ fn package_prerelease_specified_mixed_available() -> Result<()> { /// The user requires `a` which has multiple prereleases available with different /// labels. /// -/// se290bf29 +/// ```text +/// e290bf29 /// ├── environment /// │ └── python3.7 /// ├── root @@ -1318,15 +1820,16 @@ fn package_prerelease_specified_mixed_available() -> Result<()> { /// ├── a-1.0.0a1 /// ├── a-1.0.0b1 /// └── a-1.0.0rc1 +/// ``` #[test] fn package_multiple_prereleases_kinds() -> Result<()> { let temp_dir = assert_fs::TempDir::new()?; let cache_dir = assert_fs::TempDir::new()?; let venv = create_venv(&temp_dir, &cache_dir, "python3.7"); - // In addition to the standard filters, remove the scenario prefix + // In addition to the standard filters, remove the scenario version let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"se290bf29-", "")); + filters.push((r"-e290bf29", "")); insta::with_settings!({ filters => filters @@ -1334,7 +1837,7 @@ fn package_multiple_prereleases_kinds() -> Result<()> { assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) .arg("pip") .arg("install") - .arg("se290bf29-a>=1.0.0a1") + .arg("a-e290bf29>=1.0.0a1") .arg("--extra-index-url") .arg("https://test.pypi.org/simple") .arg("--cache-dir") @@ -1355,7 +1858,7 @@ fn package_multiple_prereleases_kinds() -> Result<()> { }); // Release candidates should be the highest precedence prerelease kind. - assert_installed(&venv, "se290bf29_a", "1.0.0rc1", &temp_dir); + assert_installed(&venv, "a_e290bf29", "1.0.0rc1", &temp_dir); Ok(()) } @@ -1364,7 +1867,8 @@ fn package_multiple_prereleases_kinds() -> Result<()> { /// /// The user requires `a` which has multiple alphas available. /// -/// sf5948c28 +/// ```text +/// f5948c28 /// ├── environment /// │ └── python3.7 /// ├── root @@ -1376,15 +1880,16 @@ fn package_multiple_prereleases_kinds() -> Result<()> { /// ├── a-1.0.0a1 /// ├── a-1.0.0a2 /// └── a-1.0.0a3 +/// ``` #[test] fn package_multiple_prereleases_numbers() -> Result<()> { let temp_dir = assert_fs::TempDir::new()?; let cache_dir = assert_fs::TempDir::new()?; let venv = create_venv(&temp_dir, &cache_dir, "python3.7"); - // In addition to the standard filters, remove the scenario prefix + // In addition to the standard filters, remove the scenario version let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"sf5948c28-", "")); + filters.push((r"-f5948c28", "")); insta::with_settings!({ filters => filters @@ -1392,7 +1897,7 @@ fn package_multiple_prereleases_numbers() -> Result<()> { assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) .arg("pip") .arg("install") - .arg("sf5948c28-a>=1.0.0a1") + .arg("a-f5948c28>=1.0.0a1") .arg("--extra-index-url") .arg("https://test.pypi.org/simple") .arg("--cache-dir") @@ -1413,7 +1918,7 @@ fn package_multiple_prereleases_numbers() -> Result<()> { }); // The latest alpha version should be selected. - assert_installed(&venv, "sf5948c28_a", "1.0.0a3", &temp_dir); + assert_installed(&venv, "a_f5948c28", "1.0.0a3", &temp_dir); Ok(()) } @@ -1423,7 +1928,8 @@ fn package_multiple_prereleases_numbers() -> Result<()> { /// The user requires any version of package `a` which requires `b` which only has /// prerelease versions available. /// -/// s44ebef16 +/// ```text +/// 44ebef16 /// ├── environment /// │ └── python3.7 /// ├── root @@ -1435,15 +1941,16 @@ fn package_multiple_prereleases_numbers() -> Result<()> { /// │ └── unsatisfied: no matching version /// └── b /// └── b-1.0.0a1 +/// ``` #[test] fn transitive_package_only_prereleases() -> Result<()> { let temp_dir = assert_fs::TempDir::new()?; let cache_dir = assert_fs::TempDir::new()?; let venv = create_venv(&temp_dir, &cache_dir, "python3.7"); - // In addition to the standard filters, remove the scenario prefix + // In addition to the standard filters, remove the scenario version let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"s44ebef16-", "")); + filters.push((r"-44ebef16", "")); insta::with_settings!({ filters => filters @@ -1451,7 +1958,7 @@ fn transitive_package_only_prereleases() -> Result<()> { assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) .arg("pip") .arg("install") - .arg("s44ebef16-a") + .arg("a-44ebef16") .arg("--extra-index-url") .arg("https://test.pypi.org/simple") .arg("--cache-dir") @@ -1474,8 +1981,8 @@ fn transitive_package_only_prereleases() -> Result<()> { // Since there are only prerelease versions of `b` available, it should be selected // even though the user did not opt-in to prereleases. - assert_installed(&venv, "s44ebef16_a", "0.1.0", &temp_dir); - assert_installed(&venv, "s44ebef16_b", "1.0.0a1", &temp_dir); + assert_installed(&venv, "a_44ebef16", "0.1.0", &temp_dir); + assert_installed(&venv, "b_44ebef16", "1.0.0a1", &temp_dir); Ok(()) } @@ -1485,7 +1992,8 @@ fn transitive_package_only_prereleases() -> Result<()> { /// The user requires package `a` which has a dependency on a package which only /// matches prerelease versions but they did not include a prerelease specifier. /// -/// s27759187 +/// ```text +/// 27759187 /// ├── environment /// │ └── python3.7 /// ├── root @@ -1498,15 +2006,16 @@ fn transitive_package_only_prereleases() -> Result<()> { /// └── b /// ├── b-0.1.0 /// └── b-1.0.0a1 +/// ``` #[test] fn transitive_package_only_prereleases_in_range() -> Result<()> { let temp_dir = assert_fs::TempDir::new()?; let cache_dir = assert_fs::TempDir::new()?; let venv = create_venv(&temp_dir, &cache_dir, "python3.7"); - // In addition to the standard filters, remove the scenario prefix + // In addition to the standard filters, remove the scenario version let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"s27759187-", "")); + filters.push((r"-27759187", "")); insta::with_settings!({ filters => filters @@ -1514,7 +2023,7 @@ fn transitive_package_only_prereleases_in_range() -> Result<()> { assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) .arg("pip") .arg("install") - .arg("s27759187-a") + .arg("a-27759187") .arg("--extra-index-url") .arg("https://test.pypi.org/simple") .arg("--cache-dir") @@ -1541,7 +2050,7 @@ fn transitive_package_only_prereleases_in_range() -> Result<()> { // Since there are stable versions of `b` available, the prerelease version should // not be selected without explicit opt-in. The available version is excluded by // the range requested by the user. - assert_not_installed(&venv, "s27759187_a", &temp_dir); + assert_not_installed(&venv, "a_27759187", &temp_dir); Ok(()) } @@ -1552,7 +2061,8 @@ fn transitive_package_only_prereleases_in_range() -> Result<()> { /// matches prerelease versions; the user has opted into allowing prereleases in `b` /// explicitly. /// -/// s26efb6c5 +/// ```text +/// 26efb6c5 /// ├── environment /// │ └── python3.7 /// ├── root @@ -1567,15 +2077,16 @@ fn transitive_package_only_prereleases_in_range() -> Result<()> { /// └── b /// ├── b-0.1.0 /// └── b-1.0.0a1 +/// ``` #[test] fn transitive_package_only_prereleases_in_range_opt_in() -> Result<()> { let temp_dir = assert_fs::TempDir::new()?; let cache_dir = assert_fs::TempDir::new()?; let venv = create_venv(&temp_dir, &cache_dir, "python3.7"); - // In addition to the standard filters, remove the scenario prefix + // In addition to the standard filters, remove the scenario version let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"s26efb6c5-", "")); + filters.push((r"-26efb6c5", "")); insta::with_settings!({ filters => filters @@ -1583,8 +2094,8 @@ fn transitive_package_only_prereleases_in_range_opt_in() -> Result<()> { assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) .arg("pip") .arg("install") - .arg("s26efb6c5-a") - .arg("s26efb6c5-b>0.0.0a1") + .arg("a-26efb6c5") + .arg("b-26efb6c5>0.0.0a1") .arg("--extra-index-url") .arg("https://test.pypi.org/simple") .arg("--cache-dir") @@ -1607,8 +2118,8 @@ fn transitive_package_only_prereleases_in_range_opt_in() -> Result<()> { // Since the user included a dependency on `b` with a prerelease specifier, a // prerelease version can be selected. - assert_installed(&venv, "s26efb6c5_a", "0.1.0", &temp_dir); - assert_installed(&venv, "s26efb6c5_b", "1.0.0a1", &temp_dir); + assert_installed(&venv, "a_26efb6c5", "0.1.0", &temp_dir); + assert_installed(&venv, "b_26efb6c5", "1.0.0a1", &temp_dir); Ok(()) } @@ -1618,7 +2129,8 @@ fn transitive_package_only_prereleases_in_range_opt_in() -> Result<()> { /// A transitive dependency has both a prerelease and a stable selector, but can /// only be satisfied by a prerelease /// -/// sc7ad0310 +/// ```text +/// f8aeea37 /// ├── environment /// │ └── python3.7 /// ├── root @@ -1632,20 +2144,21 @@ fn transitive_package_only_prereleases_in_range_opt_in() -> Result<()> { /// │ └── satisfied by c-2.0.0b1 /// ├── b /// │ └── b-1.0.0 -/// │ └── requires c>=1.0.0,<=3.0.0 +/// │ └── requires c<=3.0.0,>=1.0.0 /// │ └── satisfied by c-1.0.0 /// └── c /// ├── c-1.0.0 /// └── c-2.0.0b1 +/// ``` #[test] fn transitive_prerelease_and_stable_dependency() -> Result<()> { let temp_dir = assert_fs::TempDir::new()?; let cache_dir = assert_fs::TempDir::new()?; let venv = create_venv(&temp_dir, &cache_dir, "python3.7"); - // In addition to the standard filters, remove the scenario prefix + // In addition to the standard filters, remove the scenario version let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"sc7ad0310-", "")); + filters.push((r"-f8aeea37", "")); insta::with_settings!({ filters => filters @@ -1653,8 +2166,8 @@ fn transitive_prerelease_and_stable_dependency() -> Result<()> { assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) .arg("pip") .arg("install") - .arg("sc7ad0310-a") - .arg("sc7ad0310-b") + .arg("a-f8aeea37") + .arg("b-f8aeea37") .arg("--extra-index-url") .arg("https://test.pypi.org/simple") .arg("--cache-dir") @@ -1679,8 +2192,8 @@ fn transitive_prerelease_and_stable_dependency() -> Result<()> { }); // Since the user did not explicitly opt-in to a prerelease, it cannot be selected. - assert_not_installed(&venv, "sc7ad0310_a", &temp_dir); - assert_not_installed(&venv, "sc7ad0310_b", &temp_dir); + assert_not_installed(&venv, "a_f8aeea37", &temp_dir); + assert_not_installed(&venv, "b_f8aeea37", &temp_dir); Ok(()) } @@ -1691,7 +2204,8 @@ fn transitive_prerelease_and_stable_dependency() -> Result<()> { /// only be satisfied by a prerelease. The user includes an opt-in to prereleases of /// the transitive dependency. /// -/// sa05f7cb8 +/// ```text +/// 184fc65f /// ├── environment /// │ └── python3.7 /// ├── root @@ -1708,20 +2222,21 @@ fn transitive_prerelease_and_stable_dependency() -> Result<()> { /// │ └── satisfied by c-2.0.0b1 /// ├── b /// │ └── b-1.0.0 -/// │ └── requires c>=1.0.0,<=3.0.0 +/// │ └── requires c<=3.0.0,>=1.0.0 /// │ └── satisfied by c-1.0.0 /// └── c /// ├── c-1.0.0 /// └── c-2.0.0b1 +/// ``` #[test] fn transitive_prerelease_and_stable_dependency_opt_in() -> Result<()> { let temp_dir = assert_fs::TempDir::new()?; let cache_dir = assert_fs::TempDir::new()?; let venv = create_venv(&temp_dir, &cache_dir, "python3.7"); - // In addition to the standard filters, remove the scenario prefix + // In addition to the standard filters, remove the scenario version let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"sa05f7cb8-", "")); + filters.push((r"-184fc65f", "")); insta::with_settings!({ filters => filters @@ -1729,9 +2244,9 @@ fn transitive_prerelease_and_stable_dependency_opt_in() -> Result<()> { assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) .arg("pip") .arg("install") - .arg("sa05f7cb8-a") - .arg("sa05f7cb8-b") - .arg("sa05f7cb8-c>=0.0.0a1") + .arg("a-184fc65f") + .arg("b-184fc65f") + .arg("c-184fc65f>=0.0.0a1") .arg("--extra-index-url") .arg("https://test.pypi.org/simple") .arg("--cache-dir") @@ -1754,9 +2269,9 @@ fn transitive_prerelease_and_stable_dependency_opt_in() -> Result<()> { }); // Since the user explicitly opted-in to a prerelease for `c`, it can be installed. - assert_installed(&venv, "sa05f7cb8_a", "1.0.0", &temp_dir); - assert_installed(&venv, "sa05f7cb8_b", "1.0.0", &temp_dir); - assert_installed(&venv, "sa05f7cb8_c", "2.0.0b1", &temp_dir); + assert_installed(&venv, "a_184fc65f", "1.0.0", &temp_dir); + assert_installed(&venv, "b_184fc65f", "1.0.0", &temp_dir); + assert_installed(&venv, "c_184fc65f", "2.0.0b1", &temp_dir); Ok(()) } @@ -1766,7 +2281,8 @@ fn transitive_prerelease_and_stable_dependency_opt_in() -> Result<()> { /// A transitive dependency has both a prerelease and a stable selector, but can /// only be satisfied by a prerelease. There are many prerelease versions. /// -/// s02ae765c +/// ```text +/// 7017673e /// ├── environment /// │ └── python3.7 /// ├── root @@ -1788,7 +2304,7 @@ fn transitive_prerelease_and_stable_dependency_opt_in() -> Result<()> { /// │ └── satisfied by c-2.0.0b9 /// ├── b /// │ └── b-1.0.0 -/// │ └── requires c>=1.0.0,<=3.0.0 +/// │ └── requires c<=3.0.0,>=1.0.0 /// │ └── satisfied by c-1.0.0 /// └── c /// ├── c-1.0.0 @@ -1810,15 +2326,16 @@ fn transitive_prerelease_and_stable_dependency_opt_in() -> Result<()> { /// ├── c-2.0.0b7 /// ├── c-2.0.0b8 /// └── c-2.0.0b9 +/// ``` #[test] fn transitive_prerelease_and_stable_dependency_many_versions() -> Result<()> { let temp_dir = assert_fs::TempDir::new()?; let cache_dir = assert_fs::TempDir::new()?; let venv = create_venv(&temp_dir, &cache_dir, "python3.7"); - // In addition to the standard filters, remove the scenario prefix + // In addition to the standard filters, remove the scenario version let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"s02ae765c-", "")); + filters.push((r"-7017673e", "")); insta::with_settings!({ filters => filters @@ -1826,8 +2343,8 @@ fn transitive_prerelease_and_stable_dependency_many_versions() -> Result<()> { assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) .arg("pip") .arg("install") - .arg("s02ae765c-a") - .arg("s02ae765c-b") + .arg("a-7017673e") + .arg("b-7017673e") .arg("--extra-index-url") .arg("https://test.pypi.org/simple") .arg("--cache-dir") @@ -1857,8 +2374,8 @@ fn transitive_prerelease_and_stable_dependency_many_versions() -> Result<()> { }); // Since the user did not explicitly opt-in to a prerelease, it cannot be selected. - assert_not_installed(&venv, "s02ae765c_a", &temp_dir); - assert_not_installed(&venv, "s02ae765c_b", &temp_dir); + assert_not_installed(&venv, "a_7017673e", &temp_dir); + assert_not_installed(&venv, "b_7017673e", &temp_dir); Ok(()) } @@ -1869,7 +2386,8 @@ fn transitive_prerelease_and_stable_dependency_many_versions() -> Result<()> { /// only be satisfied by a prerelease. There are many prerelease versions and some /// are excluded. /// -/// sef9ce80f +/// ```text +/// aaee5052 /// ├── environment /// │ └── python3.7 /// ├── root @@ -1879,11 +2397,11 @@ fn transitive_prerelease_and_stable_dependency_many_versions() -> Result<()> { /// │ └── satisfied by b-1.0.0 /// ├── a /// │ └── a-1.0.0 -/// │ └── requires c>1.0.0,!=2.0.0a5,!=2.0.0a6,!=2.0.0a7,!=2.0.0b1,<2.0.0b5 +/// │ └── requires c!=2.0.0a5,!=2.0.0a6,!=2.0.0a7,!=2.0.0b1,<2.0.0b5,>1.0.0 /// │ └── unsatisfied: no matching version /// ├── b /// │ └── b-1.0.0 -/// │ └── requires c>=1.0.0,<=3.0.0 +/// │ └── requires c<=3.0.0,>=1.0.0 /// │ └── satisfied by c-1.0.0 /// └── c /// ├── c-1.0.0 @@ -1905,15 +2423,16 @@ fn transitive_prerelease_and_stable_dependency_many_versions() -> Result<()> { /// ├── c-2.0.0b7 /// ├── c-2.0.0b8 /// └── c-2.0.0b9 +/// ``` #[test] fn transitive_prerelease_and_stable_dependency_many_versions_holes() -> Result<()> { let temp_dir = assert_fs::TempDir::new()?; let cache_dir = assert_fs::TempDir::new()?; let venv = create_venv(&temp_dir, &cache_dir, "python3.7"); - // In addition to the standard filters, remove the scenario prefix + // In addition to the standard filters, remove the scenario version let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"sef9ce80f-", "")); + filters.push((r"-aaee5052", "")); insta::with_settings!({ filters => filters @@ -1921,8 +2440,8 @@ fn transitive_prerelease_and_stable_dependency_many_versions_holes() -> Result<( assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) .arg("pip") .arg("install") - .arg("sef9ce80f-a") - .arg("sef9ce80f-b") + .arg("a-aaee5052") + .arg("b-aaee5052") .arg("--extra-index-url") .arg("https://test.pypi.org/simple") .arg("--cache-dir") @@ -1959,8 +2478,8 @@ fn transitive_prerelease_and_stable_dependency_many_versions_holes() -> Result<( }); // Since the user did not explicitly opt-in to a prerelease, it cannot be selected. - assert_not_installed(&venv, "sef9ce80f_a", &temp_dir); - assert_not_installed(&venv, "sef9ce80f_b", &temp_dir); + assert_not_installed(&venv, "a_aaee5052", &temp_dir); + assert_not_installed(&venv, "b_aaee5052", &temp_dir); Ok(()) } @@ -1969,7 +2488,8 @@ fn transitive_prerelease_and_stable_dependency_many_versions_holes() -> Result<( /// /// The user requires a package which requires a Python version that does not exist /// -/// s0825b69c +/// ```text +/// 0825b69c /// ├── environment /// │ └── python3.7 /// ├── root @@ -1978,15 +2498,16 @@ fn transitive_prerelease_and_stable_dependency_many_versions_holes() -> Result<( /// └── a /// └── a-1.0.0 /// └── requires python>=4.0 (incompatible with environment) +/// ``` #[test] fn requires_python_version_does_not_exist() -> Result<()> { let temp_dir = assert_fs::TempDir::new()?; let cache_dir = assert_fs::TempDir::new()?; let venv = create_venv(&temp_dir, &cache_dir, "python3.7"); - // In addition to the standard filters, remove the scenario prefix + // In addition to the standard filters, remove the scenario version let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"s0825b69c-", "")); + filters.push((r"-0825b69c", "")); insta::with_settings!({ filters => filters @@ -1994,7 +2515,7 @@ fn requires_python_version_does_not_exist() -> Result<()> { assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) .arg("pip") .arg("install") - .arg("s0825b69c-a==1.0.0") + .arg("a-0825b69c==1.0.0") .arg("--extra-index-url") .arg("https://test.pypi.org/simple") .arg("--cache-dir") @@ -2013,7 +2534,7 @@ fn requires_python_version_does_not_exist() -> Result<()> { "###); }); - assert_not_installed(&venv, "s0825b69c_a", &temp_dir); + assert_not_installed(&venv, "a_0825b69c", &temp_dir); Ok(()) } @@ -2023,7 +2544,8 @@ fn requires_python_version_does_not_exist() -> Result<()> { /// The user requires a package which requires a Python version less than the /// current version /// -/// sf9296b84 +/// ```text +/// f9296b84 /// ├── environment /// │ └── python3.9 /// ├── root @@ -2032,15 +2554,16 @@ fn requires_python_version_does_not_exist() -> Result<()> { /// └── a /// └── a-1.0.0 /// └── requires python<=3.8 (incompatible with environment) +/// ``` #[test] fn requires_python_version_less_than_current() -> Result<()> { let temp_dir = assert_fs::TempDir::new()?; let cache_dir = assert_fs::TempDir::new()?; let venv = create_venv(&temp_dir, &cache_dir, "python3.9"); - // In addition to the standard filters, remove the scenario prefix + // In addition to the standard filters, remove the scenario version let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"sf9296b84-", "")); + filters.push((r"-f9296b84", "")); insta::with_settings!({ filters => filters @@ -2048,7 +2571,7 @@ fn requires_python_version_less_than_current() -> Result<()> { assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) .arg("pip") .arg("install") - .arg("sf9296b84-a==1.0.0") + .arg("a-f9296b84==1.0.0") .arg("--extra-index-url") .arg("https://test.pypi.org/simple") .arg("--cache-dir") @@ -2067,7 +2590,7 @@ fn requires_python_version_less_than_current() -> Result<()> { "###); }); - assert_not_installed(&venv, "sf9296b84_a", &temp_dir); + assert_not_installed(&venv, "a_f9296b84", &temp_dir); Ok(()) } @@ -2077,7 +2600,8 @@ fn requires_python_version_less_than_current() -> Result<()> { /// The user requires a package which requires a Python version greater than the /// current version /// -/// sa11d5394 +/// ```text +/// a11d5394 /// ├── environment /// │ └── python3.9 /// ├── root @@ -2086,15 +2610,16 @@ fn requires_python_version_less_than_current() -> Result<()> { /// └── a /// └── a-1.0.0 /// └── requires python>=3.10 (incompatible with environment) +/// ``` #[test] fn requires_python_version_greater_than_current() -> Result<()> { let temp_dir = assert_fs::TempDir::new()?; let cache_dir = assert_fs::TempDir::new()?; let venv = create_venv(&temp_dir, &cache_dir, "python3.9"); - // In addition to the standard filters, remove the scenario prefix + // In addition to the standard filters, remove the scenario version let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"sa11d5394-", "")); + filters.push((r"-a11d5394", "")); insta::with_settings!({ filters => filters @@ -2102,7 +2627,7 @@ fn requires_python_version_greater_than_current() -> Result<()> { assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) .arg("pip") .arg("install") - .arg("sa11d5394-a==1.0.0") + .arg("a-a11d5394==1.0.0") .arg("--extra-index-url") .arg("https://test.pypi.org/simple") .arg("--cache-dir") @@ -2121,7 +2646,7 @@ fn requires_python_version_greater_than_current() -> Result<()> { "###); }); - assert_not_installed(&venv, "sa11d5394_a", &temp_dir); + assert_not_installed(&venv, "a_a11d5394", &temp_dir); Ok(()) } @@ -2131,7 +2656,8 @@ fn requires_python_version_greater_than_current() -> Result<()> { /// The user requires a package which has many versions which all require a Python /// version greater than the current version /// -/// s02dc550c +/// ```text +/// 02dc550c /// ├── environment /// │ └── python3.9 /// ├── root @@ -2162,15 +2688,16 @@ fn requires_python_version_greater_than_current() -> Result<()> { /// │ └── requires python>=3.11 (incompatible with environment) /// └── a-3.5.0 /// └── requires python>=3.11 (incompatible with environment) +/// ``` #[test] fn requires_python_version_greater_than_current_many() -> Result<()> { let temp_dir = assert_fs::TempDir::new()?; let cache_dir = assert_fs::TempDir::new()?; let venv = create_venv(&temp_dir, &cache_dir, "python3.9"); - // In addition to the standard filters, remove the scenario prefix + // In addition to the standard filters, remove the scenario version let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"s02dc550c-", "")); + filters.push((r"-02dc550c", "")); insta::with_settings!({ filters => filters @@ -2178,7 +2705,7 @@ fn requires_python_version_greater_than_current_many() -> Result<()> { assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) .arg("pip") .arg("install") - .arg("s02dc550c-a==1.0.0") + .arg("a-02dc550c==1.0.0") .arg("--extra-index-url") .arg("https://test.pypi.org/simple") .arg("--cache-dir") @@ -2196,7 +2723,7 @@ fn requires_python_version_greater_than_current_many() -> Result<()> { "###); }); - assert_not_installed(&venv, "s02dc550c_a", &temp_dir); + assert_not_installed(&venv, "a_02dc550c", &temp_dir); Ok(()) } @@ -2206,7 +2733,8 @@ fn requires_python_version_greater_than_current_many() -> Result<()> { /// The user requires a package where recent versions require a Python version /// greater than the current version, but an older version is compatible. /// -/// sef060cef +/// ```text +/// ef060cef /// ├── environment /// │ └── python3.9 /// ├── root @@ -2223,15 +2751,16 @@ fn requires_python_version_greater_than_current_many() -> Result<()> { /// │ └── requires python>=3.11 (incompatible with environment) /// └── a-4.0.0 /// └── requires python>=3.12 (incompatible with environment) +/// ``` #[test] fn requires_python_version_greater_than_current_backtrack() -> Result<()> { let temp_dir = assert_fs::TempDir::new()?; let cache_dir = assert_fs::TempDir::new()?; let venv = create_venv(&temp_dir, &cache_dir, "python3.9"); - // In addition to the standard filters, remove the scenario prefix + // In addition to the standard filters, remove the scenario version let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"sef060cef-", "")); + filters.push((r"-ef060cef", "")); insta::with_settings!({ filters => filters @@ -2239,7 +2768,7 @@ fn requires_python_version_greater_than_current_backtrack() -> Result<()> { assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) .arg("pip") .arg("install") - .arg("sef060cef-a") + .arg("a-ef060cef") .arg("--extra-index-url") .arg("https://test.pypi.org/simple") .arg("--cache-dir") @@ -2259,7 +2788,7 @@ fn requires_python_version_greater_than_current_backtrack() -> Result<()> { "###); }); - assert_installed(&venv, "sef060cef_a", "1.0.0", &temp_dir); + assert_installed(&venv, "a_ef060cef", "1.0.0", &temp_dir); Ok(()) } @@ -2269,7 +2798,8 @@ fn requires_python_version_greater_than_current_backtrack() -> Result<()> { /// The user requires a package where recent versions require a Python version /// greater than the current version, but an excluded older version is compatible. /// -/// s1bde0c18 +/// ```text +/// 1bde0c18 /// ├── environment /// │ └── python3.9 /// ├── root @@ -2285,15 +2815,16 @@ fn requires_python_version_greater_than_current_backtrack() -> Result<()> { /// │ └── requires python>=3.11 (incompatible with environment) /// └── a-4.0.0 /// └── requires python>=3.12 (incompatible with environment) +/// ``` #[test] fn requires_python_version_greater_than_current_excluded() -> Result<()> { let temp_dir = assert_fs::TempDir::new()?; let cache_dir = assert_fs::TempDir::new()?; let venv = create_venv(&temp_dir, &cache_dir, "python3.9"); - // In addition to the standard filters, remove the scenario prefix + // In addition to the standard filters, remove the scenario version let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"s1bde0c18-", "")); + filters.push((r"-1bde0c18", "")); insta::with_settings!({ filters => filters @@ -2301,7 +2832,7 @@ fn requires_python_version_greater_than_current_excluded() -> Result<()> { assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) .arg("pip") .arg("install") - .arg("s1bde0c18-a>=2.0.0") + .arg("a-1bde0c18>=2.0.0") .arg("--extra-index-url") .arg("https://test.pypi.org/simple") .arg("--cache-dir") @@ -2336,7 +2867,7 @@ fn requires_python_version_greater_than_current_excluded() -> Result<()> { "###); }); - assert_not_installed(&venv, "s1bde0c18_a", &temp_dir); + assert_not_installed(&venv, "a_1bde0c18", &temp_dir); Ok(()) } @@ -2345,7 +2876,8 @@ fn requires_python_version_greater_than_current_excluded() -> Result<()> { /// /// A wheel for a specific platform is available alongside the default. /// -/// s74e4a459 +/// ```text +/// 74e4a459 /// ├── environment /// │ └── python3.7 /// ├── root @@ -2353,15 +2885,16 @@ fn requires_python_version_greater_than_current_excluded() -> Result<()> { /// │ └── satisfied by a-1.0.0 /// └── a /// └── a-1.0.0 +/// ``` #[test] fn specific_tag_and_default() -> Result<()> { let temp_dir = assert_fs::TempDir::new()?; let cache_dir = assert_fs::TempDir::new()?; let venv = create_venv(&temp_dir, &cache_dir, "python3.7"); - // In addition to the standard filters, remove the scenario prefix + // In addition to the standard filters, remove the scenario version let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"s74e4a459-", "")); + filters.push((r"-74e4a459", "")); insta::with_settings!({ filters => filters @@ -2369,7 +2902,7 @@ fn specific_tag_and_default() -> Result<()> { assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) .arg("pip") .arg("install") - .arg("s74e4a459-a") + .arg("a-74e4a459") .arg("--extra-index-url") .arg("https://test.pypi.org/simple") .arg("--cache-dir") @@ -2396,7 +2929,8 @@ fn specific_tag_and_default() -> Result<()> { /// /// No source distributions are available, only wheels. /// -/// s4f019491 +/// ```text +/// 4f019491 /// ├── environment /// │ └── python3.7 /// ├── root @@ -2404,15 +2938,16 @@ fn specific_tag_and_default() -> Result<()> { /// │ └── satisfied by a-1.0.0 /// └── a /// └── a-1.0.0 +/// ``` #[test] fn only_wheels() -> Result<()> { let temp_dir = assert_fs::TempDir::new()?; let cache_dir = assert_fs::TempDir::new()?; let venv = create_venv(&temp_dir, &cache_dir, "python3.7"); - // In addition to the standard filters, remove the scenario prefix + // In addition to the standard filters, remove the scenario version let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"s4f019491-", "")); + filters.push((r"-4f019491", "")); insta::with_settings!({ filters => filters @@ -2420,7 +2955,7 @@ fn only_wheels() -> Result<()> { assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) .arg("pip") .arg("install") - .arg("s4f019491-a") + .arg("a-4f019491") .arg("--extra-index-url") .arg("https://test.pypi.org/simple") .arg("--cache-dir") @@ -2447,7 +2982,8 @@ fn only_wheels() -> Result<()> { /// /// No wheels are available, only source distributions. /// -/// s614d801c +/// ```text +/// 614d801c /// ├── environment /// │ └── python3.7 /// ├── root @@ -2455,15 +2991,16 @@ fn only_wheels() -> Result<()> { /// │ └── satisfied by a-1.0.0 /// └── a /// └── a-1.0.0 +/// ``` #[test] fn no_wheels() -> Result<()> { let temp_dir = assert_fs::TempDir::new()?; let cache_dir = assert_fs::TempDir::new()?; let venv = create_venv(&temp_dir, &cache_dir, "python3.7"); - // In addition to the standard filters, remove the scenario prefix + // In addition to the standard filters, remove the scenario version let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"s614d801c-", "")); + filters.push((r"-614d801c", "")); insta::with_settings!({ filters => filters @@ -2471,7 +3008,7 @@ fn no_wheels() -> Result<()> { assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) .arg("pip") .arg("install") - .arg("s614d801c-a") + .arg("a-614d801c") .arg("--extra-index-url") .arg("https://test.pypi.org/simple") .arg("--cache-dir") @@ -2498,7 +3035,8 @@ fn no_wheels() -> Result<()> { /// /// No wheels with valid tags are available, just source distributions. /// -/// s737bbfd4 +/// ```text +/// 737bbfd4 /// ├── environment /// │ └── python3.7 /// ├── root @@ -2506,15 +3044,16 @@ fn no_wheels() -> Result<()> { /// │ └── satisfied by a-1.0.0 /// └── a /// └── a-1.0.0 +/// ``` #[test] fn no_wheels_with_matching_platform() -> Result<()> { let temp_dir = assert_fs::TempDir::new()?; let cache_dir = assert_fs::TempDir::new()?; let venv = create_venv(&temp_dir, &cache_dir, "python3.7"); - // In addition to the standard filters, remove the scenario prefix + // In addition to the standard filters, remove the scenario version let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"s737bbfd4-", "")); + filters.push((r"-737bbfd4", "")); insta::with_settings!({ filters => filters @@ -2522,7 +3061,7 @@ fn no_wheels_with_matching_platform() -> Result<()> { assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) .arg("pip") .arg("install") - .arg("s737bbfd4-a") + .arg("a-737bbfd4") .arg("--extra-index-url") .arg("https://test.pypi.org/simple") .arg("--cache-dir") diff --git a/scripts/scenarios/template.mustache b/scripts/scenarios/template.mustache index f9a836a38..c2febc62e 100644 --- a/scripts/scenarios/template.mustache +++ b/scripts/scenarios/template.mustache @@ -55,19 +55,21 @@ fn assert_not_installed(venv: &Path, package: &'static str, temp_dir: &Path) { /// {{.}} {{/description_lines}} /// -/// {{prefix}} +/// ```text +/// {{version}} {{#tree}} /// {{.}} {{/tree}} +/// ``` #[test] -fn {{normalized_name}}() -> Result<()> { +fn {{module_name}}() -> Result<()> { let temp_dir = assert_fs::TempDir::new()?; let cache_dir = assert_fs::TempDir::new()?; let venv = create_venv(&temp_dir, &cache_dir, "python{{environment.python}}"); - // In addition to the standard filters, remove the scenario prefix + // In addition to the standard filters, remove the scenario version let mut filters = INSTA_FILTERS.to_vec(); - filters.push((r"{{prefix}}-", "")); + filters.push((r"-{{version}}", "")); insta::with_settings!({ filters => filters @@ -76,7 +78,7 @@ fn {{normalized_name}}() -> Result<()> { .arg("pip") .arg("install") {{#root.requires}} - .arg("{{prefix}}-{{.}}") + .arg("{{requirement}}") {{/root.requires}} {{#environment.prereleases}} .arg("--prerelease=allow") @@ -95,19 +97,19 @@ fn {{normalized_name}}() -> Result<()> { // {{.}} {{/expected.explanation_lines}} {{#expected.satisfiable}} - {{#expected.packages_list}} + {{#expected.packages}} assert_installed( &venv, - "{{prefix_module}}_{{package_module}}", + "{{module_name}}", "{{version}}", &temp_dir ); - {{/expected.packages_list}} + {{/expected.packages}} {{/expected.satisfiable}} {{^expected.satisfiable}} - {{#root.requires_packages}} - assert_not_installed(&venv, "{{prefix_module}}_{{package_module}}", &temp_dir); - {{/root.requires_packages}} + {{#root.requires}} + assert_not_installed(&venv, "{{module_name}}", &temp_dir); + {{/root.requires}} {{/expected.satisfiable}} Ok(()) diff --git a/scripts/scenarios/update.py b/scripts/scenarios/update.py index 51be82cd2..36379ad03 100755 --- a/scripts/scenarios/update.py +++ b/scripts/scenarios/update.py @@ -42,11 +42,10 @@ import shutil import subprocess import sys import textwrap -import packaging.requirements from pathlib import Path -PACKSE_COMMIT = "a9d2f659117693b89cba8a487200fd01444468af" +PACKSE_COMMIT = "b6cb1f6310a40937dc68a59c82460fea58957b70" TOOL_ROOT = Path(__file__).parent TEMPLATE = TOOL_ROOT / "template.mustache" PACKSE = TOOL_ROOT / "packse-scenarios" @@ -147,10 +146,6 @@ data["generated_from"] = f"https://github.com/zanieb/packse/tree/{commit}/scenar data["generated_with"] = " ".join(sys.argv) -# Add normalized names for tests -for scenario in data["scenarios"]: - scenario["normalized_name"] = scenario["name"].replace("-", "_") - # Drop the example scenario for index, scenario in enumerate(data["scenarios"]): if scenario["name"] == "example": @@ -170,39 +165,12 @@ for scenario in data["scenarios"]: else [] ) -# Convert the expected packages into a list for rendering -for scenario in data["scenarios"]: - expected = scenario["expected"] - expected["packages_list"] = [] - for key, value in expected["packages"].items(): - expected["packages_list"].append( - { - "package": key, - "version": value, - # Include a converted version of the package name to its Python module - "package_module": key.replace("-", "_"), - } - ) - - -# Convert the required packages into a list without versions -for scenario in data["scenarios"]: - requires_packages = scenario["root"]["requires_packages"] = [] - for requirement in scenario["root"]["requires"]: - package = packaging.requirements.Requirement(requirement).name - requires_packages.append( - {"package": package, "package_module": package.replace("-", "_")} - ) - - -# Include the Python module name of the prefix -for scenario in data["scenarios"]: - scenario["prefix_module"] = scenario["prefix"].replace("-", "_") - # Render the template print("Rendering template...", file=sys.stderr) -output = chevron_blue.render(template=TEMPLATE.read_text(), data=data, no_escape=True) +output = chevron_blue.render( + template=TEMPLATE.read_text(), data=data, no_escape=True, warn=True +) # Update the test file print(f"Updating test file at `{TARGET.relative_to(PROJECT_ROOT)}`...", file=sys.stderr)