1181288078
## Summary At present, we have two separate phases within the installation pipeline related to populating wheels into the cache. The first phase downloads the distribution, and then builds any source distributions into wheels; the second phase unzips all the built wheels into the cache. This PR merges those two phases into one, such that we seamlessly download, build, and unzip wheels in one pass. This is more efficient, since we can start unzipping while we build. It also ensures that if the install _fails_ partway through, we don't end up with a bunch of downloaded wheels that we never had a chance to unzip. The code is also much simpler. The main downside is that the user-facing feedback isn't as granular, since we only have one phase and one progress bar for what was originally three distinct phases. Closes https://github.com/astral-sh/puffin/issues/571. ## Test Plan I ran the benchmark script on two separate requirements files, and saw a 7% and 31% speedup respectively: ```text + TARGET=./scripts/benchmarks/requirements.txt + hyperfine --runs 100 --warmup 10 --prepare 'virtualenv --clear .venv' './target/release/main pip-sync ./scripts/benchmarks/requirements.txt --no-cache' --prepare 'virtualenv --clear .venv' './target/release/puffin pip-sync ./scripts/benchmarks/requirements.txt --no-cache' Benchmark 1: ./target/release/main pip-sync ./scripts/benchmarks/requirements.txt --no-cache Time (mean ± σ): 269.4 ms ± 33.0 ms [User: 42.4 ms, System: 117.5 ms] Range (min … max): 221.7 ms … 446.7 ms 100 runs Benchmark 2: ./target/release/puffin pip-sync ./scripts/benchmarks/requirements.txt --no-cache Time (mean ± σ): 250.6 ms ± 28.3 ms [User: 41.5 ms, System: 127.4 ms] Range (min … max): 207.6 ms … 336.4 ms 100 runs Summary './target/release/puffin pip-sync ./scripts/benchmarks/requirements.txt --no-cache' ran 1.07 ± 0.18 times faster than './target/release/main pip-sync ./scripts/benchmarks/requirements.txt --no-cache' ``` ```text + TARGET=./scripts/benchmarks/requirements-large.txt + hyperfine --runs 100 --warmup 10 --prepare 'virtualenv --clear .venv' './target/release/main pip-sync ./scripts/benchmarks/requirements-large.txt --no-cache' --prepare 'virtualenv --clear .venv' './target/release/puffin pip-sync ./scripts/benchmarks/requirements-large.txt --no-cache' Benchmark 1: ./target/release/main pip-sync ./scripts/benchmarks/requirements-large.txt --no-cache Time (mean ± σ): 5.053 s ± 0.354 s [User: 1.413 s, System: 6.710 s] Range (min … max): 4.584 s … 6.333 s 100 runs Benchmark 2: ./target/release/puffin pip-sync ./scripts/benchmarks/requirements-large.txt --no-cache Time (mean ± σ): 3.845 s ± 0.225 s [User: 1.364 s, System: 6.970 s] Range (min … max): 3.482 s … 4.715 s 100 runs Summary './target/release/puffin pip-sync ./scripts/benchmarks/requirements-large.txt --no-cache' ran ```
1832 lines
58 KiB
Rust
1832 lines
58 KiB
Rust
#![cfg(all(feature = "python", feature = "pypi"))]
|
|
|
|
use std::path::Path;
|
|
use std::process::Command;
|
|
|
|
use anyhow::{Context, Result};
|
|
use assert_cmd::prelude::*;
|
|
use assert_fs::prelude::*;
|
|
use insta_cmd::_macro_support::insta;
|
|
use insta_cmd::{assert_cmd_snapshot, get_cargo_bin};
|
|
|
|
use common::{create_venv_py312, BIN_NAME, INSTA_FILTERS};
|
|
|
|
mod common;
|
|
|
|
fn check_command(venv: &Path, command: &str, temp_dir: &Path) {
|
|
Command::new(venv.join("bin").join("python"))
|
|
.arg("-c")
|
|
.arg(command)
|
|
.current_dir(temp_dir)
|
|
.assert()
|
|
.success();
|
|
}
|
|
|
|
#[test]
|
|
fn missing_requirements_txt() -> Result<()> {
|
|
let temp_dir = assert_fs::TempDir::new()?;
|
|
let cache_dir = assert_fs::TempDir::new()?;
|
|
let requirements_txt = temp_dir.child("requirements.txt");
|
|
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.current_dir(&temp_dir));
|
|
|
|
requirements_txt.assert(predicates::path::missing());
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn missing_venv() -> Result<()> {
|
|
let temp_dir = assert_fs::TempDir::new()?;
|
|
let cache_dir = assert_fs::TempDir::new()?;
|
|
let venv = temp_dir.child(".venv");
|
|
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir));
|
|
|
|
venv.assert(predicates::path::missing());
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Install a package into a virtual environment using the default link semantics. (On macOS,
|
|
/// this using `clone` semantics.)
|
|
#[test]
|
|
fn install() -> Result<()> {
|
|
let temp_dir = assert_fs::TempDir::new()?;
|
|
let cache_dir = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
|
|
|
let requirements_txt = temp_dir.child("requirements.txt");
|
|
requirements_txt.touch()?;
|
|
requirements_txt.write_str("MarkupSafe==2.1.3")?;
|
|
|
|
insta::with_settings!({
|
|
filters => INSTA_FILTERS.to_vec()
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir));
|
|
});
|
|
|
|
check_command(&venv, "import markupsafe", &temp_dir);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Install a package into a virtual environment using copy semantics.
|
|
#[test]
|
|
fn install_copy() -> Result<()> {
|
|
let temp_dir = assert_fs::TempDir::new()?;
|
|
let cache_dir = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
|
|
|
let requirements_txt = temp_dir.child("requirements.txt");
|
|
requirements_txt.touch()?;
|
|
requirements_txt.write_str("MarkupSafe==2.1.3")?;
|
|
|
|
insta::with_settings!({
|
|
filters => INSTA_FILTERS.to_vec()
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--link-mode")
|
|
.arg("copy")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir));
|
|
});
|
|
|
|
check_command(&venv, "import markupsafe", &temp_dir);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Install a package into a virtual environment using hardlink semantics.
|
|
#[test]
|
|
fn install_hardlink() -> Result<()> {
|
|
let temp_dir = assert_fs::TempDir::new()?;
|
|
let cache_dir = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
|
|
|
let requirements_txt = temp_dir.child("requirements.txt");
|
|
requirements_txt.touch()?;
|
|
requirements_txt.write_str("MarkupSafe==2.1.3")?;
|
|
|
|
insta::with_settings!({
|
|
filters => INSTA_FILTERS.to_vec()
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--link-mode")
|
|
.arg("hardlink")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir));
|
|
});
|
|
|
|
check_command(&venv, "import markupsafe", &temp_dir);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Install multiple packages into a virtual environment.
|
|
#[test]
|
|
fn install_many() -> Result<()> {
|
|
let temp_dir = assert_fs::TempDir::new()?;
|
|
let cache_dir = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
|
|
|
let requirements_txt = temp_dir.child("requirements.txt");
|
|
requirements_txt.touch()?;
|
|
requirements_txt.write_str("MarkupSafe==2.1.3\ntomli==2.0.1")?;
|
|
|
|
insta::with_settings!({
|
|
filters => INSTA_FILTERS.to_vec()
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir));
|
|
});
|
|
|
|
check_command(&venv, "import markupsafe; import tomli", &cache_dir);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Attempt to install an already-installed package into a virtual environment.
|
|
#[test]
|
|
fn noop() -> Result<()> {
|
|
let temp_dir = assert_fs::TempDir::new()?;
|
|
let cache_dir = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
|
|
|
let requirements_txt = temp_dir.child("requirements.txt");
|
|
requirements_txt.touch()?;
|
|
requirements_txt.write_str("MarkupSafe==2.1.3")?;
|
|
|
|
Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir)
|
|
.assert()
|
|
.success();
|
|
|
|
insta::with_settings!({
|
|
filters => INSTA_FILTERS.to_vec()
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir));
|
|
});
|
|
|
|
check_command(&venv, "import markupsafe", &temp_dir);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Install a package into a virtual environment, then install the same package into a different
|
|
/// virtual environment.
|
|
#[test]
|
|
fn link() -> Result<()> {
|
|
let temp_dir = assert_fs::TempDir::new()?;
|
|
let cache_dir = assert_fs::TempDir::new()?;
|
|
let venv1 = create_venv_py312(&temp_dir, &cache_dir);
|
|
|
|
let requirements_txt = temp_dir.child("requirements.txt");
|
|
requirements_txt.touch()?;
|
|
requirements_txt.write_str("MarkupSafe==2.1.3")?;
|
|
|
|
Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv1.as_os_str())
|
|
.current_dir(&temp_dir)
|
|
.assert()
|
|
.success();
|
|
|
|
let venv2 = temp_dir.child(".venv2");
|
|
Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("venv")
|
|
.arg(venv2.as_os_str())
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.arg("--python")
|
|
.arg("python3.12")
|
|
.current_dir(&temp_dir)
|
|
.assert()
|
|
.success();
|
|
venv2.assert(predicates::path::is_dir());
|
|
|
|
insta::with_settings!({
|
|
filters => INSTA_FILTERS.to_vec()
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv2.as_os_str())
|
|
.current_dir(&temp_dir));
|
|
});
|
|
|
|
check_command(&venv2, "import markupsafe", &temp_dir);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Install a package into a virtual environment, then sync the virtual environment with a
|
|
/// different requirements file.
|
|
#[test]
|
|
fn add_remove() -> Result<()> {
|
|
let temp_dir = assert_fs::TempDir::new()?;
|
|
let cache_dir = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
|
|
|
let requirements_txt = temp_dir.child("requirements.txt");
|
|
requirements_txt.touch()?;
|
|
requirements_txt.write_str("MarkupSafe==2.1.3")?;
|
|
|
|
Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir)
|
|
.assert()
|
|
.success();
|
|
|
|
let requirements_txt = temp_dir.child("requirements.txt");
|
|
requirements_txt.touch()?;
|
|
requirements_txt.write_str("tomli==2.0.1")?;
|
|
|
|
insta::with_settings!({
|
|
filters => INSTA_FILTERS.to_vec()
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir));
|
|
});
|
|
|
|
check_command(&venv, "import tomli", &temp_dir);
|
|
|
|
Command::new(venv.join("bin").join("python"))
|
|
.arg("-c")
|
|
.arg("import markupsafe")
|
|
.current_dir(&temp_dir)
|
|
.assert()
|
|
.failure();
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Install a package into a virtual environment, then install a second package into the same
|
|
/// virtual environment.
|
|
#[test]
|
|
fn install_sequential() -> Result<()> {
|
|
let temp_dir = assert_fs::TempDir::new()?;
|
|
let cache_dir = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
|
|
|
let requirements_txt = temp_dir.child("requirements.txt");
|
|
requirements_txt.touch()?;
|
|
requirements_txt.write_str("MarkupSafe==2.1.3")?;
|
|
|
|
Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir)
|
|
.assert()
|
|
.success();
|
|
|
|
let requirements_txt = temp_dir.child("requirements.txt");
|
|
requirements_txt.touch()?;
|
|
requirements_txt.write_str("MarkupSafe==2.1.3\ntomli==2.0.1")?;
|
|
|
|
insta::with_settings!({
|
|
filters => INSTA_FILTERS.to_vec()
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir));
|
|
});
|
|
|
|
check_command(&venv, "import markupsafe; import tomli", &cache_dir);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Install a package into a virtual environment, then install a second package into the same
|
|
/// virtual environment.
|
|
#[test]
|
|
fn upgrade() -> Result<()> {
|
|
let temp_dir = assert_fs::TempDir::new()?;
|
|
let cache_dir = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
|
|
|
let requirements_txt = temp_dir.child("requirements.txt");
|
|
requirements_txt.touch()?;
|
|
requirements_txt.write_str("tomli==2.0.0")?;
|
|
|
|
Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir)
|
|
.assert()
|
|
.success();
|
|
|
|
let requirements_txt = temp_dir.child("requirements.txt");
|
|
requirements_txt.touch()?;
|
|
requirements_txt.write_str("tomli==2.0.1")?;
|
|
|
|
insta::with_settings!({
|
|
filters => INSTA_FILTERS.to_vec()
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir));
|
|
});
|
|
|
|
check_command(&venv, "import tomli", &temp_dir);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Install a package into a virtual environment from a URL.
|
|
#[test]
|
|
fn install_url() -> Result<()> {
|
|
let temp_dir = assert_fs::TempDir::new()?;
|
|
let cache_dir = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
|
|
|
let requirements_txt = temp_dir.child("requirements.txt");
|
|
requirements_txt.touch()?;
|
|
requirements_txt.write_str("werkzeug @ https://files.pythonhosted.org/packages/ff/1d/960bb4017c68674a1cb099534840f18d3def3ce44aed12b5ed8b78e0153e/Werkzeug-2.0.0-py3-none-any.whl")?;
|
|
|
|
insta::with_settings!({
|
|
filters => vec![
|
|
(r"(\d|\.)+(ms|s)", "[TIME]"),
|
|
]
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir));
|
|
});
|
|
|
|
check_command(&venv, "import werkzeug", &temp_dir);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Install a package into a virtual environment from a Git repository.
|
|
#[test]
|
|
#[cfg(feature = "git")]
|
|
fn install_git_commit() -> Result<()> {
|
|
let temp_dir = assert_fs::TempDir::new()?;
|
|
let cache_dir = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
|
|
|
let requirements_txt = temp_dir.child("requirements.txt");
|
|
requirements_txt.touch()?;
|
|
requirements_txt.write_str("werkzeug @ git+https://github.com/pallets/werkzeug.git@af160e0b6b7ddd81c22f1652c728ff5ac72d5c74")?;
|
|
|
|
insta::with_settings!({
|
|
filters => vec![
|
|
(r"(\d|\.)+(ms|s)", "[TIME]"),
|
|
]
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir));
|
|
});
|
|
|
|
check_command(&venv, "import werkzeug", &temp_dir);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Install a package into a virtual environment from a Git repository.
|
|
#[test]
|
|
#[cfg(feature = "git")]
|
|
fn install_git_tag() -> Result<()> {
|
|
let temp_dir = assert_fs::TempDir::new()?;
|
|
let cache_dir = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
|
|
|
let requirements_txt = temp_dir.child("requirements.txt");
|
|
requirements_txt.touch()?;
|
|
requirements_txt.write_str("werkzeug @ git+https://github.com/pallets/werkzeug.git@2.0.0")?;
|
|
|
|
insta::with_settings!({
|
|
filters => vec![
|
|
(r"(\d|\.)+(ms|s)", "[TIME]"),
|
|
]
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir));
|
|
});
|
|
|
|
check_command(&venv, "import werkzeug", &temp_dir);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Install two packages from the same Git repository.
|
|
#[test]
|
|
#[cfg(feature = "git")]
|
|
fn install_git_subdirectories() -> Result<()> {
|
|
let temp_dir = assert_fs::TempDir::new()?;
|
|
let cache_dir = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
|
|
|
let requirements_txt = temp_dir.child("requirements.txt");
|
|
requirements_txt.touch()?;
|
|
requirements_txt.write_str("example-pkg-a @ git+https://github.com/pypa/sample-namespace-packages.git@df7530eeb8fa0cb7dbb8ecb28363e8e36bfa2f45#subdirectory=pkg_resources/pkg_a\nexample-pkg-b @ git+https://github.com/pypa/sample-namespace-packages.git@df7530eeb8fa0cb7dbb8ecb28363e8e36bfa2f45#subdirectory=pkg_resources/pkg_b")?;
|
|
|
|
insta::with_settings!({
|
|
filters => vec![
|
|
(r"(\d|\.)+(ms|s)", "[TIME]"),
|
|
]
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir));
|
|
});
|
|
|
|
check_command(&venv, "import example_pkg", &temp_dir);
|
|
check_command(&venv, "import example_pkg.a", &temp_dir);
|
|
check_command(&venv, "import example_pkg.b", &temp_dir);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Install a source distribution into a virtual environment.
|
|
#[test]
|
|
fn install_sdist() -> Result<()> {
|
|
let temp_dir = assert_fs::TempDir::new()?;
|
|
let cache_dir = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
|
|
|
let requirements_txt = temp_dir.child("requirements.txt");
|
|
requirements_txt.touch()?;
|
|
requirements_txt.write_str("Werkzeug==0.9.6")?;
|
|
|
|
insta::with_settings!({
|
|
filters => vec![
|
|
(r"(\d|\.)+(ms|s)", "[TIME]"),
|
|
]
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir));
|
|
});
|
|
|
|
check_command(&venv, "import werkzeug", &temp_dir);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Install a source distribution into a virtual environment.
|
|
#[test]
|
|
fn install_sdist_url() -> Result<()> {
|
|
let temp_dir = assert_fs::TempDir::new()?;
|
|
let cache_dir = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
|
|
|
let requirements_txt = temp_dir.child("requirements.txt");
|
|
requirements_txt.touch()?;
|
|
requirements_txt.write_str("Werkzeug @ https://files.pythonhosted.org/packages/63/69/5702e5eb897d1a144001e21d676676bcb87b88c0862f947509ea95ea54fc/Werkzeug-0.9.6.tar.gz")?;
|
|
|
|
insta::with_settings!({
|
|
filters => vec![
|
|
(r"(\d|\.)+(ms|s)", "[TIME]"),
|
|
]
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir));
|
|
});
|
|
|
|
check_command(&venv, "import werkzeug", &temp_dir);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Attempt to re-install a package into a virtual environment from a URL. The second install
|
|
/// should be a no-op.
|
|
#[test]
|
|
fn install_url_then_install_url() -> Result<()> {
|
|
let temp_dir = assert_fs::TempDir::new()?;
|
|
let cache_dir = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
|
|
|
let requirements_txt = temp_dir.child("requirements.txt");
|
|
requirements_txt.touch()?;
|
|
requirements_txt.write_str("werkzeug @ https://files.pythonhosted.org/packages/ff/1d/960bb4017c68674a1cb099534840f18d3def3ce44aed12b5ed8b78e0153e/Werkzeug-2.0.0-py3-none-any.whl")?;
|
|
|
|
Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir)
|
|
.assert()
|
|
.success();
|
|
|
|
insta::with_settings!({
|
|
filters => vec![
|
|
(r"(\d|\.)+(ms|s)", "[TIME]"),
|
|
]
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir));
|
|
});
|
|
|
|
check_command(&venv, "import werkzeug", &temp_dir);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Install a package via a URL, then via a registry version. The second install _should_ remove the
|
|
/// URL-based version, but doesn't right now.
|
|
#[test]
|
|
fn install_url_then_install_version() -> Result<()> {
|
|
let temp_dir = assert_fs::TempDir::new()?;
|
|
let cache_dir = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
|
|
|
let requirements_txt = temp_dir.child("requirements.txt");
|
|
requirements_txt.touch()?;
|
|
requirements_txt.write_str("werkzeug @ https://files.pythonhosted.org/packages/ff/1d/960bb4017c68674a1cb099534840f18d3def3ce44aed12b5ed8b78e0153e/Werkzeug-2.0.0-py3-none-any.whl")?;
|
|
|
|
Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir)
|
|
.assert()
|
|
.success();
|
|
|
|
let requirements_txt = temp_dir.child("requirements.txt");
|
|
requirements_txt.touch()?;
|
|
requirements_txt.write_str("werkzeug==2.0.0")?;
|
|
|
|
insta::with_settings!({
|
|
filters => vec![
|
|
(r"(\d|\.)+(ms|s)", "[TIME]"),
|
|
]
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir));
|
|
});
|
|
|
|
check_command(&venv, "import werkzeug", &temp_dir);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Install a package via a registry version, then via a direct URL version. The second install
|
|
/// should remove the registry-based version.
|
|
#[test]
|
|
fn install_version_then_install_url() -> Result<()> {
|
|
let temp_dir = assert_fs::TempDir::new()?;
|
|
let cache_dir = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
|
|
|
let requirements_txt = temp_dir.child("requirements.txt");
|
|
requirements_txt.touch()?;
|
|
requirements_txt.write_str("werkzeug==2.0.0")?;
|
|
|
|
Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir)
|
|
.assert()
|
|
.success();
|
|
|
|
let requirements_txt = temp_dir.child("requirements.txt");
|
|
requirements_txt.touch()?;
|
|
requirements_txt.write_str("werkzeug @ https://files.pythonhosted.org/packages/ff/1d/960bb4017c68674a1cb099534840f18d3def3ce44aed12b5ed8b78e0153e/Werkzeug-2.0.0-py3-none-any.whl")?;
|
|
|
|
insta::with_settings!({
|
|
filters => vec![
|
|
(r"(\d|\.)+(ms|s)", "[TIME]"),
|
|
]
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir));
|
|
});
|
|
|
|
check_command(&venv, "import werkzeug", &temp_dir);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Test that we select the last 3.8 compatible numpy version instead of trying to compile an
|
|
/// incompatible sdist <https://github.com/astral-sh/puffin/issues/388>
|
|
#[test]
|
|
fn install_numpy_py38() -> Result<()> {
|
|
let temp_dir = assert_fs::TempDir::new()?;
|
|
let cache_dir = assert_fs::TempDir::new()?;
|
|
let venv = temp_dir.child(".venv");
|
|
|
|
Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("venv")
|
|
.arg(venv.as_os_str())
|
|
.arg("--python")
|
|
// TODO(konstin): Mock the venv in the installer test so we don't need this anymore
|
|
.arg(which::which("python3.8").context("python3.8 must be installed")?)
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.current_dir(&temp_dir)
|
|
.assert()
|
|
.success();
|
|
venv.assert(predicates::path::is_dir());
|
|
|
|
let requirements_txt = temp_dir.child("requirements.txt");
|
|
requirements_txt.touch()?;
|
|
requirements_txt.write_str("numpy")?;
|
|
|
|
insta::with_settings!({
|
|
filters => INSTA_FILTERS.to_vec()
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir));
|
|
});
|
|
|
|
check_command(&venv, "import numpy", &temp_dir);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn warn_on_yanked_version() -> Result<()> {
|
|
let temp_dir = assert_fs::TempDir::new()?;
|
|
let cache_dir = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
|
|
|
let requirements_in = temp_dir.child("requirements.txt");
|
|
requirements_in.touch()?;
|
|
// This version is yanked
|
|
requirements_in.write_str("ipython==8.13.0")?;
|
|
|
|
insta::with_settings!({
|
|
filters => INSTA_FILTERS.to_vec()
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir));
|
|
});
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Resolve a local wheel.
|
|
#[test]
|
|
fn install_local_wheel() -> Result<()> {
|
|
let temp_dir = assert_fs::TempDir::new()?;
|
|
let cache_dir = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
|
|
|
// Download a wheel.
|
|
let response = reqwest::blocking::get("https://files.pythonhosted.org/packages/97/75/10a9ebee3fd790d20926a90a2547f0bf78f371b2f13aa822c759680ca7b9/tomli-2.0.1-py3-none-any.whl")?;
|
|
let archive = temp_dir.child("tomli-3.0.1-py3-none-any.whl");
|
|
let mut archive_file = std::fs::File::create(&archive)?;
|
|
std::io::copy(&mut response.bytes()?.as_ref(), &mut archive_file)?;
|
|
|
|
let requirements_txt = temp_dir.child("requirements.txt");
|
|
requirements_txt.write_str(&format!("tomli @ file://{}", archive.path().display()))?;
|
|
|
|
// In addition to the standard filters, remove the temporary directory from the snapshot.
|
|
let mut filters = INSTA_FILTERS.to_vec();
|
|
filters.push((r"file://.*/", "file://[TEMP_DIR]/"));
|
|
|
|
insta::with_settings!({
|
|
filters => filters
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir));
|
|
});
|
|
|
|
check_command(&venv, "import tomli", &temp_dir);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Install a local source distribution.
|
|
#[test]
|
|
fn install_local_source_distribution() -> Result<()> {
|
|
let temp_dir = assert_fs::TempDir::new()?;
|
|
let cache_dir = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
|
|
|
// Download a source distribution.
|
|
let response = reqwest::blocking::get("https://files.pythonhosted.org/packages/b0/b4/bc2baae3970c282fae6c2cb8e0f179923dceb7eaffb0e76170628f9af97b/wheel-0.42.0.tar.gz")?;
|
|
let archive = temp_dir.child("wheel-0.42.0.tar.gz");
|
|
let mut archive_file = std::fs::File::create(&archive)?;
|
|
std::io::copy(&mut response.bytes()?.as_ref(), &mut archive_file)?;
|
|
|
|
let requirements_txt = temp_dir.child("requirements.txt");
|
|
requirements_txt.write_str(&format!("wheel @ file://{}", archive.path().display()))?;
|
|
|
|
// In addition to the standard filters, remove the temporary directory from the snapshot.
|
|
let mut filters = INSTA_FILTERS.to_vec();
|
|
filters.push((r"file://.*/", "file://[TEMP_DIR]/"));
|
|
|
|
insta::with_settings!({
|
|
filters => filters
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir));
|
|
});
|
|
|
|
check_command(&venv, "import wheel", &temp_dir);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// The `ujson` package includes a `[build-system]`, but no `build-backend`. It lists some explicit
|
|
/// build requirements, but _also_ depends on `wheel` and `setuptools`:
|
|
/// ```toml
|
|
/// [build-system]
|
|
/// requires = ["setuptools>=42", "setuptools_scm[toml]>=3.4"]
|
|
/// ```
|
|
///
|
|
/// Like `pip` and `build`, we should use PEP 517 here and respect the `requires`, but use the
|
|
/// default build backend.
|
|
#[test]
|
|
fn install_ujson() -> Result<()> {
|
|
let temp_dir = assert_fs::TempDir::new()?;
|
|
let cache_dir = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
|
|
|
let requirements_txt = temp_dir.child("requirements.txt");
|
|
requirements_txt.touch()?;
|
|
requirements_txt.write_str("ujson @ https://files.pythonhosted.org/packages/43/1a/b0a027144aa5c8f4ea654f4afdd634578b450807bb70b9f8bad00d6f6d3c/ujson-5.7.0.tar.gz")?;
|
|
|
|
insta::with_settings!({
|
|
filters => INSTA_FILTERS.to_vec()
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir));
|
|
});
|
|
|
|
check_command(&venv, "import ujson", &temp_dir);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// The `DTLSSocket` package includes a `[build-system]`, but no `build-backend`. It lists some
|
|
/// explicit build requirements that are necessary to build the distribution:
|
|
/// ```toml
|
|
/// [build-system]
|
|
/// requires = ["Cython<3", "setuptools", "wheel"]
|
|
/// ```
|
|
///
|
|
/// Like `pip` and `build`, we should use PEP 517 here and respect the `requires`, but use the
|
|
/// default build backend.
|
|
#[test]
|
|
fn install_dtls_socket() -> Result<()> {
|
|
let temp_dir = assert_fs::TempDir::new()?;
|
|
let cache_dir = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
|
|
|
let requirements_txt = temp_dir.child("requirements.txt");
|
|
requirements_txt.touch()?;
|
|
requirements_txt.write_str("DTLSSocket @ https://files.pythonhosted.org/packages/58/42/0a0442118096eb9fbc9dc70b45aee2957f7546b80545e2a05bd839380519/DTLSSocket-0.1.16.tar.gz")?;
|
|
|
|
insta::with_settings!({
|
|
filters => INSTA_FILTERS.to_vec()
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir));
|
|
});
|
|
|
|
check_command(&venv, "import DTLSSocket", &temp_dir);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Check that we show the right messages on cached, direct URL source distribution installs.
|
|
#[test]
|
|
fn install_url_source_dist_cached() -> Result<()> {
|
|
let temp_dir = assert_fs::TempDir::new()?;
|
|
let cache_dir = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
|
|
|
let requirements_txt = temp_dir.child("requirements.txt");
|
|
requirements_txt.touch()?;
|
|
requirements_txt.write_str("tqdm @ https://files.pythonhosted.org/packages/62/06/d5604a70d160f6a6ca5fd2ba25597c24abd5c5ca5f437263d177ac242308/tqdm-4.66.1.tar.gz")?;
|
|
|
|
insta::with_settings!({
|
|
filters => INSTA_FILTERS.to_vec()
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.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]
|
|
+ tqdm @ https://files.pythonhosted.org/packages/62/06/d5604a70d160f6a6ca5fd2ba25597c24abd5c5ca5f437263d177ac242308/tqdm-4.66.1.tar.gz
|
|
"###);
|
|
});
|
|
|
|
check_command(&venv, "import tqdm", &temp_dir);
|
|
|
|
// Re-run the installation in a new virtual environment.
|
|
let parent = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&parent, &cache_dir);
|
|
|
|
insta::with_settings!({
|
|
filters => INSTA_FILTERS.to_vec()
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir), @r###"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
|
|
----- stderr -----
|
|
Installed 1 package in [TIME]
|
|
+ tqdm @ https://files.pythonhosted.org/packages/62/06/d5604a70d160f6a6ca5fd2ba25597c24abd5c5ca5f437263d177ac242308/tqdm-4.66.1.tar.gz
|
|
"###);
|
|
});
|
|
|
|
check_command(&venv, "import tqdm", &temp_dir);
|
|
|
|
// Clear the cache, then re-run the installation in a new virtual environment.
|
|
let parent = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&parent, &cache_dir);
|
|
|
|
insta::with_settings!({
|
|
filters => INSTA_FILTERS.to_vec()
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("clean")
|
|
.arg("tqdm")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir), @r###"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
|
|
----- stderr -----
|
|
Cleared 1 entry for package: tqdm
|
|
"###);
|
|
});
|
|
|
|
insta::with_settings!({
|
|
filters => INSTA_FILTERS.to_vec()
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.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]
|
|
+ tqdm @ https://files.pythonhosted.org/packages/62/06/d5604a70d160f6a6ca5fd2ba25597c24abd5c5ca5f437263d177ac242308/tqdm-4.66.1.tar.gz
|
|
"###);
|
|
});
|
|
|
|
check_command(&venv, "import tqdm", &temp_dir);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Check that we show the right messages on cached, Git source distribution installs.
|
|
#[test]
|
|
#[cfg(feature = "git")]
|
|
fn install_git_source_dist_cached() -> Result<()> {
|
|
let temp_dir = assert_fs::TempDir::new()?;
|
|
let cache_dir = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
|
|
|
let requirements_txt = temp_dir.child("requirements.txt");
|
|
requirements_txt.touch()?;
|
|
requirements_txt.write_str("werkzeug @ git+https://github.com/pallets/werkzeug.git@af160e0b6b7ddd81c22f1652c728ff5ac72d5c74")?;
|
|
|
|
insta::with_settings!({
|
|
filters => INSTA_FILTERS.to_vec()
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.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]
|
|
+ werkzeug @ git+https://github.com/pallets/werkzeug.git@af160e0b6b7ddd81c22f1652c728ff5ac72d5c74
|
|
"###);
|
|
});
|
|
|
|
check_command(&venv, "import werkzeug", &temp_dir);
|
|
|
|
// Re-run the installation in a new virtual environment.
|
|
let parent = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&parent, &cache_dir);
|
|
|
|
insta::with_settings!({
|
|
filters => INSTA_FILTERS.to_vec()
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir), @r###"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
|
|
----- stderr -----
|
|
Installed 1 package in [TIME]
|
|
+ werkzeug @ git+https://github.com/pallets/werkzeug.git@af160e0b6b7ddd81c22f1652c728ff5ac72d5c74
|
|
"###);
|
|
});
|
|
|
|
check_command(&venv, "import werkzeug", &temp_dir);
|
|
|
|
// Clear the cache, then re-run the installation in a new virtual environment.
|
|
let parent = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&parent, &cache_dir);
|
|
|
|
insta::with_settings!({
|
|
filters => INSTA_FILTERS.to_vec()
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("clean")
|
|
.arg("werkzeug")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir), @r###"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
|
|
----- stderr -----
|
|
Cleared 1 entry for package: werkzeug
|
|
"###);
|
|
});
|
|
|
|
insta::with_settings!({
|
|
filters => INSTA_FILTERS.to_vec()
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.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]
|
|
+ werkzeug @ git+https://github.com/pallets/werkzeug.git@af160e0b6b7ddd81c22f1652c728ff5ac72d5c74
|
|
"###);
|
|
});
|
|
|
|
check_command(&venv, "import werkzeug", &temp_dir);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Check that we show the right messages on cached, registry source distribution installs.
|
|
#[test]
|
|
fn install_registry_source_dist_cached() -> Result<()> {
|
|
let temp_dir = assert_fs::TempDir::new()?;
|
|
let cache_dir = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
|
|
|
let requirements_txt = temp_dir.child("requirements.txt");
|
|
requirements_txt.touch()?;
|
|
requirements_txt.write_str("future==0.18.3")?;
|
|
|
|
insta::with_settings!({
|
|
filters => INSTA_FILTERS.to_vec()
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.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]
|
|
+ future==0.18.3
|
|
"###);
|
|
});
|
|
|
|
check_command(&venv, "import future", &temp_dir);
|
|
|
|
// Re-run the installation in a new virtual environment.
|
|
let parent = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&parent, &cache_dir);
|
|
|
|
insta::with_settings!({
|
|
filters => INSTA_FILTERS.to_vec()
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir), @r###"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
|
|
----- stderr -----
|
|
Installed 1 package in [TIME]
|
|
+ future==0.18.3
|
|
"###);
|
|
});
|
|
|
|
check_command(&venv, "import future", &temp_dir);
|
|
|
|
// Clear the cache, then re-run the installation in a new virtual environment.
|
|
let parent = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&parent, &cache_dir);
|
|
|
|
insta::with_settings!({
|
|
filters => INSTA_FILTERS.to_vec()
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("clean")
|
|
.arg("future")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir), @r###"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
|
|
----- stderr -----
|
|
Cleared 2 entries for package: future
|
|
"###);
|
|
});
|
|
|
|
insta::with_settings!({
|
|
filters => INSTA_FILTERS.to_vec()
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.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]
|
|
+ future==0.18.3
|
|
"###);
|
|
});
|
|
|
|
check_command(&venv, "import future", &temp_dir);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Check that we show the right messages on cached, local source distribution installs.
|
|
#[test]
|
|
fn install_path_source_dist_cached() -> Result<()> {
|
|
let temp_dir = assert_fs::TempDir::new()?;
|
|
let cache_dir = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
|
|
|
// Download a source distribution.
|
|
let response = reqwest::blocking::get("https://files.pythonhosted.org/packages/b0/b4/bc2baae3970c282fae6c2cb8e0f179923dceb7eaffb0e76170628f9af97b/wheel-0.42.0.tar.gz")?;
|
|
let archive = temp_dir.child("wheel-0.42.0.tar.gz");
|
|
let mut archive_file = std::fs::File::create(&archive)?;
|
|
std::io::copy(&mut response.bytes()?.as_ref(), &mut archive_file)?;
|
|
|
|
let requirements_txt = temp_dir.child("requirements.txt");
|
|
requirements_txt.write_str(&format!("wheel @ file://{}", archive.path().display()))?;
|
|
|
|
// In addition to the standard filters, remove the temporary directory from the snapshot.
|
|
let mut filters = INSTA_FILTERS.to_vec();
|
|
filters.push((r"file://.*/", "file://[TEMP_DIR]/"));
|
|
|
|
insta::with_settings!({
|
|
filters => filters.clone()
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.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]
|
|
+ wheel @ file://[TEMP_DIR]/wheel-0.42.0.tar.gz
|
|
"###);
|
|
});
|
|
|
|
check_command(&venv, "import wheel", &temp_dir);
|
|
|
|
// Re-run the installation in a new virtual environment.
|
|
let parent = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&parent, &cache_dir);
|
|
|
|
insta::with_settings!({
|
|
filters => filters.clone()
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir), @r###"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
|
|
----- stderr -----
|
|
Installed 1 package in [TIME]
|
|
+ wheel @ file://[TEMP_DIR]/wheel-0.42.0.tar.gz
|
|
"###);
|
|
});
|
|
|
|
check_command(&venv, "import wheel", &temp_dir);
|
|
|
|
// Clear the cache, then re-run the installation in a new virtual environment.
|
|
let parent = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&parent, &cache_dir);
|
|
|
|
insta::with_settings!({
|
|
filters => filters.clone()
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("clean")
|
|
.arg("wheel")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir), @r###"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
|
|
----- stderr -----
|
|
Cleared 1 entry for package: wheel
|
|
"###);
|
|
});
|
|
|
|
insta::with_settings!({
|
|
filters => filters.clone()
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.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]
|
|
+ wheel @ file://[TEMP_DIR]/wheel-0.42.0.tar.gz
|
|
"###);
|
|
});
|
|
|
|
check_command(&venv, "import wheel", &temp_dir);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Check that we show the right messages on cached, local source distribution installs.
|
|
#[test]
|
|
fn install_path_built_dist_cached() -> Result<()> {
|
|
let temp_dir = assert_fs::TempDir::new()?;
|
|
let cache_dir = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
|
|
|
// Download a wheel.
|
|
let response = reqwest::blocking::get("https://files.pythonhosted.org/packages/97/75/10a9ebee3fd790d20926a90a2547f0bf78f371b2f13aa822c759680ca7b9/tomli-2.0.1-py3-none-any.whl")?;
|
|
let archive = temp_dir.child("tomli-3.0.1-py3-none-any.whl");
|
|
let mut archive_file = std::fs::File::create(&archive)?;
|
|
std::io::copy(&mut response.bytes()?.as_ref(), &mut archive_file)?;
|
|
|
|
let requirements_txt = temp_dir.child("requirements.txt");
|
|
requirements_txt.write_str(&format!("tomli @ file://{}", archive.path().display()))?;
|
|
|
|
// In addition to the standard filters, remove the temporary directory from the snapshot.
|
|
let mut filters = INSTA_FILTERS.to_vec();
|
|
filters.push((r"file://.*/", "file://[TEMP_DIR]/"));
|
|
|
|
insta::with_settings!({
|
|
filters => filters.clone()
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.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]
|
|
+ tomli @ file://[TEMP_DIR]/tomli-3.0.1-py3-none-any.whl
|
|
"###);
|
|
});
|
|
|
|
check_command(&venv, "import tomli", &temp_dir);
|
|
|
|
// Re-run the installation in a new virtual environment.
|
|
let parent = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
|
|
|
insta::with_settings!({
|
|
filters => filters.clone()
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir), @r###"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
|
|
----- stderr -----
|
|
Installed 1 package in [TIME]
|
|
+ tomli @ file://[TEMP_DIR]/tomli-3.0.1-py3-none-any.whl
|
|
"###);
|
|
});
|
|
|
|
check_command(&venv, "import tomli", &parent);
|
|
|
|
// Clear the cache, then re-run the installation in a new virtual environment.
|
|
let parent = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&parent, &cache_dir);
|
|
|
|
insta::with_settings!({
|
|
filters => filters.clone()
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("clean")
|
|
.arg("tomli")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir), @r###"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
|
|
----- stderr -----
|
|
Cleared 1 entry for package: tomli
|
|
"###);
|
|
});
|
|
|
|
insta::with_settings!({
|
|
filters => filters.clone()
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.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]
|
|
+ tomli @ file://[TEMP_DIR]/tomli-3.0.1-py3-none-any.whl
|
|
"###);
|
|
});
|
|
|
|
check_command(&venv, "import tomli", &temp_dir);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Check that we show the right messages on cached, direct URL built distribution installs.
|
|
#[test]
|
|
fn install_url_built_dist_cached() -> Result<()> {
|
|
let temp_dir = assert_fs::TempDir::new()?;
|
|
let cache_dir = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
|
|
|
let requirements_txt = temp_dir.child("requirements.txt");
|
|
requirements_txt.touch()?;
|
|
requirements_txt.write_str("tqdm @ https://files.pythonhosted.org/packages/00/e5/f12a80907d0884e6dff9c16d0c0114d81b8cd07dc3ae54c5e962cc83037e/tqdm-4.66.1-py3-none-any.whl")?;
|
|
|
|
insta::with_settings!({
|
|
filters => INSTA_FILTERS.to_vec()
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.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]
|
|
+ tqdm @ https://files.pythonhosted.org/packages/00/e5/f12a80907d0884e6dff9c16d0c0114d81b8cd07dc3ae54c5e962cc83037e/tqdm-4.66.1-py3-none-any.whl
|
|
"###);
|
|
});
|
|
|
|
check_command(&venv, "import tqdm", &temp_dir);
|
|
|
|
// Re-run the installation in a new virtual environment.
|
|
let parent = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&parent, &cache_dir);
|
|
|
|
insta::with_settings!({
|
|
filters => INSTA_FILTERS.to_vec()
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir), @r###"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
|
|
----- stderr -----
|
|
Installed 1 package in [TIME]
|
|
+ tqdm @ https://files.pythonhosted.org/packages/00/e5/f12a80907d0884e6dff9c16d0c0114d81b8cd07dc3ae54c5e962cc83037e/tqdm-4.66.1-py3-none-any.whl
|
|
"###);
|
|
});
|
|
|
|
check_command(&venv, "import tqdm", &temp_dir);
|
|
|
|
// Clear the cache, then re-run the installation in a new virtual environment.
|
|
let parent = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&parent, &cache_dir);
|
|
|
|
insta::with_settings!({
|
|
filters => INSTA_FILTERS.to_vec()
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("clean")
|
|
.arg("tqdm")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir), @r###"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
|
|
----- stderr -----
|
|
Cleared 1 entry for package: tqdm
|
|
"###);
|
|
});
|
|
|
|
insta::with_settings!({
|
|
filters => INSTA_FILTERS.to_vec()
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.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]
|
|
+ tqdm @ https://files.pythonhosted.org/packages/00/e5/f12a80907d0884e6dff9c16d0c0114d81b8cd07dc3ae54c5e962cc83037e/tqdm-4.66.1-py3-none-any.whl
|
|
"###);
|
|
});
|
|
|
|
check_command(&venv, "import tqdm", &temp_dir);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Verify that fail with an appropriate error when a package is repeated.
|
|
#[test]
|
|
fn duplicate_package_overlap() -> Result<()> {
|
|
let temp_dir = assert_fs::TempDir::new()?;
|
|
let cache_dir = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
|
|
|
let requirements_txt = temp_dir.child("requirements.txt");
|
|
requirements_txt.touch()?;
|
|
requirements_txt.write_str("MarkupSafe==2.1.3\nMarkupSafe==2.1.2")?;
|
|
|
|
insta::with_settings!({
|
|
filters => INSTA_FILTERS.to_vec()
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir), @r###"
|
|
success: false
|
|
exit_code: 2
|
|
----- stdout -----
|
|
|
|
----- stderr -----
|
|
error: Failed to determine installation plan
|
|
Caused by: Detected duplicate package in requirements:
|
|
markupsafe ==2.1.2
|
|
markupsafe ==2.1.3
|
|
"###);
|
|
});
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Verify that allow duplicate packages when they are disjoint.
|
|
#[test]
|
|
fn duplicate_package_disjoint() -> Result<()> {
|
|
let temp_dir = assert_fs::TempDir::new()?;
|
|
let cache_dir = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
|
|
|
let requirements_txt = temp_dir.child("requirements.txt");
|
|
requirements_txt.touch()?;
|
|
requirements_txt.write_str("MarkupSafe==2.1.3\nMarkupSafe==2.1.2 ; python_version < '3.6'")?;
|
|
|
|
insta::with_settings!({
|
|
filters => INSTA_FILTERS.to_vec()
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.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]
|
|
+ markupsafe==2.1.3
|
|
"###);
|
|
});
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Verify that we can force reinstall of packages.
|
|
#[test]
|
|
fn reinstall() -> Result<()> {
|
|
let temp_dir = assert_fs::TempDir::new()?;
|
|
let cache_dir = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
|
|
|
let requirements_txt = temp_dir.child("requirements.txt");
|
|
requirements_txt.touch()?;
|
|
requirements_txt.write_str("MarkupSafe==2.1.3\ntomli==2.0.1")?;
|
|
|
|
insta::with_settings!({
|
|
filters => INSTA_FILTERS.to_vec()
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.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]
|
|
+ markupsafe==2.1.3
|
|
+ tomli==2.0.1
|
|
"###);
|
|
});
|
|
|
|
check_command(&venv, "import markupsafe", &temp_dir);
|
|
check_command(&venv, "import tomli", &temp_dir);
|
|
|
|
// Re-run the installation with `--reinstall`.
|
|
insta::with_settings!({
|
|
filters => INSTA_FILTERS.to_vec()
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--reinstall")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir), @r###"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
|
|
----- stderr -----
|
|
Resolved 2 packages in [TIME]
|
|
Downloaded 2 packages in [TIME]
|
|
Uninstalled 2 packages in [TIME]
|
|
Installed 2 packages in [TIME]
|
|
- markupsafe==2.1.3
|
|
+ markupsafe==2.1.3
|
|
- tomli==2.0.1
|
|
+ tomli==2.0.1
|
|
"###);
|
|
});
|
|
|
|
check_command(&venv, "import markupsafe", &temp_dir);
|
|
check_command(&venv, "import tomli", &temp_dir);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Verify that we can force reinstall of selective packages.
|
|
#[test]
|
|
fn reinstall_package() -> Result<()> {
|
|
let temp_dir = assert_fs::TempDir::new()?;
|
|
let cache_dir = assert_fs::TempDir::new()?;
|
|
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
|
|
|
let requirements_txt = temp_dir.child("requirements.txt");
|
|
requirements_txt.touch()?;
|
|
requirements_txt.write_str("MarkupSafe==2.1.3\ntomli==2.0.1")?;
|
|
|
|
insta::with_settings!({
|
|
filters => INSTA_FILTERS.to_vec()
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.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]
|
|
+ markupsafe==2.1.3
|
|
+ tomli==2.0.1
|
|
"###);
|
|
});
|
|
|
|
check_command(&venv, "import markupsafe", &temp_dir);
|
|
check_command(&venv, "import tomli", &temp_dir);
|
|
|
|
// Re-run the installation with `--reinstall`.
|
|
insta::with_settings!({
|
|
filters => INSTA_FILTERS.to_vec()
|
|
}, {
|
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
|
.arg("pip-sync")
|
|
.arg("requirements.txt")
|
|
.arg("--reinstall-package")
|
|
.arg("tomli")
|
|
.arg("--cache-dir")
|
|
.arg(cache_dir.path())
|
|
.env("VIRTUAL_ENV", venv.as_os_str())
|
|
.current_dir(&temp_dir), @r###"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
|
|
----- stderr -----
|
|
Resolved 1 package in [TIME]
|
|
Downloaded 1 package in [TIME]
|
|
Uninstalled 1 package in [TIME]
|
|
Installed 1 package in [TIME]
|
|
- tomli==2.0.1
|
|
+ tomli==2.0.1
|
|
"###);
|
|
});
|
|
|
|
check_command(&venv, "import markupsafe", &temp_dir);
|
|
check_command(&venv, "import tomli", &temp_dir);
|
|
|
|
Ok(())
|
|
}
|