mirror of https://github.com/astral-sh/uv
3120 lines
105 KiB
Rust
3120 lines
105 KiB
Rust
//! DO NOT EDIT
|
||
//!
|
||
//! Generated with ./scripts/scenarios/update.py
|
||
//! Scenarios from <https://github.com/zanieb/packse/tree/b6cb1f6310a40937dc68a59c82460fea58957b70/scenarios>
|
||
//!
|
||
#![cfg(all(feature = "python", feature = "pypi"))]
|
||
|
||
use std::path::Path;
|
||
use std::process::Command;
|
||
|
||
use anyhow::Result;
|
||
use assert_cmd::assert::Assert;
|
||
use assert_cmd::prelude::*;
|
||
use insta_cmd::_macro_support::insta;
|
||
use insta_cmd::{assert_cmd_snapshot, get_cargo_bin};
|
||
|
||
use common::{create_venv, BIN_NAME, INSTA_FILTERS};
|
||
|
||
mod common;
|
||
|
||
fn assert_command(venv: &Path, command: &str, temp_dir: &Path) -> Assert {
|
||
Command::new(venv.join("bin").join("python"))
|
||
.arg("-c")
|
||
.arg(command)
|
||
.current_dir(temp_dir)
|
||
.assert()
|
||
}
|
||
|
||
fn assert_installed(venv: &Path, package: &'static str, version: &'static str, temp_dir: &Path) {
|
||
assert_command(
|
||
venv,
|
||
format!("import {package} as package; print(package.__version__, end='')").as_str(),
|
||
temp_dir,
|
||
)
|
||
.success()
|
||
.stdout(version);
|
||
}
|
||
|
||
fn assert_not_installed(venv: &Path, package: &'static str, temp_dir: &Path) {
|
||
assert_command(venv, format!("import {package}").as_str(), temp_dir).failure();
|
||
}
|
||
|
||
/// requires-package-does-not-exist
|
||
///
|
||
/// The user requires any version of package `a` which does not exist.
|
||
///
|
||
/// ```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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"-57cd4136", ""));
|
||
|
||
insta::with_settings!({
|
||
filters => filters
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip")
|
||
.arg("install")
|
||
.arg("a-57cd4136")
|
||
.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: 2
|
||
----- stdout -----
|
||
|
||
----- stderr -----
|
||
error: Package `a` was not found in the registry.
|
||
"###);
|
||
});
|
||
|
||
assert_not_installed(&venv, "a_57cd4136", &temp_dir);
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// requires-exact-version-does-not-exist
|
||
///
|
||
/// The user requires an exact version of package `a` but only other versions exist
|
||
///
|
||
/// ```text
|
||
/// eaa03067
|
||
/// ├── environment
|
||
/// │ └── python3.7
|
||
/// ├── root
|
||
/// │ └── requires a==2.0.0
|
||
/// │ └── 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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-eaa03067", "albatross"));
|
||
filters.push((r"-eaa03067", ""));
|
||
|
||
insta::with_settings!({
|
||
filters => filters
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip")
|
||
.arg("install")
|
||
.arg("a-eaa03067==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 there is no version of albatross==2.0.0 and you require albatross==2.0.0, we can conclude that the requirements are unsatisfiable.
|
||
"###);
|
||
});
|
||
|
||
assert_not_installed(&venv, "a_eaa03067", &temp_dir);
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// requires-greater-version-does-not-exist
|
||
///
|
||
/// The user requires a version of `a` greater than `1.0.0` but only smaller or
|
||
/// equal versions exist
|
||
///
|
||
/// ```text
|
||
/// 6e8e01df
|
||
/// ├── environment
|
||
/// │ └── python3.7
|
||
/// ├── root
|
||
/// │ └── requires a>1.0.0
|
||
/// │ └── unsatisfied: no matching version
|
||
/// └── 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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-6e8e01df", "albatross"));
|
||
filters.push((r"-6e8e01df", ""));
|
||
|
||
insta::with_settings!({
|
||
filters => filters
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip")
|
||
.arg("install")
|
||
.arg("a-6e8e01df>1.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 only albatross<=1.0.0 is available and you require albatross>1.0.0, we can conclude that the requirements are unsatisfiable.
|
||
"###);
|
||
});
|
||
|
||
assert_not_installed(&venv, "a_6e8e01df", &temp_dir);
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// requires-less-version-does-not-exist
|
||
///
|
||
/// The user requires a version of `a` less than `1.0.0` but only larger versions
|
||
/// exist
|
||
///
|
||
/// ```text
|
||
/// e45cec3c
|
||
/// ├── environment
|
||
/// │ └── python3.7
|
||
/// ├── root
|
||
/// │ └── requires a<2.0.0
|
||
/// │ └── unsatisfied: no matching version
|
||
/// └── a
|
||
/// ├── 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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-e45cec3c", "albatross"));
|
||
filters.push((r"-e45cec3c", ""));
|
||
|
||
insta::with_settings!({
|
||
filters => filters
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip")
|
||
.arg("install")
|
||
.arg("a-e45cec3c<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 only albatross>=2.0.0 is available and you require albatross<2.0.0, we can conclude that the requirements are unsatisfiable.
|
||
"###);
|
||
});
|
||
|
||
assert_not_installed(&venv, "a_e45cec3c", &temp_dir);
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// transitive-requires-package-does-not-exist
|
||
///
|
||
/// The user requires package `a` but `a` requires package `b` which does not exist
|
||
///
|
||
/// ```text
|
||
/// aca2796a
|
||
/// ├── environment
|
||
/// │ └── python3.7
|
||
/// ├── root
|
||
/// │ └── requires a
|
||
/// │ └── satisfied by a-1.0.0
|
||
/// └── a
|
||
/// └── 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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-aca2796a", "albatross"));
|
||
filters.push((r"-aca2796a", ""));
|
||
|
||
insta::with_settings!({
|
||
filters => filters
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip")
|
||
.arg("install")
|
||
.arg("a-aca2796a")
|
||
.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: 2
|
||
----- stdout -----
|
||
|
||
----- stderr -----
|
||
error: Package `b` was not found in the registry.
|
||
"###);
|
||
});
|
||
|
||
assert_not_installed(&venv, "a_aca2796a", &temp_dir);
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// excluded-only-version
|
||
///
|
||
/// Only one version of the requested package is available, but the user has banned
|
||
/// that version.
|
||
///
|
||
/// ```text
|
||
/// 7a9ed79c
|
||
/// ├── environment
|
||
/// │ └── python3.7
|
||
/// ├── root
|
||
/// │ └── requires a!=1.0.0
|
||
/// │ └── 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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-7a9ed79c", "albatross"));
|
||
filters.push((r"-7a9ed79c", ""));
|
||
|
||
insta::with_settings!({
|
||
filters => filters
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip")
|
||
.arg("install")
|
||
.arg("a-7a9ed79c!=1.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 only albatross==1.0.0 is available and you require one of:
|
||
albatross<1.0.0
|
||
albatross>1.0.0
|
||
we can conclude that the requirements are unsatisfiable.
|
||
"###);
|
||
});
|
||
|
||
// Only `a==1.0.0` is available but the user excluded it.
|
||
assert_not_installed(&venv, "a_7a9ed79c", &temp_dir);
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// excluded-only-compatible-version
|
||
///
|
||
/// Only one version of the requested package `a` is compatible, but the user has
|
||
/// banned that version.
|
||
///
|
||
/// ```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<3.0.0,>=2.0.0
|
||
/// │ └── satisfied by b-2.0.0
|
||
/// ├── a
|
||
/// │ ├── a-1.0.0
|
||
/// │ │ └── requires b==1.0.0
|
||
/// │ │ └── satisfied by b-1.0.0
|
||
/// │ ├── a-2.0.0
|
||
/// │ │ └── requires b==2.0.0
|
||
/// │ │ └── satisfied by b-2.0.0
|
||
/// │ └── a-3.0.0
|
||
/// │ └── requires b==3.0.0
|
||
/// │ └── satisfied by b-3.0.0
|
||
/// └── b
|
||
/// ├── 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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-b6b89642", "albatross"));
|
||
filters.push((r"b-b6b89642", "bluebird"));
|
||
filters.push((r"-b6b89642", ""));
|
||
|
||
insta::with_settings!({
|
||
filters => filters
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip")
|
||
.arg("install")
|
||
.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")
|
||
.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 albatross that satisfy any of:
|
||
albatross<1.0.0
|
||
albatross>1.0.0,<2.0.0
|
||
albatross>2.0.0,<3.0.0
|
||
albatross>3.0.0
|
||
and albatross==1.0.0 depends on bluebird==1.0.0, we can conclude that albatross<2.0.0 depends on bluebird==1.0.0.
|
||
And because albatross==3.0.0 depends on bluebird==3.0.0 we can conclude that any of:
|
||
albatross<2.0.0
|
||
albatross>2.0.0
|
||
depends on one of:
|
||
bluebird<=1.0.0
|
||
bluebird>=3.0.0
|
||
|
||
And because you require one of:
|
||
albatross<2.0.0
|
||
albatross>2.0.0
|
||
and you require bluebird>=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, "a_b6b89642", &temp_dir);
|
||
assert_not_installed(&venv, "b_b6b89642", &temp_dir);
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// dependency-excludes-range-of-compatible-versions
|
||
///
|
||
/// There is a range of compatible versions for the requested package `a`, but
|
||
/// another dependency `c` excludes that range.
|
||
///
|
||
/// ```text
|
||
/// 1cd99bd0
|
||
/// ├── environment
|
||
/// │ └── python3.7
|
||
/// ├── root
|
||
/// │ ├── requires a
|
||
/// │ │ ├── satisfied by a-1.0.0
|
||
/// │ │ ├── satisfied by a-2.0.0
|
||
/// │ │ ├── satisfied by a-2.1.0
|
||
/// │ │ ├── satisfied by a-2.2.0
|
||
/// │ │ ├── satisfied by a-2.3.0
|
||
/// │ │ └── satisfied by a-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
|
||
/// │ └── satisfied by c-2.0.0
|
||
/// ├── a
|
||
/// │ ├── a-1.0.0
|
||
/// │ │ └── requires b==1.0.0
|
||
/// │ │ └── satisfied by b-1.0.0
|
||
/// │ ├── a-2.0.0
|
||
/// │ │ └── requires b==2.0.0
|
||
/// │ │ └── satisfied by b-2.0.0
|
||
/// │ ├── a-2.1.0
|
||
/// │ │ └── requires b==2.0.0
|
||
/// │ │ └── satisfied by b-2.0.0
|
||
/// │ ├── a-2.2.0
|
||
/// │ │ └── requires b==2.0.0
|
||
/// │ │ └── satisfied by b-2.0.0
|
||
/// │ ├── a-2.3.0
|
||
/// │ │ └── requires b==2.0.0
|
||
/// │ │ └── satisfied by b-2.0.0
|
||
/// │ └── a-3.0.0
|
||
/// │ └── requires b==3.0.0
|
||
/// │ └── satisfied by b-3.0.0
|
||
/// ├── b
|
||
/// │ ├── b-1.0.0
|
||
/// │ ├── b-2.0.0
|
||
/// │ └── b-3.0.0
|
||
/// └── c
|
||
/// ├── c-1.0.0
|
||
/// │ └── requires a<2.0.0
|
||
/// │ └── satisfied by a-1.0.0
|
||
/// └── 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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-1cd99bd0", "albatross"));
|
||
filters.push((r"b-1cd99bd0", "bluebird"));
|
||
filters.push((r"c-1cd99bd0", "crow"));
|
||
filters.push((r"-1cd99bd0", ""));
|
||
|
||
insta::with_settings!({
|
||
filters => filters
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip")
|
||
.arg("install")
|
||
.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")
|
||
.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 albatross that satisfy any of:
|
||
albatross<1.0.0
|
||
albatross>1.0.0,<2.0.0
|
||
albatross>3.0.0
|
||
and albatross==1.0.0 depends on bluebird==1.0.0, we can conclude that albatross<2.0.0 depends on bluebird==1.0.0. (1)
|
||
|
||
Because there are no versions of crow that satisfy any of:
|
||
crow<1.0.0
|
||
crow>1.0.0,<2.0.0
|
||
crow>2.0.0
|
||
and crow==1.0.0 depends on albatross<2.0.0, we can conclude that crow<2.0.0 depends on albatross<2.0.0.
|
||
And because crow==2.0.0 depends on albatross>=3.0.0 we can conclude that all versions of crow depend on one of:
|
||
albatross<2.0.0
|
||
albatross>=3.0.0
|
||
|
||
And because we know from (1) that albatross<2.0.0 depends on bluebird==1.0.0, we can conclude that albatross!=3.0.0, bluebird!=1.0.0, all versions of crow are incompatible.
|
||
And because albatross==3.0.0 depends on bluebird==3.0.0 we can conclude that all versions of crow depend on one of:
|
||
bluebird<=1.0.0
|
||
bluebird>=3.0.0
|
||
|
||
And because you require bluebird>=2.0.0,<3.0.0 and you require crow, we can conclude that the requirements are unsatisfiable.
|
||
"###);
|
||
});
|
||
|
||
// 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, "a_1cd99bd0", &temp_dir);
|
||
assert_not_installed(&venv, "b_1cd99bd0", &temp_dir);
|
||
assert_not_installed(&venv, "c_1cd99bd0", &temp_dir);
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// dependency-excludes-non-contiguous-range-of-compatible-versions
|
||
///
|
||
/// There is a non-contiguous range of compatible versions for the requested package
|
||
/// `a`, but another dependency `c` excludes the range. This is the same as
|
||
/// `dependency-excludes-range-of-compatible-versions` but some of the versions of
|
||
/// `a` are incompatible for another reason e.g. dependency on non-existant package
|
||
/// `d`.
|
||
///
|
||
/// ```text
|
||
/// 0fd25b39
|
||
/// ├── environment
|
||
/// │ └── python3.7
|
||
/// ├── root
|
||
/// │ ├── requires a
|
||
/// │ │ ├── satisfied by a-1.0.0
|
||
/// │ │ ├── satisfied by a-2.0.0
|
||
/// │ │ ├── satisfied by a-2.1.0
|
||
/// │ │ ├── satisfied by a-2.2.0
|
||
/// │ │ ├── satisfied by a-2.3.0
|
||
/// │ │ ├── satisfied by a-2.4.0
|
||
/// │ │ └── satisfied by a-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
|
||
/// │ └── satisfied by c-2.0.0
|
||
/// ├── a
|
||
/// │ ├── a-1.0.0
|
||
/// │ │ └── requires b==1.0.0
|
||
/// │ │ └── satisfied by b-1.0.0
|
||
/// │ ├── a-2.0.0
|
||
/// │ │ └── requires b==2.0.0
|
||
/// │ │ └── satisfied by b-2.0.0
|
||
/// │ ├── a-2.1.0
|
||
/// │ │ ├── requires b==2.0.0
|
||
/// │ │ │ └── satisfied by b-2.0.0
|
||
/// │ │ └── requires d
|
||
/// │ │ └── unsatisfied: no versions for package
|
||
/// │ ├── a-2.2.0
|
||
/// │ │ └── requires b==2.0.0
|
||
/// │ │ └── satisfied by b-2.0.0
|
||
/// │ ├── a-2.3.0
|
||
/// │ │ ├── requires b==2.0.0
|
||
/// │ │ │ └── satisfied by b-2.0.0
|
||
/// │ │ └── requires d
|
||
/// │ │ └── unsatisfied: no versions for package
|
||
/// │ ├── a-2.4.0
|
||
/// │ │ └── requires b==2.0.0
|
||
/// │ │ └── satisfied by b-2.0.0
|
||
/// │ └── a-3.0.0
|
||
/// │ └── requires b==3.0.0
|
||
/// │ └── satisfied by b-3.0.0
|
||
/// ├── b
|
||
/// │ ├── b-1.0.0
|
||
/// │ ├── b-2.0.0
|
||
/// │ └── b-3.0.0
|
||
/// └── c
|
||
/// ├── c-1.0.0
|
||
/// │ └── requires a<2.0.0
|
||
/// │ └── satisfied by a-1.0.0
|
||
/// └── 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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-0fd25b39", "albatross"));
|
||
filters.push((r"b-0fd25b39", "bluebird"));
|
||
filters.push((r"c-0fd25b39", "crow"));
|
||
filters.push((r"-0fd25b39", ""));
|
||
|
||
insta::with_settings!({
|
||
filters => filters
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip")
|
||
.arg("install")
|
||
.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")
|
||
.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 crow that satisfy any of:
|
||
crow<1.0.0
|
||
crow>1.0.0,<2.0.0
|
||
crow>2.0.0
|
||
and crow==1.0.0 depends on albatross<2.0.0, we can conclude that crow<2.0.0 depends on albatross<2.0.0. (1)
|
||
|
||
Because albatross==1.0.0 depends on bluebird==1.0.0 and there are no versions of albatross that satisfy any of:
|
||
albatross<1.0.0
|
||
albatross>1.0.0,<2.0.0
|
||
we can conclude that albatross<2.0.0 depends on bluebird==1.0.0.
|
||
And because we know from (1) that crow<2.0.0 depends on albatross<2.0.0, we can conclude that crow<2.0.0 depends on bluebird==1.0.0.
|
||
And because crow==2.0.0 depends on albatross>=3.0.0 we can conclude that all versions of crow, bluebird!=1.0.0, albatross<3.0.0 are incompatible. (2)
|
||
|
||
Because albatross==3.0.0 depends on bluebird==3.0.0 and only albatross<=3.0.0 is available, we can conclude that albatross>=3.0.0 depends on bluebird==3.0.0.
|
||
And because we know from (2) that all versions of crow, bluebird!=1.0.0, albatross<3.0.0 are incompatible, we can conclude that all versions of crow depend on one of:
|
||
bluebird<=1.0.0
|
||
bluebird>=3.0.0
|
||
|
||
And because you require crow and you require bluebird>=2.0.0,<3.0.0, we can conclude that the requirements are unsatisfiable.
|
||
"###);
|
||
});
|
||
|
||
// 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, "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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-76e5355c", "albatross"));
|
||
filters.push((r"b-76e5355c", "bluebird"));
|
||
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]
|
||
+ albatross==1.0.0
|
||
+ bluebird==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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-06e7489c", "albatross"));
|
||
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]
|
||
+ albatross==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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-e55f15c4", "albatross"));
|
||
filters.push((r"b-e55f15c4", "bluebird"));
|
||
filters.push((r"c-e55f15c4", "crow"));
|
||
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]
|
||
+ albatross==1.0.0
|
||
+ bluebird==1.0.0
|
||
+ crow==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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-492741b0", "albatross"));
|
||
filters.push((r"b-492741b0", "bluebird"));
|
||
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 only albatross[extra-c]==1.0.0 is available and albatross[extra-c]==1.0.0 depends on bluebird==2.0.0, we can conclude that all versions of albatross[extra-c] depend on bluebird==2.0.0.
|
||
And because albatross[extra-b]==1.0.0 depends on bluebird==1.0.0 and only albatross[extra-b]==1.0.0 is available, we can conclude that all versions of albatross[extra-b] and all versions of albatross[extra-c] are incompatible.
|
||
And because you require albatross[extra-c] and you require albatross[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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-f0b0089a", "albatross"));
|
||
filters.push((r"b-f0b0089a", "bluebird"));
|
||
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]
|
||
+ albatross==1.0.0
|
||
+ bluebird==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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-9d588075", "albatross"));
|
||
filters.push((r"b-9d588075", "bluebird"));
|
||
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 albatross[extra]==1.0.0 depends on bluebird==1.0.0 and only albatross[extra]==1.0.0 is available, we can conclude that all versions of albatross[extra] depend on bluebird==1.0.0.
|
||
And because you require albatross[extra] and you require bluebird==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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-f1877db3", "albatross"));
|
||
filters.push((r"b-f1877db3", "bluebird"));
|
||
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]
|
||
+ albatross==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(())
|
||
}
|
||
|
||
/// direct-incompatible-versions
|
||
///
|
||
/// The user requires two incompatible, existing versions of package `a`
|
||
///
|
||
/// ```text
|
||
/// 80d82ee8
|
||
/// ├── environment
|
||
/// │ └── python3.7
|
||
/// ├── root
|
||
/// │ ├── requires a==1.0.0
|
||
/// │ │ └── satisfied by a-1.0.0
|
||
/// │ └── requires a==2.0.0
|
||
/// │ └── satisfied by a-2.0.0
|
||
/// └── 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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-80d82ee8", "albatross"));
|
||
filters.push((r"-80d82ee8", ""));
|
||
|
||
insta::with_settings!({
|
||
filters => filters
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip")
|
||
.arg("install")
|
||
.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")
|
||
.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:
|
||
╰─▶ root dependencies are unusable: Conflicting versions for `albatross`: `albatross==1.0.0` does not intersect with `albatross==2.0.0`
|
||
"###);
|
||
});
|
||
|
||
assert_not_installed(&venv, "a_80d82ee8", &temp_dir);
|
||
assert_not_installed(&venv, "a_80d82ee8", &temp_dir);
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// transitive-incompatible-with-root-version
|
||
///
|
||
/// The user requires packages `a` and `b` but `a` requires a different version of
|
||
/// `b`
|
||
///
|
||
/// ```text
|
||
/// a967e815
|
||
/// ├── environment
|
||
/// │ └── python3.7
|
||
/// ├── root
|
||
/// │ ├── requires a
|
||
/// │ │ └── satisfied by a-1.0.0
|
||
/// │ └── requires b==1.0.0
|
||
/// │ └── satisfied by b-1.0.0
|
||
/// ├── a
|
||
/// │ └── a-1.0.0
|
||
/// │ └── requires b==2.0.0
|
||
/// │ └── satisfied by b-2.0.0
|
||
/// └── 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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-a967e815", "albatross"));
|
||
filters.push((r"b-a967e815", "bluebird"));
|
||
filters.push((r"-a967e815", ""));
|
||
|
||
insta::with_settings!({
|
||
filters => filters
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip")
|
||
.arg("install")
|
||
.arg("a-a967e815")
|
||
.arg("b-a967e815==1.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 albatross==1.0.0 depends on bluebird==2.0.0 and only albatross==1.0.0 is available, we can conclude that all versions of albatross depend on bluebird==2.0.0.
|
||
And because you require bluebird==1.0.0 and you require albatross, we can conclude that the requirements are unsatisfiable.
|
||
"###);
|
||
});
|
||
|
||
assert_not_installed(&venv, "a_a967e815", &temp_dir);
|
||
assert_not_installed(&venv, "b_a967e815", &temp_dir);
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// transitive-incompatible-with-transitive
|
||
///
|
||
/// The user requires package `a` and `b`; `a` and `b` require different versions of
|
||
/// `c`
|
||
///
|
||
/// ```text
|
||
/// 6866d8dc
|
||
/// ├── environment
|
||
/// │ └── python3.7
|
||
/// ├── root
|
||
/// │ ├── requires a
|
||
/// │ │ └── satisfied by a-1.0.0
|
||
/// │ └── requires b
|
||
/// │ └── satisfied by b-1.0.0
|
||
/// ├── a
|
||
/// │ └── a-1.0.0
|
||
/// │ └── requires c==1.0.0
|
||
/// │ └── satisfied by c-1.0.0
|
||
/// ├── b
|
||
/// │ └── b-1.0.0
|
||
/// │ └── requires c==2.0.0
|
||
/// │ └── satisfied by c-2.0.0
|
||
/// └── 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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-6866d8dc", "albatross"));
|
||
filters.push((r"b-6866d8dc", "bluebird"));
|
||
filters.push((r"c-6866d8dc", "crow"));
|
||
filters.push((r"-6866d8dc", ""));
|
||
|
||
insta::with_settings!({
|
||
filters => filters
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip")
|
||
.arg("install")
|
||
.arg("a-6866d8dc")
|
||
.arg("b-6866d8dc")
|
||
.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 only bluebird==1.0.0 is available and bluebird==1.0.0 depends on crow==2.0.0, we can conclude that all versions of bluebird depend on crow==2.0.0.
|
||
And because albatross==1.0.0 depends on crow==1.0.0 and only albatross==1.0.0 is available, we can conclude that all versions of bluebird and all versions of albatross are incompatible.
|
||
And because you require bluebird and you require albatross, we can conclude that the requirements are unsatisfiable.
|
||
"###);
|
||
});
|
||
|
||
assert_not_installed(&venv, "a_6866d8dc", &temp_dir);
|
||
assert_not_installed(&venv, "b_6866d8dc", &temp_dir);
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// package-only-prereleases
|
||
///
|
||
/// The user requires any version of package `a` which only has prerelease versions
|
||
/// available.
|
||
///
|
||
/// ```text
|
||
/// 9a1b3dda
|
||
/// ├── environment
|
||
/// │ └── python3.7
|
||
/// ├── root
|
||
/// │ └── requires a
|
||
/// │ └── 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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-9a1b3dda", "albatross"));
|
||
filters.push((r"-9a1b3dda", ""));
|
||
|
||
insta::with_settings!({
|
||
filters => filters
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip")
|
||
.arg("install")
|
||
.arg("a-9a1b3dda")
|
||
.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]
|
||
+ albatross==1.0.0a1
|
||
"###);
|
||
});
|
||
|
||
// 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, "a_9a1b3dda", "1.0.0a1", &temp_dir);
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// package-only-prereleases-in-range
|
||
///
|
||
/// The user requires a version of package `a` which only matches prerelease
|
||
/// versions but they did not include a prerelease specifier.
|
||
///
|
||
/// ```text
|
||
/// 19673198
|
||
/// ├── environment
|
||
/// │ └── python3.7
|
||
/// ├── root
|
||
/// │ └── requires a>0.1.0
|
||
/// │ └── unsatisfied: no matching version
|
||
/// └── 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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-19673198", "albatross"));
|
||
filters.push((r"-19673198", ""));
|
||
|
||
insta::with_settings!({
|
||
filters => filters
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip")
|
||
.arg("install")
|
||
.arg("a-19673198>0.1.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 only albatross<=0.1.0 is available and you require albatross>0.1.0, we can conclude that the requirements are unsatisfiable.
|
||
|
||
hint: Pre-releases are available for albatross in the requested range (e.g., 1.0.0a1), but pre-releases weren't enabled (try: `--prerelease=allow`)
|
||
"###);
|
||
});
|
||
|
||
// Since there are stable versions of `a` available, prerelease versions should not
|
||
// be selected without explicit opt-in.
|
||
assert_not_installed(&venv, "a_19673198", &temp_dir);
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// requires-package-only-prereleases-in-range-global-opt-in
|
||
///
|
||
/// The user requires a version of package `a` which only matches prerelease
|
||
/// versions. They did not include a prerelease specifier for the package, but they
|
||
/// opted into prereleases globally.
|
||
///
|
||
/// ```text
|
||
/// 51f94da2
|
||
/// ├── environment
|
||
/// │ └── python3.7
|
||
/// ├── root
|
||
/// │ └── requires a>0.1.0
|
||
/// │ └── unsatisfied: no matching version
|
||
/// └── 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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-51f94da2", "albatross"));
|
||
filters.push((r"-51f94da2", ""));
|
||
|
||
insta::with_settings!({
|
||
filters => filters
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip")
|
||
.arg("install")
|
||
.arg("a-51f94da2>0.1.0")
|
||
.arg("--prerelease=allow")
|
||
.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]
|
||
+ albatross==1.0.0a1
|
||
"###);
|
||
});
|
||
|
||
assert_installed(&venv, "a_51f94da2", "1.0.0a1", &temp_dir);
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// requires-package-prerelease-and-final-any
|
||
///
|
||
/// The user requires any version of package `a` has a prerelease version available
|
||
/// and an older non-prerelease version.
|
||
///
|
||
/// ```text
|
||
/// eebe53a6
|
||
/// ├── environment
|
||
/// │ └── python3.7
|
||
/// ├── root
|
||
/// │ └── requires a
|
||
/// │ └── satisfied by a-0.1.0
|
||
/// └── 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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-eebe53a6", "albatross"));
|
||
filters.push((r"-eebe53a6", ""));
|
||
|
||
insta::with_settings!({
|
||
filters => filters
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip")
|
||
.arg("install")
|
||
.arg("a-eebe53a6")
|
||
.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]
|
||
+ albatross==0.1.0
|
||
"###);
|
||
});
|
||
|
||
// Since the user did not provide a prerelease specifier, the older stable version
|
||
// should be selected.
|
||
assert_installed(&venv, "a_eebe53a6", "0.1.0", &temp_dir);
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// package-prerelease-specified-only-final-available
|
||
///
|
||
/// The user requires a version of `a` with a prerelease specifier and only stable
|
||
/// releases are available.
|
||
///
|
||
/// ```text
|
||
/// 9d4725eb
|
||
/// ├── environment
|
||
/// │ └── python3.7
|
||
/// ├── root
|
||
/// │ └── requires a>=0.1.0a1
|
||
/// │ ├── satisfied by a-0.1.0
|
||
/// │ ├── satisfied by a-0.2.0
|
||
/// │ └── satisfied by a-0.3.0
|
||
/// └── a
|
||
/// ├── 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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-9d4725eb", "albatross"));
|
||
filters.push((r"-9d4725eb", ""));
|
||
|
||
insta::with_settings!({
|
||
filters => filters
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip")
|
||
.arg("install")
|
||
.arg("a-9d4725eb>=0.1.0a1")
|
||
.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]
|
||
+ albatross==0.3.0
|
||
"###);
|
||
});
|
||
|
||
// The latest stable version should be selected.
|
||
assert_installed(&venv, "a_9d4725eb", "0.3.0", &temp_dir);
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// package-prerelease-specified-only-prerelease-available
|
||
///
|
||
/// The user requires a version of `a` with a prerelease specifier and only
|
||
/// prerelease releases are available.
|
||
///
|
||
/// ```text
|
||
/// 6cc95bc8
|
||
/// ├── environment
|
||
/// │ └── python3.7
|
||
/// ├── root
|
||
/// │ └── requires a>=0.1.0a1
|
||
/// │ ├── satisfied by a-0.1.0a1
|
||
/// │ ├── satisfied by a-0.2.0a1
|
||
/// │ └── satisfied by a-0.3.0a1
|
||
/// └── a
|
||
/// ├── 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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-6cc95bc8", "albatross"));
|
||
filters.push((r"-6cc95bc8", ""));
|
||
|
||
insta::with_settings!({
|
||
filters => filters
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip")
|
||
.arg("install")
|
||
.arg("a-6cc95bc8>=0.1.0a1")
|
||
.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]
|
||
+ albatross==0.3.0a1
|
||
"###);
|
||
});
|
||
|
||
// The latest prerelease version should be selected.
|
||
assert_installed(&venv, "a_6cc95bc8", "0.3.0a1", &temp_dir);
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// package-prerelease-specified-mixed-available
|
||
///
|
||
/// The user requires a version of `a` with a prerelease specifier and both
|
||
/// prerelease and stable releases are available.
|
||
///
|
||
/// ```text
|
||
/// c97845e2
|
||
/// ├── environment
|
||
/// │ └── python3.7
|
||
/// ├── root
|
||
/// │ └── requires a>=0.1.0a1
|
||
/// │ ├── satisfied by a-0.1.0
|
||
/// │ ├── satisfied by a-0.2.0a1
|
||
/// │ ├── satisfied by a-0.3.0
|
||
/// │ └── satisfied by a-1.0.0a1
|
||
/// └── a
|
||
/// ├── a-0.1.0
|
||
/// ├── 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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-c97845e2", "albatross"));
|
||
filters.push((r"-c97845e2", ""));
|
||
|
||
insta::with_settings!({
|
||
filters => filters
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip")
|
||
.arg("install")
|
||
.arg("a-c97845e2>=0.1.0a1")
|
||
.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]
|
||
+ albatross==1.0.0a1
|
||
"###);
|
||
});
|
||
|
||
// Since the user provided a prerelease specifier, the latest prerelease version
|
||
// should be selected.
|
||
assert_installed(&venv, "a_c97845e2", "1.0.0a1", &temp_dir);
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// package-multiple-prereleases-kinds
|
||
///
|
||
/// The user requires `a` which has multiple prereleases available with different
|
||
/// labels.
|
||
///
|
||
/// ```text
|
||
/// e290bf29
|
||
/// ├── environment
|
||
/// │ └── python3.7
|
||
/// ├── root
|
||
/// │ └── requires a>=1.0.0a1
|
||
/// │ ├── satisfied by a-1.0.0a1
|
||
/// │ ├── satisfied by a-1.0.0b1
|
||
/// │ └── satisfied by a-1.0.0rc1
|
||
/// └── a
|
||
/// ├── 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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-e290bf29", "albatross"));
|
||
filters.push((r"-e290bf29", ""));
|
||
|
||
insta::with_settings!({
|
||
filters => filters
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip")
|
||
.arg("install")
|
||
.arg("a-e290bf29>=1.0.0a1")
|
||
.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]
|
||
+ albatross==1.0.0rc1
|
||
"###);
|
||
});
|
||
|
||
// Release candidates should be the highest precedence prerelease kind.
|
||
assert_installed(&venv, "a_e290bf29", "1.0.0rc1", &temp_dir);
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// package-multiple-prereleases-numbers
|
||
///
|
||
/// The user requires `a` which has multiple alphas available.
|
||
///
|
||
/// ```text
|
||
/// f5948c28
|
||
/// ├── environment
|
||
/// │ └── python3.7
|
||
/// ├── root
|
||
/// │ └── requires a>=1.0.0a1
|
||
/// │ ├── satisfied by a-1.0.0a1
|
||
/// │ ├── satisfied by a-1.0.0a2
|
||
/// │ └── satisfied by a-1.0.0a3
|
||
/// └── a
|
||
/// ├── 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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-f5948c28", "albatross"));
|
||
filters.push((r"-f5948c28", ""));
|
||
|
||
insta::with_settings!({
|
||
filters => filters
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip")
|
||
.arg("install")
|
||
.arg("a-f5948c28>=1.0.0a1")
|
||
.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]
|
||
+ albatross==1.0.0a3
|
||
"###);
|
||
});
|
||
|
||
// The latest alpha version should be selected.
|
||
assert_installed(&venv, "a_f5948c28", "1.0.0a3", &temp_dir);
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// transitive-package-only-prereleases
|
||
///
|
||
/// The user requires any version of package `a` which requires `b` which only has
|
||
/// prerelease versions available.
|
||
///
|
||
/// ```text
|
||
/// 44ebef16
|
||
/// ├── environment
|
||
/// │ └── python3.7
|
||
/// ├── root
|
||
/// │ └── requires a
|
||
/// │ └── satisfied by a-0.1.0
|
||
/// ├── a
|
||
/// │ └── a-0.1.0
|
||
/// │ └── requires b
|
||
/// │ └── 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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-44ebef16", "albatross"));
|
||
filters.push((r"b-44ebef16", "bluebird"));
|
||
filters.push((r"-44ebef16", ""));
|
||
|
||
insta::with_settings!({
|
||
filters => filters
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip")
|
||
.arg("install")
|
||
.arg("a-44ebef16")
|
||
.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]
|
||
+ albatross==0.1.0
|
||
+ bluebird==1.0.0a1
|
||
"###);
|
||
});
|
||
|
||
// 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, "a_44ebef16", "0.1.0", &temp_dir);
|
||
assert_installed(&venv, "b_44ebef16", "1.0.0a1", &temp_dir);
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// transitive-package-only-prereleases-in-range
|
||
///
|
||
/// 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.
|
||
///
|
||
/// ```text
|
||
/// 27759187
|
||
/// ├── environment
|
||
/// │ └── python3.7
|
||
/// ├── root
|
||
/// │ └── requires a
|
||
/// │ └── satisfied by a-0.1.0
|
||
/// ├── a
|
||
/// │ └── a-0.1.0
|
||
/// │ └── requires b>0.1
|
||
/// │ └── unsatisfied: no matching version
|
||
/// └── 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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-27759187", "albatross"));
|
||
filters.push((r"b-27759187", "bluebird"));
|
||
filters.push((r"-27759187", ""));
|
||
|
||
insta::with_settings!({
|
||
filters => filters
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip")
|
||
.arg("install")
|
||
.arg("a-27759187")
|
||
.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 only bluebird<=0.1 is available and albatross==0.1.0 depends on bluebird>0.1, we can conclude that albatross==0.1.0 cannot be used.
|
||
And because only albatross==0.1.0 is available and you require albatross, we can conclude that the requirements are unsatisfiable.
|
||
|
||
hint: Pre-releases are available for bluebird in the requested range (e.g., 1.0.0a1), but pre-releases weren't enabled (try: `--prerelease=allow`)
|
||
"###);
|
||
});
|
||
|
||
// 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, "a_27759187", &temp_dir);
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// transitive-package-only-prereleases-in-range-opt-in
|
||
///
|
||
/// The user requires package `a` which has a dependency on a package which only
|
||
/// matches prerelease versions; the user has opted into allowing prereleases in `b`
|
||
/// explicitly.
|
||
///
|
||
/// ```text
|
||
/// 26efb6c5
|
||
/// ├── environment
|
||
/// │ └── python3.7
|
||
/// ├── root
|
||
/// │ ├── requires a
|
||
/// │ │ └── satisfied by a-0.1.0
|
||
/// │ └── requires b>0.0.0a1
|
||
/// │ └── satisfied by b-0.1.0
|
||
/// ├── a
|
||
/// │ └── a-0.1.0
|
||
/// │ └── requires b>0.1
|
||
/// │ └── unsatisfied: no matching version
|
||
/// └── 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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-26efb6c5", "albatross"));
|
||
filters.push((r"b-26efb6c5", "bluebird"));
|
||
filters.push((r"-26efb6c5", ""));
|
||
|
||
insta::with_settings!({
|
||
filters => filters
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip")
|
||
.arg("install")
|
||
.arg("a-26efb6c5")
|
||
.arg("b-26efb6c5>0.0.0a1")
|
||
.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]
|
||
+ albatross==0.1.0
|
||
+ bluebird==1.0.0a1
|
||
"###);
|
||
});
|
||
|
||
// Since the user included a dependency on `b` with a prerelease specifier, a
|
||
// prerelease version can be selected.
|
||
assert_installed(&venv, "a_26efb6c5", "0.1.0", &temp_dir);
|
||
assert_installed(&venv, "b_26efb6c5", "1.0.0a1", &temp_dir);
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// transitive-prerelease-and-stable-dependency
|
||
///
|
||
/// A transitive dependency has both a prerelease and a stable selector, but can
|
||
/// only be satisfied by a prerelease
|
||
///
|
||
/// ```text
|
||
/// f8aeea37
|
||
/// ├── environment
|
||
/// │ └── python3.7
|
||
/// ├── root
|
||
/// │ ├── requires a
|
||
/// │ │ └── satisfied by a-1.0.0
|
||
/// │ └── requires b
|
||
/// │ └── satisfied by b-1.0.0
|
||
/// ├── a
|
||
/// │ └── a-1.0.0
|
||
/// │ └── requires c==2.0.0b1
|
||
/// │ └── satisfied by c-2.0.0b1
|
||
/// ├── b
|
||
/// │ └── b-1.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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-f8aeea37", "albatross"));
|
||
filters.push((r"b-f8aeea37", "bluebird"));
|
||
filters.push((r"c-f8aeea37", "crow"));
|
||
filters.push((r"-f8aeea37", ""));
|
||
|
||
insta::with_settings!({
|
||
filters => filters
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip")
|
||
.arg("install")
|
||
.arg("a-f8aeea37")
|
||
.arg("b-f8aeea37")
|
||
.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 is no version of crow==2.0.0b1 and albatross==1.0.0 depends on crow==2.0.0b1, we can conclude that albatross==1.0.0 cannot be used.
|
||
And because only albatross==1.0.0 is available and you require albatross, we can conclude that the requirements are unsatisfiable.
|
||
|
||
hint: crow was requested with a pre-release marker (e.g., crow==2.0.0b1), but pre-releases weren't enabled (try: `--prerelease=allow`)
|
||
"###);
|
||
});
|
||
|
||
// Since the user did not explicitly opt-in to a prerelease, it cannot be selected.
|
||
assert_not_installed(&venv, "a_f8aeea37", &temp_dir);
|
||
assert_not_installed(&venv, "b_f8aeea37", &temp_dir);
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// transitive-prerelease-and-stable-dependency-opt-in
|
||
///
|
||
/// A transitive dependency has both a prerelease and a stable selector, but can
|
||
/// only be satisfied by a prerelease. The user includes an opt-in to prereleases of
|
||
/// the transitive dependency.
|
||
///
|
||
/// ```text
|
||
/// 184fc65f
|
||
/// ├── environment
|
||
/// │ └── python3.7
|
||
/// ├── root
|
||
/// │ ├── requires a
|
||
/// │ │ └── satisfied by a-1.0.0
|
||
/// │ ├── requires b
|
||
/// │ │ └── satisfied by b-1.0.0
|
||
/// │ └── requires c>=0.0.0a1
|
||
/// │ ├── satisfied by c-1.0.0
|
||
/// │ └── satisfied by c-2.0.0b1
|
||
/// ├── a
|
||
/// │ └── a-1.0.0
|
||
/// │ └── requires c==2.0.0b1
|
||
/// │ └── satisfied by c-2.0.0b1
|
||
/// ├── b
|
||
/// │ └── b-1.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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-184fc65f", "albatross"));
|
||
filters.push((r"b-184fc65f", "bluebird"));
|
||
filters.push((r"c-184fc65f", "crow"));
|
||
filters.push((r"-184fc65f", ""));
|
||
|
||
insta::with_settings!({
|
||
filters => filters
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip")
|
||
.arg("install")
|
||
.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")
|
||
.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]
|
||
+ albatross==1.0.0
|
||
+ bluebird==1.0.0
|
||
+ crow==2.0.0b1
|
||
"###);
|
||
});
|
||
|
||
// Since the user explicitly opted-in to a prerelease for `c`, it can be installed.
|
||
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(())
|
||
}
|
||
|
||
/// transitive-prerelease-and-stable-dependency-many-versions
|
||
///
|
||
/// A transitive dependency has both a prerelease and a stable selector, but can
|
||
/// only be satisfied by a prerelease. There are many prerelease versions.
|
||
///
|
||
/// ```text
|
||
/// 7017673e
|
||
/// ├── environment
|
||
/// │ └── python3.7
|
||
/// ├── root
|
||
/// │ ├── requires a
|
||
/// │ │ └── satisfied by a-1.0.0
|
||
/// │ └── requires b
|
||
/// │ └── satisfied by b-1.0.0
|
||
/// ├── a
|
||
/// │ └── a-1.0.0
|
||
/// │ └── requires c>=2.0.0b1
|
||
/// │ ├── satisfied by c-2.0.0b1
|
||
/// │ ├── satisfied by c-2.0.0b2
|
||
/// │ ├── satisfied by c-2.0.0b3
|
||
/// │ ├── satisfied by c-2.0.0b4
|
||
/// │ ├── satisfied by c-2.0.0b5
|
||
/// │ ├── satisfied by c-2.0.0b6
|
||
/// │ ├── satisfied by c-2.0.0b7
|
||
/// │ ├── satisfied by c-2.0.0b8
|
||
/// │ └── satisfied by c-2.0.0b9
|
||
/// ├── b
|
||
/// │ └── b-1.0.0
|
||
/// │ └── requires c<=3.0.0,>=1.0.0
|
||
/// │ └── satisfied by c-1.0.0
|
||
/// └── c
|
||
/// ├── c-1.0.0
|
||
/// ├── c-2.0.0a1
|
||
/// ├── c-2.0.0a2
|
||
/// ├── c-2.0.0a3
|
||
/// ├── c-2.0.0a4
|
||
/// ├── c-2.0.0a5
|
||
/// ├── c-2.0.0a6
|
||
/// ├── c-2.0.0a7
|
||
/// ├── c-2.0.0a8
|
||
/// ├── c-2.0.0a9
|
||
/// ├── c-2.0.0b1
|
||
/// ├── c-2.0.0b2
|
||
/// ├── c-2.0.0b3
|
||
/// ├── c-2.0.0b4
|
||
/// ├── c-2.0.0b5
|
||
/// ├── c-2.0.0b6
|
||
/// ├── 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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-7017673e", "albatross"));
|
||
filters.push((r"b-7017673e", "bluebird"));
|
||
filters.push((r"c-7017673e", "crow"));
|
||
filters.push((r"-7017673e", ""));
|
||
|
||
insta::with_settings!({
|
||
filters => filters
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip")
|
||
.arg("install")
|
||
.arg("a-7017673e")
|
||
.arg("b-7017673e")
|
||
.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 only bluebird==1.0.0 is available and bluebird==1.0.0 depends on crow, we can conclude that all versions of bluebird depend on crow.
|
||
And because only crow<2.0.0b1 is available we can conclude that all versions of bluebird depend on crow<2.0.0b1.
|
||
And because albatross==1.0.0 depends on crow>=2.0.0b1 and only albatross==1.0.0 is available, we can conclude that all versions of bluebird and all versions of albatross are incompatible.
|
||
And because you require bluebird and you require albatross, we can conclude that the requirements are unsatisfiable.
|
||
|
||
hint: crow was requested with a pre-release marker (e.g., crow>=2.0.0b1), but pre-releases weren't enabled (try: `--prerelease=allow`)
|
||
"###);
|
||
});
|
||
|
||
// Since the user did not explicitly opt-in to a prerelease, it cannot be selected.
|
||
assert_not_installed(&venv, "a_7017673e", &temp_dir);
|
||
assert_not_installed(&venv, "b_7017673e", &temp_dir);
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// transitive-prerelease-and-stable-dependency-many-versions-holes
|
||
///
|
||
/// A transitive dependency has both a prerelease and a stable selector, but can
|
||
/// only be satisfied by a prerelease. There are many prerelease versions and some
|
||
/// are excluded.
|
||
///
|
||
/// ```text
|
||
/// aaee5052
|
||
/// ├── environment
|
||
/// │ └── python3.7
|
||
/// ├── root
|
||
/// │ ├── requires a
|
||
/// │ │ └── satisfied by a-1.0.0
|
||
/// │ └── requires b
|
||
/// │ └── satisfied by b-1.0.0
|
||
/// ├── a
|
||
/// │ └── a-1.0.0
|
||
/// │ └── 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<=3.0.0,>=1.0.0
|
||
/// │ └── satisfied by c-1.0.0
|
||
/// └── c
|
||
/// ├── c-1.0.0
|
||
/// ├── c-2.0.0a1
|
||
/// ├── c-2.0.0a2
|
||
/// ├── c-2.0.0a3
|
||
/// ├── c-2.0.0a4
|
||
/// ├── c-2.0.0a5
|
||
/// ├── c-2.0.0a6
|
||
/// ├── c-2.0.0a7
|
||
/// ├── c-2.0.0a8
|
||
/// ├── c-2.0.0a9
|
||
/// ├── c-2.0.0b1
|
||
/// ├── c-2.0.0b2
|
||
/// ├── c-2.0.0b3
|
||
/// ├── c-2.0.0b4
|
||
/// ├── c-2.0.0b5
|
||
/// ├── c-2.0.0b6
|
||
/// ├── 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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-aaee5052", "albatross"));
|
||
filters.push((r"b-aaee5052", "bluebird"));
|
||
filters.push((r"c-aaee5052", "crow"));
|
||
filters.push((r"-aaee5052", ""));
|
||
|
||
insta::with_settings!({
|
||
filters => filters
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip")
|
||
.arg("install")
|
||
.arg("a-aaee5052")
|
||
.arg("b-aaee5052")
|
||
.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 crow that satisfy any of:
|
||
crow>1.0.0,<2.0.0a5
|
||
crow>2.0.0a7,<2.0.0b1
|
||
crow>2.0.0b1,<2.0.0b5
|
||
and albatross==1.0.0 depends on one of:
|
||
crow>1.0.0,<2.0.0a5
|
||
crow>2.0.0a7,<2.0.0b1
|
||
crow>2.0.0b1,<2.0.0b5
|
||
we can conclude that albatross==1.0.0 cannot be used.
|
||
And because only albatross==1.0.0 is available and you require albatross, we can conclude that the requirements are unsatisfiable.
|
||
|
||
hint: crow was requested with a pre-release marker (e.g., any of:
|
||
crow>1.0.0,<2.0.0a5
|
||
crow>2.0.0a7,<2.0.0b1
|
||
crow>2.0.0b1,<2.0.0b5
|
||
), but pre-releases weren't enabled (try: `--prerelease=allow`)
|
||
"###);
|
||
});
|
||
|
||
// Since the user did not explicitly opt-in to a prerelease, it cannot be selected.
|
||
assert_not_installed(&venv, "a_aaee5052", &temp_dir);
|
||
assert_not_installed(&venv, "b_aaee5052", &temp_dir);
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// requires-python-version-does-not-exist
|
||
///
|
||
/// The user requires a package which requires a Python version that does not exist
|
||
///
|
||
/// ```text
|
||
/// 0825b69c
|
||
/// ├── environment
|
||
/// │ └── python3.7
|
||
/// ├── root
|
||
/// │ └── requires a==1.0.0
|
||
/// │ └── satisfied by a-1.0.0
|
||
/// └── 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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-0825b69c", "albatross"));
|
||
filters.push((r"-0825b69c", ""));
|
||
|
||
insta::with_settings!({
|
||
filters => filters
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip")
|
||
.arg("install")
|
||
.arg("a-0825b69c==1.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 the requested Python version (3.7, 3.7.17 installed) does not satisfy Python>=4.0 and albatross==1.0.0 depends on Python>=4.0, we can conclude that albatross==1.0.0 cannot be used.
|
||
And because you require albatross==1.0.0 we can conclude that the requirements are unsatisfiable.
|
||
"###);
|
||
});
|
||
|
||
assert_not_installed(&venv, "a_0825b69c", &temp_dir);
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// requires-python-version-less-than-current
|
||
///
|
||
/// The user requires a package which requires a Python version less than the
|
||
/// current version
|
||
///
|
||
/// ```text
|
||
/// f9296b84
|
||
/// ├── environment
|
||
/// │ └── python3.9
|
||
/// ├── root
|
||
/// │ └── requires a==1.0.0
|
||
/// │ └── satisfied by a-1.0.0
|
||
/// └── 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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-f9296b84", "albatross"));
|
||
filters.push((r"-f9296b84", ""));
|
||
|
||
insta::with_settings!({
|
||
filters => filters
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip")
|
||
.arg("install")
|
||
.arg("a-f9296b84==1.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 the requested Python version (3.9, 3.9.17 installed) does not satisfy Python<=3.8 and albatross==1.0.0 depends on Python<=3.8, we can conclude that albatross==1.0.0 cannot be used.
|
||
And because you require albatross==1.0.0 we can conclude that the requirements are unsatisfiable.
|
||
"###);
|
||
});
|
||
|
||
assert_not_installed(&venv, "a_f9296b84", &temp_dir);
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// requires-python-version-greater-than-current
|
||
///
|
||
/// The user requires a package which requires a Python version greater than the
|
||
/// current version
|
||
///
|
||
/// ```text
|
||
/// a11d5394
|
||
/// ├── environment
|
||
/// │ └── python3.9
|
||
/// ├── root
|
||
/// │ └── requires a==1.0.0
|
||
/// │ └── satisfied by a-1.0.0
|
||
/// └── 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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-a11d5394", "albatross"));
|
||
filters.push((r"-a11d5394", ""));
|
||
|
||
insta::with_settings!({
|
||
filters => filters
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip")
|
||
.arg("install")
|
||
.arg("a-a11d5394==1.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 the requested Python version (3.9, 3.9.17 installed) does not satisfy Python>=3.10 and albatross==1.0.0 depends on Python>=3.10, we can conclude that albatross==1.0.0 cannot be used.
|
||
And because you require albatross==1.0.0 we can conclude that the requirements are unsatisfiable.
|
||
"###);
|
||
});
|
||
|
||
assert_not_installed(&venv, "a_a11d5394", &temp_dir);
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// requires-python-version-greater-than-current-many
|
||
///
|
||
/// The user requires a package which has many versions which all require a Python
|
||
/// version greater than the current version
|
||
///
|
||
/// ```text
|
||
/// 02dc550c
|
||
/// ├── environment
|
||
/// │ └── python3.9
|
||
/// ├── root
|
||
/// │ └── requires a==1.0.0
|
||
/// │ └── unsatisfied: no matching version
|
||
/// └── a
|
||
/// ├── a-2.0.0
|
||
/// │ └── requires python>=3.10 (incompatible with environment)
|
||
/// ├── a-2.1.0
|
||
/// │ └── requires python>=3.10 (incompatible with environment)
|
||
/// ├── a-2.2.0
|
||
/// │ └── requires python>=3.10 (incompatible with environment)
|
||
/// ├── a-2.3.0
|
||
/// │ └── requires python>=3.10 (incompatible with environment)
|
||
/// ├── a-2.4.0
|
||
/// │ └── requires python>=3.10 (incompatible with environment)
|
||
/// ├── a-2.5.0
|
||
/// │ └── requires python>=3.10 (incompatible with environment)
|
||
/// ├── a-3.0.0
|
||
/// │ └── requires python>=3.11 (incompatible with environment)
|
||
/// ├── a-3.1.0
|
||
/// │ └── requires python>=3.11 (incompatible with environment)
|
||
/// ├── a-3.2.0
|
||
/// │ └── requires python>=3.11 (incompatible with environment)
|
||
/// ├── a-3.3.0
|
||
/// │ └── requires python>=3.11 (incompatible with environment)
|
||
/// ├── a-3.4.0
|
||
/// │ └── 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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-02dc550c", "albatross"));
|
||
filters.push((r"-02dc550c", ""));
|
||
|
||
insta::with_settings!({
|
||
filters => filters
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip")
|
||
.arg("install")
|
||
.arg("a-02dc550c==1.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 there is no version of albatross==1.0.0 and you require albatross==1.0.0, we can conclude that the requirements are unsatisfiable.
|
||
"###);
|
||
});
|
||
|
||
assert_not_installed(&venv, "a_02dc550c", &temp_dir);
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// requires-python-version-greater-than-current-backtrack
|
||
///
|
||
/// The user requires a package where recent versions require a Python version
|
||
/// greater than the current version, but an older version is compatible.
|
||
///
|
||
/// ```text
|
||
/// ef060cef
|
||
/// ├── environment
|
||
/// │ └── python3.9
|
||
/// ├── root
|
||
/// │ └── requires a
|
||
/// │ ├── satisfied by a-1.0.0
|
||
/// │ ├── satisfied by a-2.0.0
|
||
/// │ ├── satisfied by a-3.0.0
|
||
/// │ └── satisfied by a-4.0.0
|
||
/// └── a
|
||
/// ├── a-1.0.0
|
||
/// ├── a-2.0.0
|
||
/// │ └── requires python>=3.10 (incompatible with environment)
|
||
/// ├── a-3.0.0
|
||
/// │ └── 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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-ef060cef", "albatross"));
|
||
filters.push((r"-ef060cef", ""));
|
||
|
||
insta::with_settings!({
|
||
filters => filters
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip")
|
||
.arg("install")
|
||
.arg("a-ef060cef")
|
||
.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]
|
||
+ albatross==1.0.0
|
||
"###);
|
||
});
|
||
|
||
assert_installed(&venv, "a_ef060cef", "1.0.0", &temp_dir);
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// requires-python-version-greater-than-current-excluded
|
||
///
|
||
/// The user requires a package where recent versions require a Python version
|
||
/// greater than the current version, but an excluded older version is compatible.
|
||
///
|
||
/// ```text
|
||
/// 1bde0c18
|
||
/// ├── environment
|
||
/// │ └── python3.9
|
||
/// ├── root
|
||
/// │ └── requires a>=2.0.0
|
||
/// │ ├── satisfied by a-2.0.0
|
||
/// │ ├── satisfied by a-3.0.0
|
||
/// │ └── satisfied by a-4.0.0
|
||
/// └── a
|
||
/// ├── a-1.0.0
|
||
/// ├── a-2.0.0
|
||
/// │ └── requires python>=3.10 (incompatible with environment)
|
||
/// ├── a-3.0.0
|
||
/// │ └── 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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-1bde0c18", "albatross"));
|
||
filters.push((r"-1bde0c18", ""));
|
||
|
||
insta::with_settings!({
|
||
filters => filters
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip")
|
||
.arg("install")
|
||
.arg("a-1bde0c18>=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 the requested Python version (3.9, 3.9.17 installed) does not satisfy Python>=3.10,<3.11 and the requested Python version (3.9, 3.9.17 installed) does not satisfy Python>=3.12, we can conclude that any of:
|
||
Python>=3.10,<3.11
|
||
Python>=3.12
|
||
are incompatible.
|
||
And because the requested Python version (3.9, 3.9.17 installed) does not satisfy Python>=3.11,<3.12 we can conclude that Python>=3.10 are incompatible.
|
||
And because albatross==2.0.0 depends on Python>=3.10 and there are no versions of albatross that satisfy any of:
|
||
albatross>2.0.0,<3.0.0
|
||
albatross>3.0.0,<4.0.0
|
||
albatross>4.0.0
|
||
we can conclude that albatross>=2.0.0,<3.0.0 cannot be used. (1)
|
||
|
||
Because the requested Python version (3.9, 3.9.17 installed) does not satisfy Python>=3.11,<3.12 and the requested Python version (3.9, 3.9.17 installed) does not satisfy Python>=3.12, we can conclude that Python>=3.11 are incompatible.
|
||
And because albatross==3.0.0 depends on Python>=3.11 we can conclude that albatross==3.0.0 cannot be used.
|
||
And because we know from (1) that albatross>=2.0.0,<3.0.0 cannot be used, we can conclude that albatross>=2.0.0,<4.0.0 cannot be used. (2)
|
||
|
||
Because the requested Python version (3.9, 3.9.17 installed) does not satisfy Python>=3.12 and albatross==4.0.0 depends on Python>=3.12, we can conclude that albatross==4.0.0 cannot be used.
|
||
And because we know from (2) that albatross>=2.0.0,<4.0.0 cannot be used, we can conclude that albatross>=2.0.0 cannot be used.
|
||
And because you require albatross>=2.0.0 we can conclude that the requirements are unsatisfiable.
|
||
"###);
|
||
});
|
||
|
||
assert_not_installed(&venv, "a_1bde0c18", &temp_dir);
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// specific-tag-and-default
|
||
///
|
||
/// A wheel for a specific platform is available alongside the default.
|
||
///
|
||
/// ```text
|
||
/// 74e4a459
|
||
/// ├── environment
|
||
/// │ └── python3.7
|
||
/// ├── root
|
||
/// │ └── requires a
|
||
/// │ └── 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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-74e4a459", "albatross"));
|
||
filters.push((r"-74e4a459", ""));
|
||
|
||
insta::with_settings!({
|
||
filters => filters
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip")
|
||
.arg("install")
|
||
.arg("a-74e4a459")
|
||
.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]
|
||
+ albatross==1.0.0
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// only-wheels
|
||
///
|
||
/// No source distributions are available, only wheels.
|
||
///
|
||
/// ```text
|
||
/// 4f019491
|
||
/// ├── environment
|
||
/// │ └── python3.7
|
||
/// ├── root
|
||
/// │ └── requires a
|
||
/// │ └── 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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-4f019491", "albatross"));
|
||
filters.push((r"-4f019491", ""));
|
||
|
||
insta::with_settings!({
|
||
filters => filters
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip")
|
||
.arg("install")
|
||
.arg("a-4f019491")
|
||
.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]
|
||
+ albatross==1.0.0
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// no-wheels
|
||
///
|
||
/// No wheels are available, only source distributions.
|
||
///
|
||
/// ```text
|
||
/// 614d801c
|
||
/// ├── environment
|
||
/// │ └── python3.7
|
||
/// ├── root
|
||
/// │ └── requires a
|
||
/// │ └── 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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-614d801c", "albatross"));
|
||
filters.push((r"-614d801c", ""));
|
||
|
||
insta::with_settings!({
|
||
filters => filters
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip")
|
||
.arg("install")
|
||
.arg("a-614d801c")
|
||
.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]
|
||
+ albatross==1.0.0
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// no-wheels-with-matching-platform
|
||
///
|
||
/// No wheels with valid tags are available, just source distributions.
|
||
///
|
||
/// ```text
|
||
/// 737bbfd4
|
||
/// ├── environment
|
||
/// │ └── python3.7
|
||
/// ├── root
|
||
/// │ └── requires a
|
||
/// │ └── 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, swap out package names for more realistic messages
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"a-737bbfd4", "albatross"));
|
||
filters.push((r"-737bbfd4", ""));
|
||
|
||
insta::with_settings!({
|
||
filters => filters
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip")
|
||
.arg("install")
|
||
.arg("a-737bbfd4")
|
||
.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]
|
||
+ albatross==1.0.0
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|