From 248d6f89ef50a2befffc8951acc875bf0103355f Mon Sep 17 00:00:00 2001 From: Zanie Blue Date: Wed, 27 Mar 2024 09:10:12 -0500 Subject: [PATCH] Bring harmony to the test snapshot filtering situation (#2678) The snapshot filtering situation has gotten way out of hand, with each test hand-rolling it's own filters on top of copied cruft from previous tests. I've attempted to address this holistically: - `TestContext.filters()` has everything you should need - This was introduced a while ago, but needed a few more filters for it to be generalized everywhere - Using `INSTA_FILTERS` is **not recommended** unless you do not want the context filters - It is okay to extend these filters for things unrelated to paths - If you have to write a custom path filter, please highlight it in review so we can address it in the common module - `TestContext.site_packages()` gives cross-platform access to the site-packages directory - Do not manually construct the path to site-packages from the venv - Do not turn off tests on Windows because you manually constructed a Unix path to site-packages - `TestContext.workspace_root` gives access to uv's repository directory - Use this for installing from `scripts/packages/` - If you need coverage for relative paths, copy the test package into the `temp_dir` don't change the working directory of the test fixture There is additional work that can be done here, such as: - Auditing and removing additional uses of `INSTA_FILTERS` - Updating manual construction of `Command` instances to use a utility - The `venv` tests are particularly frightening in their lack of a test context and could use some love - Improving the developer experience i.e. apply context filters to snapshots by default --- crates/uv-fs/src/path.rs | 11 +- crates/uv/build.rs | 7 +- crates/uv/tests/cache_prune.rs | 53 +-- crates/uv/tests/common/mod.rs | 132 ++++-- crates/uv/tests/pip_compile.rs | 240 +++------- crates/uv/tests/pip_compile_scenarios.rs | 18 +- crates/uv/tests/pip_freeze.rs | 31 +- crates/uv/tests/pip_install.rs | 434 ++++++------------- crates/uv/tests/pip_install_scenarios.rs | 196 ++++----- crates/uv/tests/pip_list.rs | 357 ++++----------- crates/uv/tests/pip_show.rs | 79 +--- crates/uv/tests/pip_sync.rs | 399 ++++++----------- crates/uv/tests/pip_uninstall.rs | 128 ++---- scripts/scenarios/templates/compile.mustache | 2 +- scripts/scenarios/templates/install.mustache | 2 +- 15 files changed, 696 insertions(+), 1393 deletions(-) diff --git a/crates/uv-fs/src/path.rs b/crates/uv-fs/src/path.rs index efac5164d..f6e94bcf0 100644 --- a/crates/uv-fs/src/path.rs +++ b/crates/uv-fs/src/path.rs @@ -3,7 +3,12 @@ use std::path::{Component, Path, PathBuf}; use once_cell::sync::Lazy; -pub static CWD: Lazy = Lazy::new(|| std::env::current_dir().unwrap()); +pub static CWD: Lazy = Lazy::new(|| { + std::env::current_dir() + .unwrap() + .canonicalize() + .expect("The current directory must exist") +}); pub trait Simplified { /// Simplify a [`Path`]. @@ -34,7 +39,9 @@ impl> Simplified for T { fn user_display(&self) -> std::path::Display { let path = dunce::simplified(self.as_ref()); - path.strip_prefix(&*CWD).unwrap_or(path).display() + path.strip_prefix(CWD.simplified()) + .unwrap_or(path) + .display() } } diff --git a/crates/uv/build.rs b/crates/uv/build.rs index 28c01bb4f..eb130a873 100644 --- a/crates/uv/build.rs +++ b/crates/uv/build.rs @@ -5,8 +5,11 @@ fn main() { // The workspace root directory is not available without walking up the tree // https://github.com/rust-lang/cargo/issues/3946 let workspace_root = Path::new(&std::env::var("CARGO_MANIFEST_DIR").unwrap()) - .join("..") - .join(".."); + .parent() + .expect("CARGO_MANIFEST_DIR should be nested in workspace") + .parent() + .expect("CARGO_MANIFEST_DIR should be doubly nested in workspace") + .to_path_buf(); commit_info(&workspace_root); diff --git a/crates/uv/tests/cache_prune.rs b/crates/uv/tests/cache_prune.rs index 0fd85238f..fe23ca759 100644 --- a/crates/uv/tests/cache_prune.rs +++ b/crates/uv/tests/cache_prune.rs @@ -8,7 +8,7 @@ use assert_fs::prelude::*; use common::uv_snapshot; -use crate::common::{get_bin, TestContext, INSTA_FILTERS}; +use crate::common::{get_bin, TestContext}; mod common; @@ -66,18 +66,13 @@ fn prune_no_op() -> Result<()> { .assert() .success(); - let filters = [(r"Pruning cache at: .*", "Pruning cache at: [CACHE_DIR]")] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect::>(); - - uv_snapshot!(filters, prune_command(&context).arg("--verbose"), @r###" + uv_snapshot!(context.filters(), prune_command(&context).arg("--verbose"), @r###" success: true exit_code: 0 ----- stdout ----- ----- stderr ----- - Pruning cache at: [CACHE_DIR] + Pruning cache at: [CACHE_DIR]/ No unused entries found "###); @@ -102,25 +97,14 @@ fn prune_stale_directory() -> Result<()> { let simple = context.cache_dir.child("simple-v4"); simple.create_dir_all()?; - let filters = [ - (r"Pruning cache at: .*", "Pruning cache at: [CACHE_DIR]"), - ( - r"Removing dangling cache entry: .*[\\|/]simple-v4", - "Pruning cache at: [CACHE_DIR]/simple-v4", - ), - ] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect::>(); - - uv_snapshot!(filters, prune_command(&context).arg("--verbose"), @r###" + uv_snapshot!(context.filters(), prune_command(&context).arg("--verbose"), @r###" success: true exit_code: 0 ----- stdout ----- ----- stderr ----- - Pruning cache at: [CACHE_DIR] - DEBUG Pruning cache at: [CACHE_DIR]/simple-v4 + Pruning cache at: [CACHE_DIR]/ + DEBUG Removing dangling cache entry: [CACHE_DIR]/simple-v4 Removed 1 directory "###); @@ -145,16 +129,17 @@ fn prune_stale_symlink() -> Result<()> { let wheels = context.cache_dir.child("wheels-v0"); fs_err::remove_dir_all(wheels)?; - let filters = [ - (r"Pruning cache at: .*", "Pruning cache at: [CACHE_DIR]"), - ( - r"Removing dangling cache entry: .*[\\|/]archive-v0[\\|/].*", - "Pruning cache at: [CACHE_DIR]/archive-v0/anyio", - ), - ] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect::>(); + let filters: Vec<_> = context + .filters() + .into_iter() + .chain([ + // The cache entry does not have a stable key, so we filter it out + ( + r"\[CACHE_DIR\](\\|\/)(.+)(\\|\/).*", + "[CACHE_DIR]/$2/[ENTRY]", + ), + ]) + .collect(); uv_snapshot!(filters, prune_command(&context).arg("--verbose"), @r###" success: true @@ -162,8 +147,8 @@ fn prune_stale_symlink() -> Result<()> { ----- stdout ----- ----- stderr ----- - Pruning cache at: [CACHE_DIR] - DEBUG Pruning cache at: [CACHE_DIR]/archive-v0/anyio + Pruning cache at: [CACHE_DIR]/ + DEBUG Removing dangling cache entry: [CACHE_DIR]/archive-v0/[ENTRY] Removed 44 files ([SIZE]) "###); diff --git a/crates/uv/tests/common/mod.rs b/crates/uv/tests/common/mod.rs index 31ea21f7f..6755d8fec 100644 --- a/crates/uv/tests/common/mod.rs +++ b/crates/uv/tests/common/mod.rs @@ -45,6 +45,7 @@ pub struct TestContext { pub cache_dir: assert_fs::TempDir, pub venv: PathBuf, pub python_version: String, + pub workspace_root: PathBuf, // Standard filters for this test context filters: Vec<(String, String)>, @@ -56,6 +57,17 @@ impl TestContext { let cache_dir = assert_fs::TempDir::new().expect("Failed to create cache dir"); let venv = create_venv(&temp_dir, &cache_dir, python_version); + // The workspace root directory is not available without walking up the tree + // https://github.com/rust-lang/cargo/issues/3946 + let workspace_root = Path::new(&std::env::var("CARGO_MANIFEST_DIR").unwrap()) + .parent() + .expect("CARGO_MANIFEST_DIR should be nested in workspace") + .parent() + .expect("CARGO_MANIFEST_DIR should be doubly nested in workspace") + .to_path_buf(); + + let site_packages = site_packages_path(&venv, format!("python{python_version}")); + let mut filters = Vec::new(); filters.extend( Self::path_patterns(&cache_dir) @@ -63,15 +75,52 @@ impl TestContext { .map(|pattern| (pattern, "[CACHE_DIR]/".to_string())), ); filters.extend( - Self::path_patterns(&temp_dir) + Self::path_patterns(&site_packages) .into_iter() - .map(|pattern| (pattern, "[TEMP_DIR]/".to_string())), + .map(|pattern| (pattern, "[SITE_PACKAGES]/".to_string())), ); filters.extend( Self::path_patterns(&venv) .into_iter() .map(|pattern| (pattern, "[VENV]/".to_string())), ); + filters.extend( + Self::path_patterns(&temp_dir) + .into_iter() + .map(|pattern| (pattern, "[TEMP_DIR]/".to_string())), + ); + filters.extend( + Self::path_patterns(&workspace_root) + .into_iter() + .map(|pattern| (pattern, "[WORKSPACE]/".to_string())), + ); + + // Account for [`Simplified::user_display`] which is relative to the command working directory + filters.push(( + Self::path_pattern( + site_packages + .strip_prefix(&temp_dir) + .expect("The test site-packages directory is always in the tempdir"), + ), + "[SITE_PACKAGES]/".to_string(), + )); + filters.push(( + Self::path_pattern( + venv.strip_prefix(&temp_dir) + .expect("The test virtual environment directory is always in the tempdir"), + ), + "[VENV]/".to_string(), + )); + + // Filter non-deterministic temporary directory names + // Note we apply this _after_ all the full paths to avoid breaking their matching + filters.push((r"(\\|\/)\.tmp.*(\\|\/)".to_string(), "/[TMP]/".to_string())); + + // Account for platform prefix differences `file://` (Unix) vs `file:///` (Windows) + filters.push((r"file:///".to_string(), "file://".to_string())); + + // Destroy any remaining UNC prefixes (Windows only) + filters.push((r"\\\\\?\\".to_string(), String::new())); Self { temp_dir, @@ -79,6 +128,7 @@ impl TestContext { venv, python_version: python_version.to_string(), filters, + workspace_root, } } @@ -128,33 +178,35 @@ impl TestContext { .stdout(version); } - /// Generate an escaped regex pattern for the given path. + /// Generate various escaped regex patterns for the given path. fn path_patterns(path: impl AsRef) -> Vec { - vec![ - format!( - // Trim the trailing separator for cross-platform directories filters - r"{}\\?/?", - regex::escape( - &path - .as_ref() - .canonicalize() - .expect("Failed to create canonical path") - // Normalize the path to match display and remove UNC prefixes on Windows - .simplified() - .display() - .to_string(), - ) - // Make seprators platform agnostic because on Windows we will display + let mut patterns = Vec::new(); + + // We can only canonicalize paths that exist already + if path.as_ref().exists() { + patterns.push(Self::path_pattern( + path.as_ref() + .canonicalize() + .expect("Failed to create canonical path"), + )); + } + + // Include a non-canonicalized version + patterns.push(Self::path_pattern(path)); + + patterns + } + + /// Generate an escaped regex pattern for the given path. + fn path_pattern(path: impl AsRef) -> String { + format!( + // Trim the trailing separator for cross-platform directories filters + r"{}\\?/?", + regex::escape(&path.as_ref().simplified_display().to_string()) + // Make separators platform agnostic because on Windows we will display // paths with Unix-style separators sometimes .replace(r"\\", r"(\\|\/)") - ), - // Include a non-canonicalized version - format!( - r"{}\\?/?", - regex::escape(&path.as_ref().simplified().display().to_string()) - .replace(r"\\", r"(\\|\/)") - ), - ] + ) } /// Standard snapshot filters _plus_ those for this test context. @@ -176,16 +228,20 @@ impl TestContext { /// Returns the site-packages folder inside the venv. pub fn site_packages(&self) -> PathBuf { - if cfg!(unix) { - self.venv - .join("lib") - .join(format!("{}{}", self.python_kind(), self.python_version)) - .join("site-packages") - } else if cfg!(windows) { - self.venv.join("Lib").join("site-packages") - } else { - unimplemented!("Only Windows and Unix are supported") - } + site_packages_path( + &self.venv, + format!("{}{}", self.python_kind(), self.python_version), + ) + } +} + +fn site_packages_path(venv: &Path, python: String) -> PathBuf { + if cfg!(unix) { + venv.join("lib").join(python).join("site-packages") + } else if cfg!(windows) { + venv.join("Lib").join("site-packages") + } else { + unimplemented!("Only Windows and Unix are supported") } } @@ -253,8 +309,8 @@ pub fn bootstrapped_pythons() -> Option> { /// Create a virtual environment named `.venv` in a temporary directory with the given /// Python version. Expected format for `python` is "python". -pub fn create_venv( - temp_dir: &assert_fs::TempDir, +pub fn create_venv>( + temp_dir: &Parent, cache_dir: &assert_fs::TempDir, python: &str, ) -> PathBuf { diff --git a/crates/uv/tests/pip_compile.rs b/crates/uv/tests/pip_compile.rs index f88fe097a..4e60c2d7d 100644 --- a/crates/uv/tests/pip_compile.rs +++ b/crates/uv/tests/pip_compile.rs @@ -12,7 +12,7 @@ use assert_fs::TempDir; use indoc::indoc; use url::Url; -use common::{uv_snapshot, TestContext, INSTA_FILTERS}; +use common::{uv_snapshot, TestContext}; use uv_fs::Simplified; use crate::common::{get_bin, EXCLUDE_NEWER}; @@ -629,13 +629,7 @@ dependencies = [ "#, )?; - // In addition to the standard filters, remove the temporary directory from the snapshot. - let filters: Vec<_> = [(r"file://.*/", "file://[TEMP_DIR]/")] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect(); - - uv_snapshot!(filters, context.compile() + uv_snapshot!(context.filters(), context.compile() .arg("pyproject.toml"), @r###" success: false exit_code: 2 @@ -862,7 +856,7 @@ fn compile_python_37() -> Result<()> { ), ] .into_iter() - .chain(INSTA_FILTERS.to_vec()) + .chain(context.filters()) .collect(); uv_snapshot!(filters, context.compile() @@ -1083,7 +1077,7 @@ fn compile_git_https_dependency() -> Result<()> { // In addition to the standard filters, remove the `main` commit, which will change frequently. let filters: Vec<_> = [(r"@(\d|\w){40}", "@[COMMIT]")] .into_iter() - .chain(INSTA_FILTERS.to_vec()) + .chain(context.filters()) .collect(); uv_snapshot!(filters, context.compile() @@ -2096,13 +2090,7 @@ fn compile_wheel_path_dependency() -> Result<()> { Url::from_file_path(flask_wheel.path()).unwrap() ))?; - // In addition to the standard filters, remove the temporary directory from the snapshot. - let filters: Vec<_> = [(r"file://.*/", "file://[TEMP_DIR]/")] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect(); - - uv_snapshot!(filters, context.compile() + uv_snapshot!(context.filters(), context.compile() .arg("requirements.in"), @r###" success: true exit_code: 0 @@ -2229,14 +2217,7 @@ fn compile_wheel_path_dependency() -> Result<()> { let requirements_in = context.temp_dir.child("requirements.in"); requirements_in.write_str(&format!("flask @ {}", flask_wheel.path().display()))?; - // In addition to the standard filters, remove the temporary directory from the snapshot. - let filter_path = regex::escape(&flask_wheel.user_display().to_string()); - let filters: Vec<_> = [(filter_path.as_str(), "/[TEMP_DIR]/")] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect(); - - uv_snapshot!(filters, context.compile() + uv_snapshot!(context.filters(), context.compile() .arg("requirements.in"), @r###" success: true exit_code: 0 @@ -2247,7 +2228,7 @@ fn compile_wheel_path_dependency() -> Result<()> { # via flask click==8.1.7 # via flask - flask @ /[TEMP_DIR]/ + flask @ [TEMP_DIR]/flask-3.0.0-py3-none-any.whl itsdangerous==2.1.2 # via flask jinja2==3.1.3 @@ -2269,14 +2250,7 @@ fn compile_wheel_path_dependency() -> Result<()> { let requirements_in = context.temp_dir.child("requirements.in"); requirements_in.write_str(&format!("flask @ file://{}", flask_wheel.path().display()))?; - // In addition to the standard filters, remove the temporary directory from the snapshot. - let filter_path = regex::escape(&flask_wheel.user_display().to_string()); - let filters: Vec<_> = [(filter_path.as_str(), "/[TEMP_DIR]/")] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect(); - - uv_snapshot!(filters, context.compile() + uv_snapshot!(context.filters(), context.compile() .arg("requirements.in"), @r###" success: true exit_code: 0 @@ -2287,7 +2261,7 @@ fn compile_wheel_path_dependency() -> Result<()> { # via flask click==8.1.7 # via flask - flask @ file:///[TEMP_DIR]/ + flask @ file://[TEMP_DIR]/flask-3.0.0-py3-none-any.whl itsdangerous==2.1.2 # via flask jinja2==3.1.3 @@ -2312,14 +2286,7 @@ fn compile_wheel_path_dependency() -> Result<()> { flask_wheel.path().display() ))?; - // In addition to the standard filters, remove the temporary directory from the snapshot. - let filter_path = regex::escape(&flask_wheel.user_display().to_string()); - let filters: Vec<_> = [(filter_path.as_str(), "/[TEMP_DIR]/")] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect(); - - uv_snapshot!(filters, context.compile() + uv_snapshot!(context.filters(), context.compile() .arg("requirements.in"), @r###" success: true exit_code: 0 @@ -2330,7 +2297,7 @@ fn compile_wheel_path_dependency() -> Result<()> { # via flask click==8.1.7 # via flask - flask @ file://localhost//[TEMP_DIR]/ + flask @ file://localhost/[TEMP_DIR]/flask-3.0.0-py3-none-any.whl itsdangerous==2.1.2 # via flask jinja2==3.1.3 @@ -2366,13 +2333,7 @@ fn compile_source_distribution_path_dependency() -> Result<()> { Url::from_file_path(flask_wheel.path()).unwrap() ))?; - // In addition to the standard filters, remove the temporary directory from the snapshot. - let filters: Vec<_> = [(r"file://.*/", "file://[TEMP_DIR]/")] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect(); - - uv_snapshot!(filters, context.compile() + uv_snapshot!(context.filters(), context.compile() .arg("requirements.in"), @r###" success: true exit_code: 0 @@ -2407,15 +2368,15 @@ fn compile_source_distribution_path_dependency() -> Result<()> { fn compile_wheel_path_dependency_missing() -> Result<()> { let context = TestContext::new("3.12"); let requirements_in = context.temp_dir.child("requirements.in"); - requirements_in.write_str("flask @ file:///path/to/flask-3.0.0-py3-none-any.whl")?; + requirements_in.write_str(&format!( + "flask @ {}", + context + .temp_dir + .join("flask-3.0.0-py3-none-any.whl") + .simplified_display() + ))?; - // In addition to the standard filters, remove the temporary directory from the snapshot. - let filters: Vec<_> = [(r"file://.*/", "file://[TEMP_DIR]/")] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect(); - - uv_snapshot!(filters, context.compile() + uv_snapshot!(context.filters(), context.compile() .arg("requirements.in"), @r###" success: false exit_code: 2 @@ -2892,20 +2853,14 @@ fn compile_editable() -> Result<()> { " })?; - let filter_path = regex::escape(&requirements_in.user_display().to_string()); - let filters: Vec<_> = [(filter_path.as_str(), "requirements.in")] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect(); - - uv_snapshot!(filters, context.compile() + uv_snapshot!(context.filters(), context.compile() .arg(requirements_in.path()) .current_dir(current_dir()?), @r###" success: true exit_code: 0 ----- stdout ----- # This file was autogenerated by uv via the following command: - # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z requirements.in + # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z [TEMP_DIR]/requirements.in -e ${PROJECT_ROOT}/../../scripts/packages/maturin_editable -e ../../scripts/packages/poetry_editable -e file://../../scripts/packages/black_editable @@ -2951,12 +2906,6 @@ fn recursive_extras_direct_url() -> Result<()> { let requirements_in = context.temp_dir.child("requirements.in"); requirements_in.write_str("black[dev] @ ../../scripts/packages/black_editable")?; - let filter_path = regex::escape(&requirements_in.user_display().to_string()); - let filters: Vec<_> = [(filter_path.as_str(), "requirements.in")] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect(); - let mut command = Command::new(get_bin()); if cfg!(all(windows, debug_assertions)) { // TODO(konstin): Reduce stack usage in debug mode enough that the tests pass with the @@ -2964,7 +2913,7 @@ fn recursive_extras_direct_url() -> Result<()> { command.env("UV_STACK_SIZE", (2 * 1024 * 1024).to_string()); } - uv_snapshot!(filters, command + uv_snapshot!(context.filters(), command .arg("pip") .arg("compile") .arg(requirements_in.path()) @@ -2977,7 +2926,7 @@ fn recursive_extras_direct_url() -> Result<()> { exit_code: 0 ----- stdout ----- # This file was autogenerated by uv via the following command: - # uv pip compile requirements.in --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z + # uv pip compile [TEMP_DIR]/requirements.in --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z aiohttp==3.9.3 # via black aiosignal==1.3.1 @@ -3014,20 +2963,14 @@ fn compile_editable_url_requirement() -> Result<()> { let requirements_in = context.temp_dir.child("requirements.in"); requirements_in.write_str("-e ../../scripts/packages/hatchling_editable")?; - let filter_path = regex::escape(&requirements_in.user_display().to_string()); - let filters: Vec<_> = [(filter_path.as_str(), "requirements.in")] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect(); - - uv_snapshot!(filters, context.compile() + uv_snapshot!(context.filters(), context.compile() .arg(requirements_in.path()) .current_dir(current_dir()?), @r###" success: true exit_code: 0 ----- stdout ----- # This file was autogenerated by uv via the following command: - # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z requirements.in + # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z [TEMP_DIR]/requirements.in -e ../../scripts/packages/hatchling_editable iniconfig @ git+https://github.com/pytest-dev/iniconfig@9cae43103df70bac6fde7b9f35ad11a9f1be0cb4 # via hatchling-editable @@ -3296,7 +3239,7 @@ fn generate_hashes() -> Result<()> { vec![] } .into_iter() - .chain(INSTA_FILTERS.to_vec()) + .chain(context.filters()) .collect(); uv_snapshot!(filters, context.compile() @@ -3414,24 +3357,10 @@ fn find_links_directory() -> Result<()> { werkzeug @ https://files.pythonhosted.org/packages/c3/fc/254c3e9b5feb89ff5b9076a23218dafbc99c96ac5941e900b71206e6313b/werkzeug-3.0.1-py3-none-any.whl "})?; - let project_root = fs_err::canonicalize(std::env::current_dir()?.join("..").join(".."))?; - let project_root_string = regex::escape(&project_root.user_display().to_string()); - let filters: Vec<_> = [ - (project_root_string.as_str(), "[PROJECT_ROOT]"), - // Unify trailing (back)slash between Windows and Unix. - ( - "[PROJECT_ROOT]/scripts/wheels/", - "[PROJECT_ROOT]/scripts/wheels", - ), - ] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect(); - - uv_snapshot!(filters, context.compile() + uv_snapshot!(context.filters(), context.compile() .arg("requirements.in") .arg("--find-links") - .arg(project_root.join("scripts").join("wheels")), @r###" + .arg(context.workspace_root.join("scripts").join("wheels")), @r###" success: true exit_code: 0 ----- stdout ----- @@ -3708,7 +3637,7 @@ fn missing_path_requirement() -> Result<()> { let filters: Vec<_> = [(r"/C:/", "/")] .into_iter() - .chain(INSTA_FILTERS.to_vec()) + .chain(context.filters()) .collect(); uv_snapshot!(filters, context.compile() @@ -3718,7 +3647,7 @@ fn missing_path_requirement() -> Result<()> { ----- stdout ----- ----- stderr ----- - error: Distribution not found at: file:///tmp/anyio-3.7.0.tar.gz + error: Distribution not found at: file://tmp/anyio-3.7.0.tar.gz "###); Ok(()) @@ -3729,19 +3658,9 @@ fn missing_path_requirement() -> Result<()> { fn missing_editable_requirement() -> Result<()> { let context = TestContext::new("3.12"); let requirements_in = context.temp_dir.child("requirements.in"); - requirements_in.write_str("-e ../tmp/anyio-3.7.0.tar.gz")?; + requirements_in.write_str("-e foo/anyio-3.7.0.tar.gz")?; - // File url, absolute Unix path or absolute Windows path - let filters: Vec<_> = [ - (r" file://.*/", " file://[TEMP_DIR]/"), - (r" /.*/", " /[TEMP_DIR]/"), - (r" [A-Z]:\\.*\\", " /[TEMP_DIR]/"), - ] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect::>(); - - uv_snapshot!(filters, context.compile() + uv_snapshot!(context.filters(), context.compile() .arg("requirements.in"), @r###" success: false exit_code: 2 @@ -3749,7 +3668,7 @@ fn missing_editable_requirement() -> Result<()> { ----- stderr ----- error: Failed to build editables - Caused by: Source distribution not found at: /[TEMP_DIR]/anyio-3.7.0.tar.gz + Caused by: Source distribution not found at: [TEMP_DIR]/foo/anyio-3.7.0.tar.gz "###); Ok(()) @@ -4612,29 +4531,20 @@ fn editable_invalid_extra() -> Result<()> { let requirements_in = context.temp_dir.child("requirements.in"); requirements_in.write_str("-e ../../scripts/packages/black_editable[empty]")?; - let requirements_path = regex::escape(&requirements_in.user_display().to_string()); - let filters: Vec<_> = [ - (r" file://.*/", " file://[TEMP_DIR]/"), - (requirements_path.as_str(), "requirements.in"), - ] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect(); - - uv_snapshot!(filters, context.compile() + uv_snapshot!(context.filters(), context.compile() .arg(requirements_in.path()) .current_dir(current_dir()?), @r###" success: true exit_code: 0 ----- stdout ----- # This file was autogenerated by uv via the following command: - # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z requirements.in + # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z [TEMP_DIR]/requirements.in -e ../../scripts/packages/black_editable ----- stderr ----- Built 1 editable in [TIME] Resolved 1 package in [TIME] - warning: The package `black @ file://[TEMP_DIR]/black_editable` does not have an extra named `empty`. + warning: The package `black @ file://[WORKSPACE]/scripts/packages/black_editable` does not have an extra named `empty`. "###); Ok(()) @@ -4930,17 +4840,7 @@ fn override_editable() -> Result<()> { let overrides_txt = context.temp_dir.child("overrides.txt"); overrides_txt.write_str("black==23.10.1")?; - let requirements_path = regex::escape(&requirements_in.user_display().to_string()); - let overrides_path = regex::escape(&overrides_txt.user_display().to_string()); - let filters: Vec<_> = [ - (requirements_path.as_str(), "requirements.in"), - (overrides_path.as_str(), "overrides.txt"), - ] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect(); - - uv_snapshot!(filters, context.compile() + uv_snapshot!(context.filters(), context.compile() .arg(requirements_in.path()) .arg("--override") .arg(overrides_txt.path()) @@ -4949,7 +4849,7 @@ fn override_editable() -> Result<()> { exit_code: 0 ----- stdout ----- # This file was autogenerated by uv via the following command: - # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z requirements.in --override overrides.txt + # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z [TEMP_DIR]/requirements.in --override [TEMP_DIR]/overrides.txt -e ../../scripts/packages/black_editable ----- stderr ----- @@ -5278,16 +5178,7 @@ fn editable_direct_dependency() -> Result<()> { let requirements_in = context.temp_dir.child("requirements.in"); requirements_in.write_str("-e ../../scripts/packages/setuptools_editable")?; - let requirements_path = regex::escape(&requirements_in.user_display().to_string()); - let filters: Vec<_> = [ - (r" file://.*/", " file://[TEMP_DIR]/"), - (requirements_path.as_str(), "requirements.in"), - ] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect(); - - uv_snapshot!(filters, context.compile() + uv_snapshot!(context.filters(), context.compile() .arg(requirements_in.path()) .arg("--resolution") .arg("lowest-direct") @@ -5296,7 +5187,7 @@ fn editable_direct_dependency() -> Result<()> { exit_code: 0 ----- stdout ----- # This file was autogenerated by uv via the following command: - # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z requirements.in --resolution lowest-direct + # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z [TEMP_DIR]/requirements.in --resolution lowest-direct -e ../../scripts/packages/setuptools_editable iniconfig==0.1 # via setuptools-editable @@ -5468,7 +5359,8 @@ fn requires_python_editable() -> Result<()> { let context = TestContext::new("3.12"); // Create an editable package with a `Requires-Python` constraint that is not met. - let editable_dir = TempDir::new()?; + let editable_dir = context.temp_dir.child("editable"); + editable_dir.create_dir_all()?; let pyproject_toml = editable_dir.child("pyproject.toml"); pyproject_toml.write_str( r#"[project] @@ -5505,7 +5397,8 @@ fn requires_python_editable_target_version() -> Result<()> { let context = TestContext::new("3.12"); // Create an editable package with a `Requires-Python` constraint that is not met. - let editable_dir = TempDir::new()?; + let editable_dir = context.temp_dir.child("editable"); + editable_dir.create_dir_all()?; let pyproject_toml = editable_dir.child("pyproject.toml"); pyproject_toml.write_str( r#"[project] @@ -5530,7 +5423,7 @@ requires-python = "<=3.8" ), ] .into_iter() - .chain(INSTA_FILTERS.to_vec()) + .chain(context.filters()) .collect(); uv_snapshot!(filters, context.compile() @@ -5720,7 +5613,8 @@ fn requires_python_direct_url() -> Result<()> { let context = TestContext::new("3.12"); // Create an editable package with a `Requires-Python` constraint that is not met. - let editable_dir = TempDir::new()?; + let editable_dir = context.temp_dir.child("editable"); + editable_dir.create_dir_all()?; let pyproject_toml = editable_dir.child("pyproject.toml"); pyproject_toml.write_str( r#"[project] @@ -5764,14 +5658,8 @@ fn compile_root_uri_editable() -> Result<()> { let requirements_in = context.temp_dir.child("requirements.in"); requirements_in.write_str("-e ${ROOT_PATH}")?; - // In addition to the standard filters, remove the temporary directory from the snapshot. - let filters: Vec<_> = [(r"file://.*/", "file://[TEMP_DIR]/")] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect(); - let root_path = current_dir()?.join("../../scripts/packages/root_editable"); - uv_snapshot!(filters, context.compile() + uv_snapshot!(context.filters(), context.compile() .arg("requirements.in") .env("ROOT_PATH", root_path.as_os_str()), @r###" success: true @@ -5780,7 +5668,7 @@ fn compile_root_uri_editable() -> Result<()> { # This file was autogenerated by uv via the following command: # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z requirements.in -e ${ROOT_PATH} - black @ file://[TEMP_DIR]/black_editable + black @ file://[WORKSPACE]/scripts/packages/root_editable/../black_editable # via root-editable ----- stderr ----- @@ -5800,15 +5688,9 @@ fn compile_root_uri_non_editable() -> Result<()> { let requirements_in = context.temp_dir.child("requirements.in"); requirements_in.write_str("${ROOT_PATH}\n${BLACK_PATH}")?; - // In addition to the standard filters, remove the temporary directory from the snapshot. - let filters: Vec<_> = [(r"file://.*/", "file://[TEMP_DIR]/")] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect(); - let root_path = current_dir()?.join("../../scripts/packages/root_editable"); let black_path = current_dir()?.join("../../scripts/packages/black_editable"); - uv_snapshot!(filters, context.compile() + uv_snapshot!(context.filters(), context.compile() .arg("requirements.in") .env("ROOT_PATH", root_path.as_os_str()) .env("BLACK_PATH", black_path.as_os_str()), @r###" @@ -6098,20 +5980,14 @@ fn unnamed_path_requirement() -> Result<()> { " })?; - let filter_path = regex::escape(&requirements_in.user_display().to_string()); - let filters: Vec<_> = [(filter_path.as_str(), "requirements.in")] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect(); - - uv_snapshot!(filters, context.compile() + uv_snapshot!(context.filters(), context.compile() .arg(requirements_in.path()) .current_dir(current_dir()?), @r###" success: true exit_code: 0 ----- stdout ----- # This file was autogenerated by uv via the following command: - # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z requirements.in + # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z [TEMP_DIR]/requirements.in anyio==4.3.0 # via # httpx @@ -6236,20 +6112,14 @@ fn dynamic_dependencies() -> Result<()> { let requirements_in = context.temp_dir.child("requirements.in"); requirements_in.write_str("hatchling-dynamic @ ../../scripts/packages/hatchling_dynamic")?; - let filter_path = regex::escape(&requirements_in.user_display().to_string()); - let filters: Vec<_> = [(filter_path.as_str(), "requirements.in")] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect(); - - uv_snapshot!(filters, context.compile() + uv_snapshot!(context.filters(), context.compile() .arg(requirements_in.path()) .current_dir(current_dir()?), @r###" success: true exit_code: 0 ----- stdout ----- # This file was autogenerated by uv via the following command: - # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z requirements.in + # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z [TEMP_DIR]/requirements.in anyio==4.3.0 # via hatchling-dynamic hatchling-dynamic @ ../../scripts/packages/hatchling_dynamic diff --git a/crates/uv/tests/pip_compile_scenarios.rs b/crates/uv/tests/pip_compile_scenarios.rs index 0605f931e..00787f107 100644 --- a/crates/uv/tests/pip_compile_scenarios.rs +++ b/crates/uv/tests/pip_compile_scenarios.rs @@ -13,7 +13,7 @@ use assert_cmd::assert::OutputAssertExt; use assert_fs::fixture::{FileWriteStr, PathChild}; use predicates::prelude::predicate; -use common::{create_bin_with_executables, get_bin, uv_snapshot, TestContext, INSTA_FILTERS}; +use common::{create_bin_with_executables, get_bin, uv_snapshot, TestContext}; mod common; @@ -67,7 +67,7 @@ fn incompatible_python_compatible_override() -> Result<()> { let python_versions = &[]; // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"incompatible-python-compatible-override-", "package-")); let requirements_in = context.temp_dir.child("requirements.in"); @@ -116,7 +116,7 @@ fn compatible_python_incompatible_override() -> Result<()> { let python_versions = &[]; // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"compatible-python-incompatible-override-", "package-")); let requirements_in = context.temp_dir.child("requirements.in"); @@ -163,7 +163,7 @@ fn incompatible_python_compatible_override_unavailable_no_wheels() -> Result<()> let python_versions = &[]; // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push(( r"incompatible-python-compatible-override-unavailable-no-wheels-", "package-", @@ -219,7 +219,7 @@ fn incompatible_python_compatible_override_available_no_wheels() -> Result<()> { let python_versions = &["3.11"]; // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push(( r"incompatible-python-compatible-override-available-no-wheels-", "package-", @@ -274,7 +274,7 @@ fn incompatible_python_compatible_override_no_compatible_wheels() -> Result<()> let python_versions = &[]; // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push(( r"incompatible-python-compatible-override-no-compatible-wheels-", "package-", @@ -332,7 +332,7 @@ fn incompatible_python_compatible_override_other_wheel() -> Result<()> { let python_versions = &[]; // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push(( r"incompatible-python-compatible-override-other-wheel-", "package-", @@ -392,7 +392,7 @@ fn python_patch_override_no_patch() -> Result<()> { let python_versions = &[]; // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"python-patch-override-no-patch-", "package-")); let requirements_in = context.temp_dir.child("requirements.in"); @@ -439,7 +439,7 @@ fn python_patch_override_patch_compatible() -> Result<()> { let python_versions = &[]; // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"python-patch-override-patch-compatible-", "package-")); let requirements_in = context.temp_dir.child("requirements.in"); diff --git a/crates/uv/tests/pip_freeze.rs b/crates/uv/tests/pip_freeze.rs index 11751112a..94dd243db 100644 --- a/crates/uv/tests/pip_freeze.rs +++ b/crates/uv/tests/pip_freeze.rs @@ -77,7 +77,7 @@ fn freeze_many() -> Result<()> { #[test] #[cfg(unix)] fn freeze_duplicate() -> Result<()> { - use crate::common::{copy_dir_all, INSTA_FILTERS}; + use crate::common::copy_dir_all; // Sync a version of `pip` into a virtual environment. let context1 = TestContext::new("3.12"); @@ -103,31 +103,12 @@ fn freeze_duplicate() -> Result<()> { // Copy the virtual environment to a new location. copy_dir_all( - context2 - .venv - .join("lib/python3.12/site-packages/pip-22.1.1.dist-info"), - context1 - .venv - .join("lib/python3.12/site-packages/pip-22.1.1.dist-info"), + context2.site_packages().join("pip-22.1.1.dist-info"), + context1.site_packages().join("pip-22.1.1.dist-info"), )?; // Run `pip freeze`. - let filters = INSTA_FILTERS - .iter() - .chain(&[ - ( - ".*/lib/python3.12/site-packages/pip-22.1.1.dist-info", - "/pip-22.1.1.dist-info", - ), - ( - ".*/lib/python3.12/site-packages/pip-21.3.1.dist-info", - "/pip-21.3.1.dist-info", - ), - ]) - .copied() - .collect::>(); - - uv_snapshot!(filters, command(&context1).arg("--strict"), @r###" + uv_snapshot!(context1.filters(), command(&context1).arg("--strict"), @r###" success: true exit_code: 0 ----- stdout ----- @@ -136,8 +117,8 @@ fn freeze_duplicate() -> Result<()> { ----- stderr ----- warning: The package `pip` has multiple installed distributions: - /pip-21.3.1.dist-info - /pip-22.1.1.dist-info + - [SITE_PACKAGES]/pip-21.3.1.dist-info + - [SITE_PACKAGES]/pip-22.1.1.dist-info "### ); diff --git a/crates/uv/tests/pip_install.rs b/crates/uv/tests/pip_install.rs index 7ba2056dc..eaeec7199 100644 --- a/crates/uv/tests/pip_install.rs +++ b/crates/uv/tests/pip_install.rs @@ -6,11 +6,10 @@ use assert_fs::prelude::*; use base64::{prelude::BASE64_STANDARD as base64, Engine}; use indoc::indoc; use itertools::Itertools; -use std::env::current_dir; -use std::process::Command; -use url::Url; -use common::{uv_snapshot, TestContext, EXCLUDE_NEWER, INSTA_FILTERS}; +use std::process::Command; + +use common::{uv_snapshot, TestContext, EXCLUDE_NEWER}; use uv_fs::Simplified; use crate::common::get_bin; @@ -215,14 +214,10 @@ dependencies = ["flask==1.0.x"] "#, )?; - let filters = [ - (r"file://.*", "[SOURCE_DIR]"), - (r#"File ".*[/\\]site-packages"#, "File \"[SOURCE_DIR]"), - ("exit status", "exit code"), - ] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect::>(); + let filters = [("exit status", "exit code")] + .into_iter() + .chain(context.filters()) + .collect::>(); uv_snapshot!(filters, command(&context) .arg("-r") @@ -232,7 +227,7 @@ dependencies = ["flask==1.0.x"] ----- stdout ----- ----- stderr ----- - error: Failed to build: [SOURCE_DIR] + error: Failed to build: file://[TEMP_DIR]/ Caused by: Build backend failed to determine extra requires with `build_wheel()` with exit code: 1 --- stdout: configuration error: `project.dependencies[0]` must be pep508 @@ -254,32 +249,32 @@ dependencies = ["flask==1.0.x"] --- stderr: Traceback (most recent call last): File "", line 14, in - File "[SOURCE_DIR]/setuptools/build_meta.py", line 325, in get_requires_for_build_wheel + File "[CACHE_DIR]/[TMP]/build_meta.py", line 325, in get_requires_for_build_wheel return self._get_build_requires(config_settings, requirements=['wheel']) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "[SOURCE_DIR]/setuptools/build_meta.py", line 295, in _get_build_requires + File "[CACHE_DIR]/[TMP]/build_meta.py", line 295, in _get_build_requires self.run_setup() - File "[SOURCE_DIR]/setuptools/build_meta.py", line 487, in run_setup + File "[CACHE_DIR]/[TMP]/build_meta.py", line 487, in run_setup super().run_setup(setup_script=setup_script) - File "[SOURCE_DIR]/setuptools/build_meta.py", line 311, in run_setup + File "[CACHE_DIR]/[TMP]/build_meta.py", line 311, in run_setup exec(code, locals()) File "", line 1, in - File "[SOURCE_DIR]/setuptools/__init__.py", line 104, in setup + File "[CACHE_DIR]/[TMP]/__init__.py", line 104, in setup return distutils.core.setup(**attrs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "[SOURCE_DIR]/setuptools/_distutils/core.py", line 159, in setup + File "[CACHE_DIR]/[TMP]/core.py", line 159, in setup dist.parse_config_files() - File "[SOURCE_DIR]/_virtualenv.py", line 22, in parse_config_files + File "[CACHE_DIR]/[TMP]/_virtualenv.py", line 22, in parse_config_files result = old_parse_config_files(self, *args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "[SOURCE_DIR]/setuptools/dist.py", line 631, in parse_config_files + File "[CACHE_DIR]/[TMP]/dist.py", line 631, in parse_config_files pyprojecttoml.apply_configuration(self, filename, ignore_option_errors) - File "[SOURCE_DIR]/setuptools/config/pyprojecttoml.py", line 68, in apply_configuration + File "[CACHE_DIR]/[TMP]/pyprojecttoml.py", line 68, in apply_configuration config = read_configuration(filepath, True, ignore_option_errors, dist) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "[SOURCE_DIR]/setuptools/config/pyprojecttoml.py", line 129, in read_configuration + File "[CACHE_DIR]/[TMP]/pyprojecttoml.py", line 129, in read_configuration validate(subset, filepath) - File "[SOURCE_DIR]/setuptools/config/pyprojecttoml.py", line 57, in validate + File "[CACHE_DIR]/[TMP]/pyprojecttoml.py", line 57, in validate raise ValueError(f"{error}/n{summary}") from None ValueError: invalid pyproject.toml config: `project.dependencies[0]`. configuration error: `project.dependencies[0]` must be pep508 @@ -458,13 +453,13 @@ fn respect_installed_and_reinstall() -> Result<()> { let filters = if cfg!(windows) { // Remove the colorama count on windows - INSTA_FILTERS - .iter() - .copied() + context + .filters() + .into_iter() .chain([("Resolved 8 packages", "Resolved 7 packages")]) .collect() } else { - INSTA_FILTERS.to_vec() + context.filters() }; uv_snapshot!(filters, command(&context) .arg("-r") @@ -596,7 +591,6 @@ fn reinstall_extras() -> Result<()> { /// Warn, but don't fail, when uninstalling incomplete packages. #[test] -#[cfg(unix)] fn reinstall_incomplete() -> Result<()> { let context = TestContext::new("3.12"); @@ -623,23 +617,14 @@ fn reinstall_incomplete() -> Result<()> { ); // Manually remove the `RECORD` file. - fs_err::remove_file( - context - .venv - .join("lib/python3.12/site-packages/anyio-3.7.0.dist-info/RECORD"), - )?; + fs_err::remove_file(context.site_packages().join("anyio-3.7.0.dist-info/RECORD"))?; // Re-install anyio. let requirements_txt = context.temp_dir.child("requirements.txt"); requirements_txt.touch()?; requirements_txt.write_str("anyio==4.0.0")?; - let filters = [(r"Failed to uninstall package at .* due to missing RECORD", "Failed to uninstall package at .venv/lib/python3.12/site-packages/anyio-3.7.0.dist-info due to missing RECORD")] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect::>(); - - uv_snapshot!(filters, command(&context) + uv_snapshot!(context.filters(), command(&context) .arg("-r") .arg("requirements.txt"), @r###" success: true @@ -649,7 +634,7 @@ fn reinstall_incomplete() -> Result<()> { ----- stderr ----- Resolved 3 packages in [TIME] Downloaded 1 package in [TIME] - warning: Failed to uninstall package at .venv/lib/python3.12/site-packages/anyio-3.7.0.dist-info due to missing RECORD file. Installation may result in an incomplete environment. + warning: Failed to uninstall package at [SITE_PACKAGES]/anyio-3.7.0.dist-info due to missing RECORD file. Installation may result in an incomplete environment. Installed 1 package in [TIME] - anyio==3.7.0 + anyio==4.0.0 @@ -723,28 +708,13 @@ fn allow_incompatibilities() -> Result<()> { } #[test] -#[cfg(feature = "maturin")] -fn install_editable() -> Result<()> { +fn install_editable() { let context = TestContext::new("3.12"); - let current_dir = std::env::current_dir()?; - let workspace_dir = regex::escape( - Url::from_directory_path(current_dir.join("..").join("..").canonicalize()?) - .unwrap() - .as_str(), - ); - - let filters = [(workspace_dir.as_str(), "file://[WORKSPACE_DIR]/")] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect::>(); - // Install the editable package. - uv_snapshot!(filters, command(&context) + uv_snapshot!(context.filters(), command(&context) .arg("-e") - .arg("../../scripts/packages/poetry_editable") - .current_dir(¤t_dir) - .env("CARGO_TARGET_DIR", "../../../target/target_install_editable"), @r###" + .arg(context.workspace_root.join("scripts/packages/poetry_editable")), @r###" success: true exit_code: 0 ----- stdout ----- @@ -756,24 +726,15 @@ fn install_editable() -> Result<()> { Installed 4 packages in [TIME] + anyio==4.3.0 + idna==3.6 - + poetry-editable==0.1.0 (from file://[WORKSPACE_DIR]/scripts/packages/poetry_editable) + + poetry-editable==0.1.0 (from file://[WORKSPACE]/scripts/packages/poetry_editable) + sniffio==1.3.1 "### ); // Install it again (no-op). - uv_snapshot!(filters, Command::new(get_bin()) - .arg("pip") - .arg("install") + uv_snapshot!(context.filters(), command(&context) .arg("-e") - .arg("../../scripts/packages/poetry_editable") - .arg("--strict") - .arg("--cache-dir") - .arg(context.cache_dir.path()) - .arg("--exclude-newer") - .arg(EXCLUDE_NEWER) - .env("VIRTUAL_ENV", context.venv.as_os_str()) - .env("CARGO_TARGET_DIR", "../../../target/target_install_editable"), @r###" + .arg(context.workspace_root.join("scripts/packages/poetry_editable")), @r###" success: true exit_code: 0 ----- stdout ----- @@ -784,19 +745,10 @@ fn install_editable() -> Result<()> { ); // Add another, non-editable dependency. - uv_snapshot!(filters, Command::new(get_bin()) - .arg("pip") - .arg("install") + uv_snapshot!(context.filters(), command(&context) .arg("-e") - .arg("../../scripts/packages/poetry_editable") - .arg("black") - .arg("--strict") - .arg("--cache-dir") - .arg(context.cache_dir.path()) - .arg("--exclude-newer") - .arg(EXCLUDE_NEWER) - .env("VIRTUAL_ENV", context.venv.as_os_str()) - .env("CARGO_TARGET_DIR", "../../../target/target_install_editable"), @r###" + .arg(context.workspace_root.join("scripts/packages/poetry_editable")) + .arg("black"), @r###" success: true exit_code: 0 ----- stdout ----- @@ -812,35 +764,19 @@ fn install_editable() -> Result<()> { + packaging==24.0 + pathspec==0.12.1 + platformdirs==4.2.0 - - poetry-editable==0.1.0 (from file://[WORKSPACE_DIR]/scripts/packages/poetry_editable) - + poetry-editable==0.1.0 (from file://[WORKSPACE_DIR]/scripts/packages/poetry_editable) + - poetry-editable==0.1.0 (from file://[WORKSPACE]/scripts/packages/poetry_editable) + + poetry-editable==0.1.0 (from file://[WORKSPACE]/scripts/packages/poetry_editable) "### ); - - Ok(()) } #[test] -fn install_editable_and_registry() -> Result<()> { +fn install_editable_and_registry() { let context = TestContext::new("3.12"); - let current_dir = std::env::current_dir()?; - let workspace_dir = regex::escape( - Url::from_directory_path(current_dir.join("..").join("..").canonicalize()?) - .unwrap() - .as_str(), - ); - - let filters: Vec<_> = [(workspace_dir.as_str(), "file://[WORKSPACE_DIR]/")] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect(); - // Install the registry-based version of Black. - uv_snapshot!(filters, command(&context) - .arg("black") - .current_dir(¤t_dir) - .env("CARGO_TARGET_DIR", "../../../target/target_install_editable"), @r###" + uv_snapshot!(context.filters(), command(&context) + .arg("black"), @r###" success: true exit_code: 0 ----- stdout ----- @@ -859,11 +795,9 @@ fn install_editable_and_registry() -> Result<()> { ); // Install the editable version of Black. This should remove the registry-based version. - uv_snapshot!(filters, command(&context) + uv_snapshot!(context.filters(), command(&context) .arg("-e") - .arg("../../scripts/packages/black_editable") - .current_dir(¤t_dir) - .env("CARGO_TARGET_DIR", "../../../target/target_install_editable"), @r###" + .arg(context.workspace_root.join("scripts/packages/black_editable")), @r###" success: true exit_code: 0 ----- stdout ----- @@ -873,17 +807,15 @@ fn install_editable_and_registry() -> Result<()> { Resolved 1 package in [TIME] Installed 1 package in [TIME] - black==24.3.0 - + black==0.1.0 (from file://[WORKSPACE_DIR]/scripts/packages/black_editable) + + black==0.1.0 (from file://[WORKSPACE]/scripts/packages/black_editable) "### ); // Re-install the registry-based version of Black. This should be a no-op, since we have a // version of Black installed (the editable version) that satisfies the requirements. - uv_snapshot!(filters, command(&context) + uv_snapshot!(context.filters(), command(&context) .arg("black") - .arg("--strict") - .current_dir(¤t_dir) - .env("CARGO_TARGET_DIR", "../../../target/target_install_editable"), @r###" + .arg("--strict"), @r###" success: true exit_code: 0 ----- stdout ----- @@ -893,7 +825,8 @@ fn install_editable_and_registry() -> Result<()> { "### ); - let filters2: Vec<_> = filters + let filters: Vec<_> = context + .filters() .into_iter() .chain([ // Remove colorama @@ -902,10 +835,8 @@ fn install_editable_and_registry() -> Result<()> { .collect(); // Re-install Black at a specific version. This should replace the editable version. - uv_snapshot!(filters2, command(&context) - .arg("black==23.10.0") - .current_dir(¤t_dir) - .env("CARGO_TARGET_DIR", "../../../target/target_install_editable"), @r###" + uv_snapshot!(filters, command(&context) + .arg("black==23.10.0"), @r###" success: true exit_code: 0 ----- stdout ----- @@ -914,38 +845,22 @@ fn install_editable_and_registry() -> Result<()> { Resolved 6 packages in [TIME] Downloaded 1 package in [TIME] Installed 1 package in [TIME] - - black==0.1.0 (from file://[WORKSPACE_DIR]/scripts/packages/black_editable) + - black==0.1.0 (from file://[WORKSPACE]/scripts/packages/black_editable) + black==23.10.0 "### ); - - Ok(()) } #[test] -fn install_editable_no_binary() -> Result<()> { +fn install_editable_no_binary() { let context = TestContext::new("3.12"); - let current_dir = std::env::current_dir()?; - let workspace_dir = regex::escape( - Url::from_directory_path(current_dir.join("..").join("..").canonicalize()?) - .unwrap() - .as_str(), - ); - - let filters = [(workspace_dir.as_str(), "file://[WORKSPACE_DIR]/")] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect::>(); - // Install the editable package with no-binary enabled - uv_snapshot!(filters, command(&context) + uv_snapshot!(context.filters(), command(&context) .arg("-e") - .arg("../../scripts/packages/black_editable") + .arg(context.workspace_root.join("scripts/packages/black_editable")) .arg("--no-binary") - .arg(":all:") - .current_dir(¤t_dir) - .env("CARGO_TARGET_DIR", "../../../target/target_install_editable"), @r###" + .arg(":all:"), @r###" success: true exit_code: 0 ----- stdout ----- @@ -954,11 +869,9 @@ fn install_editable_no_binary() -> Result<()> { Built 1 editable in [TIME] Resolved 1 package in [TIME] Installed 1 package in [TIME] - + black==0.1.0 (from file://[WORKSPACE_DIR]/scripts/packages/black_editable) + + black==0.1.0 (from file://[WORKSPACE]/scripts/packages/black_editable) "### ); - - Ok(()) } /// Install a source distribution that uses the `flit` build system, along with `flit` @@ -1198,15 +1111,16 @@ fn install_git_private_https_pat() { let context = TestContext::new("3.8"); let token = decode_token(READ_ONLY_GITHUB_TOKEN); - let mut filters = INSTA_FILTERS.to_vec(); - filters.insert(0, (&token, "***")); + let filters: Vec<_> = [(token.as_str(), "***")] + .into_iter() + .chain(context.filters()) + .collect(); - let mut command = command(&context); - command.arg(format!( + let package = format!( "uv-private-pypackage @ git+https://{token}@github.com/astral-test/uv-private-pypackage" - )); + ); - uv_snapshot!(filters, command + uv_snapshot!(filters, command(&context).arg(package) , @r###" success: true exit_code: 0 @@ -1229,8 +1143,11 @@ fn install_git_private_https_pat_at_ref() { let context = TestContext::new("3.8"); let token = decode_token(READ_ONLY_GITHUB_TOKEN); - let mut filters = INSTA_FILTERS.to_vec(); - filters.insert(0, (&token, "***")); + let mut filters: Vec<_> = [(token.as_str(), "***")] + .into_iter() + .chain(context.filters()) + .collect(); + filters.push((r"git\+https://", "")); // A user is _required_ on Windows @@ -1241,10 +1158,9 @@ fn install_git_private_https_pat_at_ref() { "" }; - let mut command = command(&context); - command.arg(format!("uv-private-pypackage @ git+https://{user}{token}@github.com/astral-test/uv-private-pypackage@6c09ce9ae81f50670a60abd7d95f30dd416d00ac")); - - uv_snapshot!(filters, command, @r###" + let package = format!("uv-private-pypackage @ git+https://{user}{token}@github.com/astral-test/uv-private-pypackage@6c09ce9ae81f50670a60abd7d95f30dd416d00ac"); + uv_snapshot!(filters, command(&context) + .arg(package), @r###" success: true exit_code: 0 ----- stdout ----- @@ -1272,13 +1188,12 @@ fn install_git_private_https_pat_and_username() { let token = decode_token(READ_ONLY_GITHUB_TOKEN); let user = "astral-test-bot"; - let mut filters = INSTA_FILTERS.to_vec(); - filters.insert(0, (&token, "***")); + let filters: Vec<_> = [(token.as_str(), "***")] + .into_iter() + .chain(context.filters()) + .collect(); - let mut command = command(&context); - command.arg(format!("uv-private-pypackage @ git+https://{user}:{token}@github.com/astral-test/uv-private-pypackage")); - - uv_snapshot!(filters, command + uv_snapshot!(filters, command(&context).arg(format!("uv-private-pypackage @ git+https://{user}:{token}@github.com/astral-test/uv-private-pypackage")) , @r###" success: true exit_code: 0 @@ -1376,14 +1291,15 @@ fn reinstall_no_binary() { // With `--reinstall`, `--no-binary` should have an affect let filters = if cfg!(windows) { // Remove the colorama count on windows - INSTA_FILTERS - .iter() - .copied() + context + .filters() + .into_iter() .chain([("Resolved 8 packages", "Resolved 7 packages")]) .collect() } else { - INSTA_FILTERS.to_vec() + context.filters() }; + let mut command = crate::command(&context); command .arg("anyio") @@ -2012,34 +1928,13 @@ fn launcher_with_symlink() -> Result<()> { } #[test] -#[cfg(unix)] -fn config_settings() -> Result<()> { +fn config_settings() { let context = TestContext::new("3.12"); - let current_dir = std::env::current_dir()?; - let workspace_dir = regex::escape( - Url::from_directory_path(current_dir.join("..").join("..").canonicalize()?) - .unwrap() - .as_str(), - ); - - let filters = [(workspace_dir.as_str(), "file://[WORKSPACE_DIR]/")] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect::>(); - // Install the editable package. - uv_snapshot!(filters, Command::new(get_bin()) - .arg("pip") - .arg("install") + uv_snapshot!(context.filters(), command(&context) .arg("-e") - .arg("../../scripts/packages/setuptools_editable") - .arg("--cache-dir") - .arg(context.cache_dir.path()) - .arg("--exclude-newer") - .arg(EXCLUDE_NEWER) - .env("VIRTUAL_ENV", context.venv.as_os_str()) - .env("CARGO_TARGET_DIR", "../../../target/target_install_editable"), @r###" + .arg(context.workspace_root.join("scripts/packages/setuptools_editable")), @r###" success: true exit_code: 0 ----- stdout ----- @@ -2050,45 +1945,25 @@ fn config_settings() -> Result<()> { Downloaded 1 package in [TIME] Installed 2 packages in [TIME] + iniconfig==2.0.0 - + setuptools-editable==0.1.0 (from file://[WORKSPACE_DIR]/scripts/packages/setuptools_editable) + + setuptools-editable==0.1.0 (from file://[WORKSPACE]/scripts/packages/setuptools_editable) "### ); // When installed without `--editable_mode=compat`, the `finder.py` file should be present. let finder = context - .venv - .join("lib/python3.12/site-packages") + .site_packages() .join("__editable___setuptools_editable_0_1_0_finder.py"); assert!(finder.exists()); // Install the editable package with `--editable_mode=compat`. let context = TestContext::new("3.12"); - let current_dir = std::env::current_dir()?; - let workspace_dir = regex::escape( - Url::from_directory_path(current_dir.join("..").join("..").canonicalize()?) - .unwrap() - .as_str(), - ); - - let filters = [(workspace_dir.as_str(), "file://[WORKSPACE_DIR]/")] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect::>(); - - uv_snapshot!(filters, Command::new(get_bin()) - .arg("pip") - .arg("install") + uv_snapshot!(context.filters(), command(&context) .arg("-e") - .arg("../../scripts/packages/setuptools_editable") + .arg(context.workspace_root.join("scripts/packages/setuptools_editable")) .arg("-C") .arg("editable_mode=compat") - .arg("--cache-dir") - .arg(context.cache_dir.path()) - .arg("--exclude-newer") - .arg(EXCLUDE_NEWER) - .env("VIRTUAL_ENV", context.venv.as_os_str()) - .env("CARGO_TARGET_DIR", "../../../target/target_install_editable"), @r###" + , @r###" success: true exit_code: 0 ----- stdout ----- @@ -2099,23 +1974,19 @@ fn config_settings() -> Result<()> { Downloaded 1 package in [TIME] Installed 2 packages in [TIME] + iniconfig==2.0.0 - + setuptools-editable==0.1.0 (from file://[WORKSPACE_DIR]/scripts/packages/setuptools_editable) + + setuptools-editable==0.1.0 (from file://[WORKSPACE]/scripts/packages/setuptools_editable) "### ); // When installed without `--editable_mode=compat`, the `finder.py` file should _not_ be present. let finder = context - .venv - .join("lib/python3.12/site-packages") + .site_packages() .join("__editable___setuptools_editable_0_1_0_finder.py"); assert!(!finder.exists()); - - Ok(()) } /// Reinstall a duplicate package in a virtual environment. #[test] -#[cfg(unix)] fn reinstall_duplicate() -> Result<()> { use crate::common::copy_dir_all; @@ -2153,12 +2024,8 @@ fn reinstall_duplicate() -> Result<()> { // Copy the virtual environment to a new location. copy_dir_all( - context2 - .venv - .join("lib/python3.12/site-packages/pip-22.1.1.dist-info"), - context1 - .venv - .join("lib/python3.12/site-packages/pip-22.1.1.dist-info"), + context2.site_packages().join("pip-22.1.1.dist-info"), + context1.site_packages().join("pip-22.1.1.dist-info"), )?; // Run `pip install`. @@ -2223,7 +2090,8 @@ fn invalidate_editable_on_change() -> Result<()> { let context = TestContext::new("3.12"); // Create an editable package. - let editable_dir = assert_fs::TempDir::new()?; + let editable_dir = context.temp_dir.child("editable"); + editable_dir.create_dir_all()?; let pyproject_toml = editable_dir.child("pyproject.toml"); pyproject_toml.write_str( r#"[project] @@ -2236,12 +2104,7 @@ requires-python = ">=3.8" "#, )?; - let filters = [(r"\(from file://.*\)", "(from [WORKSPACE_DIR])")] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect::>(); - - uv_snapshot!(filters, command(&context) + uv_snapshot!(context.filters(), command(&context) .arg("--editable") .arg(editable_dir.path()), @r###" success: true @@ -2254,14 +2117,14 @@ requires-python = ">=3.8" Downloaded 3 packages in [TIME] Installed 4 packages in [TIME] + anyio==4.0.0 - + example==0.0.0 (from [WORKSPACE_DIR]) + + example==0.0.0 (from file://[TEMP_DIR]/editable) + idna==3.6 + sniffio==1.3.1 "### ); // Re-installing should be a no-op. - uv_snapshot!(filters, command(&context) + uv_snapshot!(context.filters(), command(&context) .arg("--editable") .arg(editable_dir.path()), @r###" success: true @@ -2286,7 +2149,7 @@ requires-python = ">=3.8" )?; // Re-installing should update the package. - uv_snapshot!(filters, command(&context) + uv_snapshot!(context.filters(), command(&context) .arg("--editable") .arg(editable_dir.path()), @r###" success: true @@ -2300,8 +2163,8 @@ requires-python = ">=3.8" Installed 2 packages in [TIME] - anyio==4.0.0 + anyio==3.7.1 - - example==0.0.0 (from [WORKSPACE_DIR]) - + example==0.0.0 (from [WORKSPACE_DIR]) + - example==0.0.0 (from file://[TEMP_DIR]/editable) + + example==0.0.0 (from file://[TEMP_DIR]/editable) "### ); @@ -2313,7 +2176,8 @@ fn invalidate_editable_dynamic() -> Result<()> { let context = TestContext::new("3.12"); // Create an editable package with dynamic metadata - let editable_dir = assert_fs::TempDir::new()?; + let editable_dir = context.temp_dir.child("editable"); + editable_dir.create_dir_all()?; let pyproject_toml = editable_dir.child("pyproject.toml"); pyproject_toml.write_str( r#" @@ -2331,12 +2195,7 @@ dependencies = {file = ["requirements.txt"]} let requirements_txt = editable_dir.child("requirements.txt"); requirements_txt.write_str("anyio==4.0.0")?; - let filters = [(r"\(from file://.*\)", "(from [WORKSPACE_DIR])")] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect::>(); - - uv_snapshot!(filters, command(&context) + uv_snapshot!(context.filters(), command(&context) .arg("--editable") .arg(editable_dir.path()), @r###" success: true @@ -2349,14 +2208,14 @@ dependencies = {file = ["requirements.txt"]} Downloaded 3 packages in [TIME] Installed 4 packages in [TIME] + anyio==4.0.0 - + example==0.1.0 (from [WORKSPACE_DIR]) + + example==0.1.0 (from file://[TEMP_DIR]/editable) + idna==3.6 + sniffio==1.3.1 "### ); // Re-installing should re-install. - uv_snapshot!(filters, command(&context) + uv_snapshot!(context.filters(), command(&context) .arg("--editable") .arg(editable_dir.path()), @r###" success: true @@ -2367,8 +2226,8 @@ dependencies = {file = ["requirements.txt"]} Built 1 editable in [TIME] Resolved 4 packages in [TIME] Installed 1 package in [TIME] - - example==0.1.0 (from [WORKSPACE_DIR]) - + example==0.1.0 (from [WORKSPACE_DIR]) + - example==0.1.0 (from file://[TEMP_DIR]/editable) + + example==0.1.0 (from file://[TEMP_DIR]/editable) "### ); @@ -2376,7 +2235,7 @@ dependencies = {file = ["requirements.txt"]} requirements_txt.write_str("anyio==3.7.1")?; // Re-installing should update the package. - uv_snapshot!(filters, command(&context) + uv_snapshot!(context.filters(), command(&context) .arg("--editable") .arg(editable_dir.path()), @r###" success: true @@ -2390,8 +2249,8 @@ dependencies = {file = ["requirements.txt"]} Installed 2 packages in [TIME] - anyio==4.0.0 + anyio==3.7.1 - - example==0.1.0 (from [WORKSPACE_DIR]) - + example==0.1.0 (from [WORKSPACE_DIR]) + - example==0.1.0 (from file://[TEMP_DIR]/editable) + + example==0.1.0 (from file://[TEMP_DIR]/editable) "### ); @@ -2403,7 +2262,8 @@ fn invalidate_path_on_change() -> Result<()> { let context = TestContext::new("3.12"); // Create a local package. - let editable_dir = assert_fs::TempDir::new()?; + let editable_dir = context.temp_dir.child("editable"); + editable_dir.create_dir_all()?; let pyproject_toml = editable_dir.child("pyproject.toml"); pyproject_toml.write_str( r#"[project] @@ -2416,12 +2276,7 @@ requires-python = ">=3.8" "#, )?; - let filters = [(r"\(from file://.*\)", "(from [WORKSPACE_DIR])")] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect::>(); - - uv_snapshot!(filters, command(&context) + uv_snapshot!(context.filters(), command(&context) .arg("example @ .") .current_dir(editable_dir.path()), @r###" success: true @@ -2433,14 +2288,14 @@ requires-python = ">=3.8" Downloaded 4 packages in [TIME] Installed 4 packages in [TIME] + anyio==4.0.0 - + example==0.0.0 (from [WORKSPACE_DIR]) + + example==0.0.0 (from file://[TEMP_DIR]/editable) + idna==3.6 + sniffio==1.3.1 "### ); // Re-installing should be a no-op. - uv_snapshot!(filters, command(&context) + uv_snapshot!(context.filters(), command(&context) .arg("example @ .") .current_dir(editable_dir.path()), @r###" success: true @@ -2465,7 +2320,7 @@ requires-python = ">=3.8" )?; // Re-installing should update the package. - uv_snapshot!(filters, command(&context) + uv_snapshot!(context.filters(), command(&context) .arg("example @ .") .current_dir(editable_dir.path()), @r###" success: true @@ -2478,8 +2333,8 @@ requires-python = ">=3.8" Installed 2 packages in [TIME] - anyio==4.0.0 + anyio==3.7.1 - - example==0.0.0 (from [WORKSPACE_DIR]) - + example==0.0.0 (from [WORKSPACE_DIR]) + - example==0.0.0 (from file://[TEMP_DIR]/editable) + + example==0.0.0 (from file://[TEMP_DIR]/editable) "### ); @@ -2491,7 +2346,8 @@ requires-python = ">=3.8" fn editable_url_with_marker() -> Result<()> { let context = TestContext::new("3.12"); - let editable_dir = assert_fs::TempDir::new()?; + let editable_dir = context.temp_dir.child("editable"); + editable_dir.create_dir_all()?; let pyproject_toml = editable_dir.child("pyproject.toml"); pyproject_toml.write_str( r#" @@ -2506,12 +2362,7 @@ requires-python = ">=3.11,<3.13" "#, )?; - let filters = [(r"\(from file://.*\)", "(from [WORKSPACE_DIR])")] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect::>(); - - uv_snapshot!(filters, command(&context) + uv_snapshot!(context.filters(), command(&context) .arg("--editable") .arg(editable_dir.path()), @r###" success: true @@ -2524,7 +2375,7 @@ requires-python = ">=3.11,<3.13" Downloaded 3 packages in [TIME] Installed 4 packages in [TIME] + anyio==4.0.0 - + example==0.1.0 (from [WORKSPACE_DIR]) + + example==0.1.0 (from file://[TEMP_DIR]/editable) + idna==3.6 + sniffio==1.3.1 "### @@ -2539,7 +2390,8 @@ fn requires_python_editable() -> Result<()> { let context = TestContext::new("3.12"); // Create an editable package with a `Requires-Python` constraint that is not met. - let editable_dir = assert_fs::TempDir::new()?; + let editable_dir = context.temp_dir.child("editable"); + editable_dir.create_dir_all()?; let pyproject_toml = editable_dir.child("pyproject.toml"); pyproject_toml.write_str( r#"[project] @@ -2576,7 +2428,7 @@ fn no_build_isolation() -> Result<()> { // We expect the build to fail, because `setuptools` is not installed. let filters = std::iter::once((r"exit code: 1", "exit status: 1")) - .chain(INSTA_FILTERS.to_vec()) + .chain(context.filters()) .collect::>(); uv_snapshot!(filters, command(&context) .arg("-r") @@ -2987,7 +2839,8 @@ fn requires_python_direct_url() -> Result<()> { let context = TestContext::new("3.12"); // Create an editable package with a `Requires-Python` constraint that is not met. - let editable_dir = assert_fs::TempDir::new()?; + let editable_dir = context.temp_dir.child("editable"); + editable_dir.create_dir_all()?; let pyproject_toml = editable_dir.child("pyproject.toml"); pyproject_toml.write_str( r#"[project] @@ -3149,32 +3002,15 @@ fn install_site_packages_mtime_updated() -> Result<()> { /// entry (because we want to ignore the entire cache from outside), ignoring all python source /// files. #[test] -fn deptry_gitignore() -> Result<()> { +fn deptry_gitignore() { let context = TestContext::new("3.12"); - let project_root = current_dir()? - .parent() - .unwrap() - .parent() - .unwrap() - .to_path_buf(); - let source_dist_dir = project_root - .join("scripts") - .join("packages") - .join("deptry_reproducer"); - let filter_path = regex::escape( - Url::from_directory_path(source_dist_dir.simplified_display().to_string()) - .unwrap() - .to_string() - .trim_end_matches('/'), - ); - let filters: Vec<_> = [(filter_path.as_str(), "[SOURCE_DIST_DIR]")] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect(); + let source_dist_dir = context + .workspace_root + .join("scripts/packages/deptry_reproducer"); - uv_snapshot!(filters, command(&context) - .arg(format!("deptry_reproducer @ {}/deptry_reproducer-0.1.0.tar.gz", source_dist_dir.simplified_display())) + uv_snapshot!(context.filters(), command(&context) + .arg(format!("deptry_reproducer @ {}", source_dist_dir.join("deptry_reproducer-0.1.0.tar.gz").simplified_display())) .arg("--strict") .current_dir(source_dist_dir), @r###" success: true @@ -3186,7 +3022,7 @@ fn deptry_gitignore() -> Result<()> { Downloaded 3 packages in [TIME] Installed 3 packages in [TIME] + cffi==1.16.0 - + deptry-reproducer==0.1.0 (from [SOURCE_DIST_DIR]/deptry_reproducer-0.1.0.tar.gz) + + deptry-reproducer==0.1.0 (from file://[WORKSPACE]/scripts/packages/deptry_reproducer/deptry_reproducer-0.1.0.tar.gz) + pycparser==2.21 "### ); @@ -3195,6 +3031,4 @@ fn deptry_gitignore() -> Result<()> { context .assert_command("import deptry_reproducer.foo") .success(); - - Ok(()) } diff --git a/crates/uv/tests/pip_install_scenarios.rs b/crates/uv/tests/pip_install_scenarios.rs index 29ec34839..e9e85a949 100644 --- a/crates/uv/tests/pip_install_scenarios.rs +++ b/crates/uv/tests/pip_install_scenarios.rs @@ -11,7 +11,7 @@ use std::process::Command; use assert_cmd::assert::Assert; use assert_cmd::prelude::*; -use common::{venv_to_interpreter, INSTA_FILTERS}; +use common::venv_to_interpreter; use crate::common::{get_bin, uv_snapshot, TestContext}; @@ -79,7 +79,7 @@ fn requires_package_does_not_exist() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"requires-package-does-not-exist-", "package-")); uv_snapshot!(filters, command(&context) @@ -118,7 +118,7 @@ fn requires_exact_version_does_not_exist() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"requires-exact-version-does-not-exist-", "package-")); uv_snapshot!(filters, command(&context) @@ -159,7 +159,7 @@ fn requires_greater_version_does_not_exist() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"requires-greater-version-does-not-exist-", "package-")); uv_snapshot!(filters, command(&context) @@ -201,7 +201,7 @@ fn requires_less_version_does_not_exist() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"requires-less-version-does-not-exist-", "package-")); uv_snapshot!(filters, command(&context) @@ -242,7 +242,7 @@ fn transitive_requires_package_does_not_exist() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"transitive-requires-package-does-not-exist-", "package-")); uv_snapshot!(filters, command(&context) @@ -283,7 +283,7 @@ fn excluded_only_version() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"excluded-only-version-", "package-")); uv_snapshot!(filters, command(&context) @@ -338,7 +338,7 @@ fn excluded_only_compatible_version() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"excluded-only-compatible-version-", "package-")); uv_snapshot!(filters, command(&context) @@ -440,7 +440,7 @@ fn dependency_excludes_range_of_compatible_versions() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push(( r"dependency-excludes-range-of-compatible-versions-", "package-", @@ -501,7 +501,7 @@ fn dependency_excludes_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-existent package +/// `a` are incompatible for another reason e.g. dependency on non-existant package /// `d`. /// /// ```text @@ -565,7 +565,7 @@ fn dependency_excludes_non_contiguous_range_of_compatible_versions() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push(( r"dependency-excludes-non-contiguous-range-of-compatible-versions-", "package-", @@ -646,7 +646,7 @@ fn extra_required() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"extra-required-", "package-")); uv_snapshot!(filters, command(&context) @@ -696,7 +696,7 @@ fn missing_extra() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"missing-extra-", "package-")); uv_snapshot!(filters, command(&context) @@ -746,7 +746,7 @@ fn multiple_extras_required() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"multiple-extras-required-", "package-")); uv_snapshot!(filters, command(&context) @@ -826,7 +826,7 @@ fn all_extras_required() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"all-extras-required-", "package-")); uv_snapshot!(filters, command(&context) @@ -894,7 +894,7 @@ fn extra_incompatible_with_extra() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"extra-incompatible-with-extra-", "package-")); uv_snapshot!(filters, command(&context) @@ -948,7 +948,7 @@ fn extra_incompatible_with_extra_not_requested() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"extra-incompatible-with-extra-not-requested-", "package-")); uv_snapshot!(filters, command(&context) @@ -1009,7 +1009,7 @@ fn extra_incompatible_with_root() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"extra-incompatible-with-root-", "package-")); uv_snapshot!(filters, command(&context) @@ -1068,7 +1068,7 @@ fn extra_does_not_exist_backtrack() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"extra-does-not-exist-backtrack-", "package-")); uv_snapshot!(filters, command(&context) @@ -1115,7 +1115,7 @@ fn direct_incompatible_versions() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"direct-incompatible-versions-", "package-")); uv_snapshot!(filters, command(&context) @@ -1168,7 +1168,7 @@ fn transitive_incompatible_with_root_version() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"transitive-incompatible-with-root-version-", "package-")); uv_snapshot!(filters, command(&context) @@ -1226,7 +1226,7 @@ fn transitive_incompatible_with_transitive() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"transitive-incompatible-with-transitive-", "package-")); uv_snapshot!(filters, command(&context) @@ -1274,7 +1274,7 @@ fn local_simple() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"local-simple-", "package-")); uv_snapshot!(filters, command(&context) @@ -1313,7 +1313,7 @@ fn local_not_used_with_sdist() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"local-not-used-with-sdist-", "package-")); uv_snapshot!(filters, command(&context) @@ -1360,7 +1360,7 @@ fn local_used_without_sdist() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"local-used-without-sdist-", "package-")); uv_snapshot!(filters, command(&context) @@ -1405,7 +1405,7 @@ fn local_not_latest() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"local-not-latest-", "package-")); uv_snapshot!(filters, command(&context) @@ -1454,7 +1454,7 @@ fn local_transitive() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"local-transitive-", "package-")); uv_snapshot!(filters, command(&context) @@ -1512,7 +1512,7 @@ fn local_transitive_greater_than() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"local-transitive-greater-than-", "package-")); uv_snapshot!(filters, command(&context) @@ -1565,7 +1565,7 @@ fn local_transitive_greater_than_or_equal() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"local-transitive-greater-than-or-equal-", "package-")); uv_snapshot!(filters, command(&context) @@ -1623,7 +1623,7 @@ fn local_transitive_less_than() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"local-transitive-less-than-", "package-")); uv_snapshot!(filters, command(&context) @@ -1676,7 +1676,7 @@ fn local_transitive_less_than_or_equal() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"local-transitive-less-than-or-equal-", "package-")); uv_snapshot!(filters, command(&context) @@ -1734,7 +1734,7 @@ fn local_transitive_confounding() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"local-transitive-confounding-", "package-")); uv_snapshot!(filters, command(&context) @@ -1782,7 +1782,7 @@ fn local_transitive_conflicting() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"local-transitive-conflicting-", "package-")); uv_snapshot!(filters, command(&context) @@ -1841,7 +1841,7 @@ fn local_transitive_backtrack() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"local-transitive-backtrack-", "package-")); uv_snapshot!(filters, command(&context) @@ -1892,7 +1892,7 @@ fn local_greater_than() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"local-greater-than-", "package-")); uv_snapshot!(filters, command(&context) @@ -1927,7 +1927,7 @@ fn local_greater_than_or_equal() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"local-greater-than-or-equal-", "package-")); uv_snapshot!(filters, command(&context) @@ -1970,7 +1970,7 @@ fn local_less_than() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"local-less-than-", "package-")); uv_snapshot!(filters, command(&context) @@ -2005,7 +2005,7 @@ fn local_less_than_or_equal() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"local-less-than-or-equal-", "package-")); uv_snapshot!(filters, command(&context) @@ -2045,7 +2045,7 @@ fn post_simple() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"post-simple-", "package-")); uv_snapshot!(filters, command(&context) @@ -2080,7 +2080,7 @@ fn post_greater_than_or_equal() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"post-greater-than-or-equal-", "package-")); uv_snapshot!(filters, command(&context) @@ -2123,7 +2123,7 @@ fn post_greater_than() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"post-greater-than-", "package-")); uv_snapshot!(filters, command(&context) @@ -2160,7 +2160,7 @@ fn post_greater_than_post() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"post-greater-than-post-", "package-")); uv_snapshot!(filters, command(&context) @@ -2206,7 +2206,7 @@ fn post_greater_than_or_equal_post() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"post-greater-than-or-equal-post-", "package-")); uv_snapshot!(filters, command(&context) @@ -2249,7 +2249,7 @@ fn post_less_than_or_equal() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"post-less-than-or-equal-", "package-")); uv_snapshot!(filters, command(&context) @@ -2288,7 +2288,7 @@ fn post_less_than() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"post-less-than-", "package-")); uv_snapshot!(filters, command(&context) @@ -2325,7 +2325,7 @@ fn post_local_greater_than() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"post-local-greater-than-", "package-")); uv_snapshot!(filters, command(&context) @@ -2366,7 +2366,7 @@ fn post_local_greater_than_post() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"post-local-greater-than-post-", "package-")); uv_snapshot!(filters, command(&context) @@ -2407,7 +2407,7 @@ fn post_equal_not_available() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"post-equal-not-available-", "package-")); uv_snapshot!(filters, command(&context) @@ -2448,7 +2448,7 @@ fn post_equal_available() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"post-equal-available-", "package-")); uv_snapshot!(filters, command(&context) @@ -2494,7 +2494,7 @@ fn post_greater_than_post_not_available() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"post-greater-than-post-not-available-", "package-")); uv_snapshot!(filters, command(&context) @@ -2534,7 +2534,7 @@ fn package_only_prereleases() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"package-only-prereleases-", "package-")); uv_snapshot!(filters, command(&context) @@ -2580,7 +2580,7 @@ fn package_only_prereleases_in_range() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"package-only-prereleases-in-range-", "package-")); uv_snapshot!(filters, command(&context) @@ -2626,7 +2626,7 @@ fn requires_package_only_prereleases_in_range_global_opt_in() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push(( r"requires-package-only-prereleases-in-range-global-opt-in-", "package-", @@ -2674,7 +2674,7 @@ fn requires_package_prerelease_and_final_any() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"requires-package-prerelease-and-final-any-", "package-")); uv_snapshot!(filters, command(&context) @@ -2723,7 +2723,7 @@ fn package_prerelease_specified_only_final_available() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push(( r"package-prerelease-specified-only-final-available-", "package-", @@ -2774,7 +2774,7 @@ fn package_prerelease_specified_only_prerelease_available() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push(( r"package-prerelease-specified-only-prerelease-available-", "package-", @@ -2827,7 +2827,7 @@ fn package_prerelease_specified_mixed_available() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"package-prerelease-specified-mixed-available-", "package-")); uv_snapshot!(filters, command(&context) @@ -2876,7 +2876,7 @@ fn package_multiple_prereleases_kinds() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"package-multiple-prereleases-kinds-", "package-")); uv_snapshot!(filters, command(&context) @@ -2923,7 +2923,7 @@ fn package_multiple_prereleases_numbers() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"package-multiple-prereleases-numbers-", "package-")); uv_snapshot!(filters, command(&context) @@ -2971,7 +2971,7 @@ fn transitive_package_only_prereleases() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"transitive-package-only-prereleases-", "package-")); uv_snapshot!(filters, command(&context) @@ -3028,7 +3028,7 @@ fn transitive_package_only_prereleases_in_range() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"transitive-package-only-prereleases-in-range-", "package-")); uv_snapshot!(filters, command(&context) @@ -3082,7 +3082,7 @@ fn transitive_package_only_prereleases_in_range_opt_in() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push(( r"transitive-package-only-prereleases-in-range-opt-in-", "package-", @@ -3149,7 +3149,7 @@ fn transitive_prerelease_and_stable_dependency() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"transitive-prerelease-and-stable-dependency-", "package-")); uv_snapshot!(filters, command(&context) @@ -3214,7 +3214,7 @@ fn transitive_prerelease_and_stable_dependency_opt_in() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push(( r"transitive-prerelease-and-stable-dependency-opt-in-", "package-", @@ -3313,7 +3313,7 @@ fn transitive_prerelease_and_stable_dependency_many_versions() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push(( r"transitive-prerelease-and-stable-dependency-many-versions-", "package-", @@ -3397,7 +3397,7 @@ fn transitive_prerelease_and_stable_dependency_many_versions_holes() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push(( r"transitive-prerelease-and-stable-dependency-many-versions-holes-", "package-", @@ -3465,7 +3465,7 @@ fn package_only_prereleases_boundary() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"package-only-prereleases-boundary-", "package-")); uv_snapshot!(filters, command(&context) @@ -3483,7 +3483,7 @@ fn package_only_prereleases_boundary() { "###); // Since there are only prerelease versions of `a` available, a prerelease is - // allowed. Since the user did not explicitly request a pre-release, pre-releases at + // allowed. Since the user did not explictly request a pre-release, pre-releases at // the boundary should not be selected. assert_installed( &context.venv, @@ -3513,7 +3513,7 @@ fn package_prereleases_boundary() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"package-prereleases-boundary-", "package-")); uv_snapshot!(filters, command(&context) @@ -3561,7 +3561,7 @@ fn package_prereleases_global_boundary() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"package-prereleases-global-boundary-", "package-")); uv_snapshot!(filters, command(&context) @@ -3612,7 +3612,7 @@ fn package_prereleases_specifier_boundary() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"package-prereleases-specifier-boundary-", "package-")); uv_snapshot!(filters, command(&context) @@ -3657,7 +3657,7 @@ fn python_version_does_not_exist() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"python-version-does-not-exist-", "package-")); uv_snapshot!(filters, command(&context) @@ -3699,7 +3699,7 @@ fn python_less_than_current() { let context = TestContext::new("3.9"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"python-less-than-current-", "package-")); uv_snapshot!(filters, command(&context) @@ -3741,7 +3741,7 @@ fn python_greater_than_current() { let context = TestContext::new("3.9"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"python-greater-than-current-", "package-")); uv_snapshot!(filters, command(&context) @@ -3783,7 +3783,7 @@ fn python_greater_than_current_patch() { let context = TestContext::new("3.8.12"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"python-greater-than-current-patch-", "package-")); uv_snapshot!(filters, command(&context) @@ -3847,7 +3847,7 @@ fn python_greater_than_current_many() { let context = TestContext::new("3.9"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"python-greater-than-current-many-", "package-")); uv_snapshot!(filters, command(&context) @@ -3896,7 +3896,7 @@ fn python_greater_than_current_backtrack() { let context = TestContext::new("3.9"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"python-greater-than-current-backtrack-", "package-")); uv_snapshot!(filters, command(&context) @@ -3947,7 +3947,7 @@ fn python_greater_than_current_excluded() { let context = TestContext::new("3.9"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"python-greater-than-current-excluded-", "package-")); uv_snapshot!(filters, command(&context) @@ -4003,7 +4003,7 @@ fn specific_tag_and_default() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"specific-tag-and-default-", "package-")); uv_snapshot!(filters, command(&context) @@ -4038,7 +4038,7 @@ fn only_wheels() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"only-wheels-", "package-")); uv_snapshot!(filters, command(&context) @@ -4073,7 +4073,7 @@ fn no_wheels() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"no-wheels-", "package-")); uv_snapshot!(filters, command(&context) @@ -4108,7 +4108,7 @@ fn no_wheels_with_matching_platform() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"no-wheels-with-matching-platform-", "package-")); uv_snapshot!(filters, command(&context) @@ -4144,7 +4144,7 @@ fn no_sdist_no_wheels_with_matching_platform() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"no-sdist-no-wheels-with-matching-platform-", "package-")); uv_snapshot!(filters, command(&context) @@ -4185,7 +4185,7 @@ fn no_sdist_no_wheels_with_matching_python() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"no-sdist-no-wheels-with-matching-python-", "package-")); uv_snapshot!(filters, command(&context) @@ -4226,7 +4226,7 @@ fn no_sdist_no_wheels_with_matching_abi() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"no-sdist-no-wheels-with-matching-abi-", "package-")); uv_snapshot!(filters, command(&context) @@ -4267,7 +4267,7 @@ fn no_wheels_no_build() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"no-wheels-no-build-", "package-")); uv_snapshot!(filters, command(&context) @@ -4306,7 +4306,7 @@ fn only_wheels_no_binary() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"only-wheels-no-binary-", "package-")); uv_snapshot!(filters, command(&context) @@ -4345,7 +4345,7 @@ fn no_build() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"no-build-", "package-")); uv_snapshot!(filters, command(&context) @@ -4385,7 +4385,7 @@ fn no_binary() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"no-binary-", "package-")); uv_snapshot!(filters, command(&context) @@ -4425,7 +4425,7 @@ fn package_only_yanked() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"package-only-yanked-", "package-")); uv_snapshot!(filters, command(&context) @@ -4464,7 +4464,7 @@ fn package_only_yanked_in_range() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"package-only-yanked-in-range-", "package-")); uv_snapshot!(filters, command(&context) @@ -4511,7 +4511,7 @@ fn requires_package_yanked_and_unyanked_any() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"requires-package-yanked-and-unyanked-any-", "package-")); uv_snapshot!(filters, command(&context) @@ -4559,7 +4559,7 @@ fn package_yanked_specified_mixed_available() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"package-yanked-specified-mixed-available-", "package-")); uv_snapshot!(filters, command(&context) @@ -4607,7 +4607,7 @@ fn transitive_package_only_yanked() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"transitive-package-only-yanked-", "package-")); uv_snapshot!(filters, command(&context) @@ -4656,7 +4656,7 @@ fn transitive_package_only_yanked_in_range() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"transitive-package-only-yanked-in-range-", "package-")); uv_snapshot!(filters, command(&context) @@ -4711,7 +4711,7 @@ fn transitive_package_only_yanked_in_range_opt_in() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push(( r"transitive-package-only-yanked-in-range-opt-in-", "package-", @@ -4779,7 +4779,7 @@ fn transitive_yanked_and_unyanked_dependency() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"transitive-yanked-and-unyanked-dependency-", "package-")); uv_snapshot!(filters, command(&context) @@ -4841,7 +4841,7 @@ fn transitive_yanked_and_unyanked_dependency_opt_in() { let context = TestContext::new("3.8"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push(( r"transitive-yanked-and-unyanked-dependency-opt-in-", "package-", diff --git a/crates/uv/tests/pip_list.rs b/crates/uv/tests/pip_list.rs index e7e17bf2d..9b545ee2c 100644 --- a/crates/uv/tests/pip_list.rs +++ b/crates/uv/tests/pip_list.rs @@ -3,11 +3,10 @@ use std::process::Command; use anyhow::Result; use assert_fs::fixture::PathChild; use assert_fs::fixture::{FileTouch, FileWriteStr}; -use url::Url; use common::uv_snapshot; -use crate::common::{get_bin, TestContext, EXCLUDE_NEWER, INSTA_FILTERS}; +use crate::common::{get_bin, TestContext, EXCLUDE_NEWER}; mod common; @@ -101,25 +100,13 @@ fn list_single_no_editable() -> Result<()> { } #[test] -fn list_editable() -> Result<()> { +fn list_editable() { let context = TestContext::new("3.12"); - let current_dir = std::env::current_dir()?; - let workspace_dir = - Url::from_directory_path(current_dir.join("..").join("..").canonicalize()?).unwrap(); - let workspace_dir_re = regex::escape(workspace_dir.as_str()); - - let filters = [(workspace_dir_re.as_str(), "file://[WORKSPACE_DIR]/")] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect::>(); - // Install the editable package. - uv_snapshot!(filters, install_command(&context) + uv_snapshot!(context.filters(), install_command(&context) .arg("-e") - .arg("../../scripts/packages/poetry_editable") - .current_dir(¤t_dir) - .env("CARGO_TARGET_DIR", "../../../target/target_install_editable"), @r###" + .arg(context.workspace_root.join("scripts/packages/poetry_editable")), @r###" success: true exit_code: 0 ----- stdout ----- @@ -131,92 +118,47 @@ fn list_editable() -> Result<()> { Installed 4 packages in [TIME] + anyio==4.3.0 + idna==3.6 - + poetry-editable==0.1.0 (from file://[WORKSPACE_DIR]/scripts/packages/poetry_editable) + + poetry-editable==0.1.0 (from file://[WORKSPACE]/scripts/packages/poetry_editable) + sniffio==1.3.1 "### ); - // Account for difference length workspace dir - let prefix = if cfg!(windows) { "file:///" } else { "file://" }; - - // Origin of lengths used below: - // - |Editable project location| = 25 - // - expected length = 48 - // - expected length - |Editable project location| = 23 - // - |`[WORKSPACE_DIR]/`| = 16 - // - |`file://`| = 7, |`file:///`| = 8 (windows) - - let workspace_len_difference = workspace_dir.as_str().len() + 23 - 16 - prefix.len(); - let find_divider = "-".repeat(25 + workspace_len_difference); - let replace_divider = "-".repeat(48); - - let find_header = format!( - "Editable project location{0}", - " ".repeat(workspace_len_difference) - ); - let replace_header = format!("Editable project location{0}", " ".repeat(23)); - - let find_whitespace = " ".repeat(25 + workspace_len_difference); - let replace_whitespace = " ".repeat(48); - - let search_workspace = workspace_dir_re.as_str().strip_prefix(prefix).unwrap(); - let replace_workspace = "[WORKSPACE_DIR]/"; - - let filters = INSTA_FILTERS - .iter() - .copied() - .chain(vec![ - (search_workspace, replace_workspace), - (find_divider.as_str(), replace_divider.as_str()), - (find_header.as_str(), replace_header.as_str()), - (find_whitespace.as_str(), replace_whitespace.as_str()), - ]) + let filters = context + .filters() + .into_iter() + .chain(vec![(r"\-\-\-\-\-\-+.*", "[UNDERLINE]"), (" +", " ")]) .collect::>(); uv_snapshot!(filters, Command::new(get_bin()) - .arg("pip") - .arg("list") - .arg("--cache-dir") - .arg(context.cache_dir.path()) - .env("VIRTUAL_ENV", context.venv.as_os_str()) - .current_dir(&context.temp_dir), @r###" + .arg("pip") + .arg("list") + .arg("--cache-dir") + .arg(context.cache_dir.path()) + .env("VIRTUAL_ENV", context.venv.as_os_str()) + .current_dir(&context.temp_dir), @r###" success: true exit_code: 0 ----- stdout ----- - Package Version Editable project location - --------------- ------- ------------------------------------------------ - anyio 4.3.0 - idna 3.6 - poetry-editable 0.1.0 [WORKSPACE_DIR]/scripts/packages/poetry_editable - sniffio 1.3.1 + Package Version Editable project location + [UNDERLINE] + anyio 4.3.0 + idna 3.6 + poetry-editable 0.1.0 [WORKSPACE]/scripts/packages/poetry_editable + sniffio 1.3.1 ----- stderr ----- "### ); - - Ok(()) } #[test] -fn list_editable_only() -> Result<()> { +fn list_editable_only() { let context = TestContext::new("3.12"); - let current_dir = std::env::current_dir()?; - let workspace_dir = - Url::from_directory_path(current_dir.join("..").join("..").canonicalize()?).unwrap(); - let workspace_dir_re = regex::escape(workspace_dir.as_str()); - - let filters = [(workspace_dir_re.as_str(), "file://[WORKSPACE_DIR]/")] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect::>(); - // Install the editable package. - uv_snapshot!(filters, install_command(&context) + uv_snapshot!(context.filters(), install_command(&context) .arg("-e") - .arg("../../scripts/packages/poetry_editable") - .current_dir(¤t_dir) - .env("CARGO_TARGET_DIR", "../../../target/target_install_editable"), @r###" + .arg(context.workspace_root.join("scripts/packages/poetry_editable")), @r###" success: true exit_code: 0 ----- stdout ----- @@ -228,39 +170,15 @@ fn list_editable_only() -> Result<()> { Installed 4 packages in [TIME] + anyio==4.3.0 + idna==3.6 - + poetry-editable==0.1.0 (from file://[WORKSPACE_DIR]/scripts/packages/poetry_editable) + + poetry-editable==0.1.0 (from file://[WORKSPACE]/scripts/packages/poetry_editable) + sniffio==1.3.1 "### ); - // Account for difference length workspace dir - let prefix = if cfg!(windows) { "file:///" } else { "file://" }; - - let workspace_len_difference = workspace_dir.as_str().len() + 23 - 16 - prefix.len(); - let find_divider = "-".repeat(25 + workspace_len_difference); - let replace_divider = "-".repeat(48); - - let find_header = format!( - "Editable project location{0}", - " ".repeat(workspace_len_difference) - ); - let replace_header = format!("Editable project location{0}", " ".repeat(23)); - - let find_whitespace = " ".repeat(25 + workspace_len_difference); - let replace_whitespace = " ".repeat(48); - - let search_workspace = workspace_dir_re.as_str().strip_prefix(prefix).unwrap(); - let replace_workspace = "[WORKSPACE_DIR]/"; - - let filters = INSTA_FILTERS - .iter() - .copied() - .chain(vec![ - (search_workspace, replace_workspace), - (find_divider.as_str(), replace_divider.as_str()), - (find_header.as_str(), replace_header.as_str()), - (find_whitespace.as_str(), replace_whitespace.as_str()), - ]) + let filters = context + .filters() + .into_iter() + .chain(vec![(r"\-\-\-\-\-\-+.*", "[UNDERLINE]"), (" +", " ")]) .collect::>(); uv_snapshot!(filters, Command::new(get_bin()) @@ -274,9 +192,9 @@ fn list_editable_only() -> Result<()> { success: true exit_code: 0 ----- stdout ----- - Package Version Editable project location - --------------- ------- ------------------------------------------------ - poetry-editable 0.1.0 [WORKSPACE_DIR]/scripts/packages/poetry_editable + Package Version Editable project location + [UNDERLINE] + poetry-editable 0.1.0 [WORKSPACE]/scripts/packages/poetry_editable ----- stderr ----- "### @@ -294,9 +212,9 @@ fn list_editable_only() -> Result<()> { exit_code: 0 ----- stdout ----- Package Version - ------- ------- - anyio 4.3.0 - idna 3.6 + [UNDERLINE] + anyio 4.3.0 + idna 3.6 sniffio 1.3.1 ----- stderr ----- @@ -319,30 +237,16 @@ fn list_editable_only() -> Result<()> { ----- stderr ----- "### ); - - Ok(()) } #[test] -fn list_exclude() -> Result<()> { +fn list_exclude() { let context = TestContext::new("3.12"); - let current_dir = std::env::current_dir()?; - let workspace_dir = - Url::from_directory_path(current_dir.join("..").join("..").canonicalize()?).unwrap(); - let workspace_dir_re = regex::escape(workspace_dir.as_str()); - - let filters = [(workspace_dir_re.as_str(), "file://[WORKSPACE_DIR]/")] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect::>(); - // Install the editable package. - uv_snapshot!(filters, install_command(&context) + uv_snapshot!(context.filters(), install_command(&context) .arg("-e") - .arg("../../scripts/packages/poetry_editable") - .current_dir(¤t_dir) - .env("CARGO_TARGET_DIR", "../../../target/target_install_editable"), @r###" + .arg(context.workspace_root.join("scripts/packages/poetry_editable")), @r###" success: true exit_code: 0 ----- stdout ----- @@ -354,39 +258,15 @@ fn list_exclude() -> Result<()> { Installed 4 packages in [TIME] + anyio==4.3.0 + idna==3.6 - + poetry-editable==0.1.0 (from file://[WORKSPACE_DIR]/scripts/packages/poetry_editable) + + poetry-editable==0.1.0 (from file://[WORKSPACE]/scripts/packages/poetry_editable) + sniffio==1.3.1 "### ); - // Account for difference length workspace dir - let prefix = if cfg!(windows) { "file:///" } else { "file://" }; - - let workspace_len_difference = workspace_dir.as_str().len() + 23 - 16 - prefix.len(); - let find_divider = "-".repeat(25 + workspace_len_difference); - let replace_divider = "-".repeat(48); - - let find_header = format!( - "Editable project location{0}", - " ".repeat(workspace_len_difference) - ); - let replace_header = format!("Editable project location{0}", " ".repeat(23)); - - let find_whitespace = " ".repeat(25 + workspace_len_difference); - let replace_whitespace = " ".repeat(48); - - let search_workspace = workspace_dir_re.as_str().strip_prefix(prefix).unwrap(); - let replace_workspace = "[WORKSPACE_DIR]/"; - - let filters = INSTA_FILTERS - .iter() - .copied() - .chain(vec![ - (search_workspace, replace_workspace), - (find_divider.as_str(), replace_divider.as_str()), - (find_header.as_str(), replace_header.as_str()), - (find_whitespace.as_str(), replace_whitespace.as_str()), - ]) + let filters = context + .filters() + .into_iter() + .chain(vec![(r"\-\-\-\-\-\-+.*", "[UNDERLINE]"), (" +", " ")]) .collect::>(); uv_snapshot!(filters, Command::new(get_bin()) @@ -401,12 +281,12 @@ fn list_exclude() -> Result<()> { success: true exit_code: 0 ----- stdout ----- - Package Version Editable project location - --------------- ------- ------------------------------------------------ - anyio 4.3.0 - idna 3.6 - poetry-editable 0.1.0 [WORKSPACE_DIR]/scripts/packages/poetry_editable - sniffio 1.3.1 + Package Version Editable project location + [UNDERLINE] + anyio 4.3.0 + idna 3.6 + poetry-editable 0.1.0 [WORKSPACE]/scripts/packages/poetry_editable + sniffio 1.3.1 ----- stderr ----- "### @@ -425,9 +305,9 @@ fn list_exclude() -> Result<()> { exit_code: 0 ----- stdout ----- Package Version - ------- ------- - anyio 4.3.0 - idna 3.6 + [UNDERLINE] + anyio 4.3.0 + idna 3.6 sniffio 1.3.1 ----- stderr ----- @@ -449,41 +329,25 @@ fn list_exclude() -> Result<()> { exit_code: 0 ----- stdout ----- Package Version - ------- ------- - anyio 4.3.0 - idna 3.6 + [UNDERLINE] + anyio 4.3.0 + idna 3.6 sniffio 1.3.1 ----- stderr ----- "### ); - - Ok(()) } #[test] #[cfg(not(windows))] -fn list_format_json() -> Result<()> { +fn list_format_json() { let context = TestContext::new("3.12"); - let current_dir = std::env::current_dir()?; - let workspace_dir = regex::escape( - Url::from_directory_path(current_dir.join("..").join("..").canonicalize()?) - .unwrap() - .as_str(), - ); - - let filters = [(workspace_dir.as_str(), "file://[WORKSPACE_DIR]/")] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect::>(); - // Install the editable package. - uv_snapshot!(filters, install_command(&context) + uv_snapshot!(context.filters(), install_command(&context) .arg("-e") - .arg("../../scripts/packages/poetry_editable") - .current_dir(¤t_dir) - .env("CARGO_TARGET_DIR", "../../../target/target_install_editable"), @r###" + .arg(context.workspace_root.join("scripts/packages/poetry_editable")), @r###" success: true exit_code: 0 ----- stdout ----- @@ -495,47 +359,16 @@ fn list_format_json() -> Result<()> { Installed 4 packages in [TIME] + anyio==4.3.0 + idna==3.6 - + poetry-editable==0.1.0 (from file://[WORKSPACE_DIR]/scripts/packages/poetry_editable) + + poetry-editable==0.1.0 (from file://[WORKSPACE]/scripts/packages/poetry_editable) + sniffio==1.3.1 "### ); - let workspace_dir = regex::escape( - current_dir - .join("..") - .join("..") - .canonicalize()? - .to_str() - .unwrap(), - ); - - let workspace_len_difference = workspace_dir.as_str().len() + 23 - 16; - let find_divider = "-".repeat(25 + workspace_len_difference); - let replace_divider = "-".repeat(48); - - let find_header = format!( - "Editable project location{0}", - " ".repeat(workspace_len_difference) - ); - let replace_header = format!("Editable project location{0}", " ".repeat(23)); - - let find_whitespace = " ".repeat(25 + workspace_len_difference); - let replace_whitespace = " ".repeat(48); - - let search_workspace = workspace_dir.as_str(); - let search_workspace_escaped = search_workspace.replace('/', "\\\\"); - let replace_workspace = "[WORKSPACE_DIR]"; - - let filters: Vec<_> = [ - (search_workspace, replace_workspace), - (search_workspace_escaped.as_str(), replace_workspace), - (find_divider.as_str(), replace_divider.as_str()), - (find_header.as_str(), replace_header.as_str()), - (find_whitespace.as_str(), replace_whitespace.as_str()), - ] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect(); + let filters: Vec<_> = context + .filters() + .into_iter() + .chain(vec![(r"\-\-\-\-\-\-+.*", "[UNDERLINE]"), (" +", " ")]) + .collect(); uv_snapshot!(filters, Command::new(get_bin()) .arg("pip") @@ -548,7 +381,7 @@ fn list_format_json() -> Result<()> { success: true exit_code: 0 ----- stdout ----- - [{"name":"anyio","version":"4.3.0"},{"name":"idna","version":"3.6"},{"name":"poetry-editable","version":"0.1.0","editable_project_location":"[WORKSPACE_DIR]/scripts/packages/poetry_editable"},{"name":"sniffio","version":"1.3.1"}] + [{"name":"anyio","version":"4.3.0"},{"name":"idna","version":"3.6"},{"name":"poetry-editable","version":"0.1.0","editable_project_location":"[WORKSPACE]/scripts/packages/poetry_editable"},{"name":"sniffio","version":"1.3.1"}] ----- stderr ----- "### @@ -566,7 +399,7 @@ fn list_format_json() -> Result<()> { success: true exit_code: 0 ----- stdout ----- - [{"name":"poetry-editable","version":"0.1.0","editable_project_location":"[WORKSPACE_DIR]/scripts/packages/poetry_editable"}] + [{"name":"poetry-editable","version":"0.1.0","editable_project_location":"[WORKSPACE]/scripts/packages/poetry_editable"}] ----- stderr ----- "### @@ -607,32 +440,16 @@ fn list_format_json() -> Result<()> { ----- stderr ----- "### ); - - Ok(()) } #[test] -fn list_format_freeze() -> Result<()> { +fn list_format_freeze() { let context = TestContext::new("3.12"); - let current_dir = std::env::current_dir()?; - let workspace_dir = regex::escape( - Url::from_directory_path(current_dir.join("..").join("..").canonicalize()?) - .unwrap() - .as_str(), - ); - - let filters = [(workspace_dir.as_str(), "file://[WORKSPACE_DIR]/")] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect::>(); - // Install the editable package. - uv_snapshot!(filters, install_command(&context) + uv_snapshot!(context.filters(), install_command(&context) .arg("-e") - .arg("../../scripts/packages/poetry_editable") - .current_dir(¤t_dir) - .env("CARGO_TARGET_DIR", "../../../target/target_install_editable"), @r###" + .arg(context.workspace_root.join("scripts/packages/poetry_editable")), @r###" success: true exit_code: 0 ----- stdout ----- @@ -644,39 +461,15 @@ fn list_format_freeze() -> Result<()> { Installed 4 packages in [TIME] + anyio==4.3.0 + idna==3.6 - + poetry-editable==0.1.0 (from file://[WORKSPACE_DIR]/scripts/packages/poetry_editable) + + poetry-editable==0.1.0 (from file://[WORKSPACE]/scripts/packages/poetry_editable) + sniffio==1.3.1 "### ); - // Account for difference length workspace dir - let prefix = if cfg!(windows) { "file:///" } else { "file://" }; - - let workspace_len_difference = workspace_dir.as_str().len() + 23 - 16 - prefix.len(); - let find_divider = "-".repeat(25 + workspace_len_difference); - let replace_divider = "-".repeat(48); - - let find_header = format!( - "Editable project location{0}", - " ".repeat(workspace_len_difference) - ); - let replace_header = format!("Editable project location{0}", " ".repeat(23)); - - let find_whitespace = " ".repeat(25 + workspace_len_difference); - let replace_whitespace = " ".repeat(48); - - let search_workspace = workspace_dir.as_str().strip_prefix(prefix).unwrap(); - let replace_workspace = "[WORKSPACE_DIR]/"; - - let filters = INSTA_FILTERS - .iter() - .copied() - .chain(vec![ - (search_workspace, replace_workspace), - (find_divider.as_str(), replace_divider.as_str()), - (find_header.as_str(), replace_header.as_str()), - (find_whitespace.as_str(), replace_whitespace.as_str()), - ]) + let filters = context + .filters() + .into_iter() + .chain(vec![(r"\-\-\-\-\-\-+.*", "[UNDERLINE]"), (" +", " ")]) .collect::>(); uv_snapshot!(filters, Command::new(get_bin()) @@ -754,6 +547,4 @@ fn list_format_freeze() -> Result<()> { ----- stderr ----- "### ); - - Ok(()) } diff --git a/crates/uv/tests/pip_show.rs b/crates/uv/tests/pip_show.rs index 1bd092e8d..5edee570d 100644 --- a/crates/uv/tests/pip_show.rs +++ b/crates/uv/tests/pip_show.rs @@ -85,14 +85,7 @@ fn show_requires_multiple() -> Result<()> { ); context.assert_command("import requests").success(); - let filters = [( - r"Location:.*site-packages", - "Location: [WORKSPACE_DIR]/site-packages", - )] - .to_vec(); - - // Guards against the package names being sorted. - uv_snapshot!(filters, Command::new(get_bin()) + uv_snapshot!(context.filters(), Command::new(get_bin()) .arg("pip") .arg("show") .arg("requests") @@ -105,7 +98,7 @@ fn show_requires_multiple() -> Result<()> { ----- stdout ----- Name: requests Version: 2.31.0 - Location: [WORKSPACE_DIR]/site-packages + Location: [SITE_PACKAGES]/ Requires: certifi, charset-normalizer, idna, urllib3 Required-by: @@ -144,10 +137,7 @@ fn show_python_version_marker() -> Result<()> { context.assert_command("import click").success(); - let mut filters = vec![( - r"Location:.*site-packages", - "Location: [WORKSPACE_DIR]/site-packages", - )]; + let mut filters = context.filters(); if cfg!(windows) { filters.push(("Requires: colorama", "Requires:")); } @@ -165,7 +155,7 @@ fn show_python_version_marker() -> Result<()> { ----- stdout ----- Name: click Version: 8.1.7 - Location: [WORKSPACE_DIR]/site-packages + Location: [SITE_PACKAGES]/ Requires: Required-by: @@ -202,12 +192,7 @@ fn show_found_single_package() -> Result<()> { context.assert_command("import markupsafe").success(); - let filters = vec![( - r"Location:.*site-packages", - "Location: [WORKSPACE_DIR]/site-packages", - )]; - - uv_snapshot!(filters, Command::new(get_bin()) + uv_snapshot!(context.filters(), Command::new(get_bin()) .arg("pip") .arg("show") .arg("markupsafe") @@ -220,7 +205,7 @@ fn show_found_single_package() -> Result<()> { ----- stdout ----- Name: markupsafe Version: 2.1.3 - Location: [WORKSPACE_DIR]/site-packages + Location: [SITE_PACKAGES]/ Requires: Required-by: @@ -262,14 +247,7 @@ fn show_found_multiple_packages() -> Result<()> { context.assert_command("import markupsafe").success(); - // In addition to the standard filters, remove the temporary directory from the snapshot. - let filters = [( - r"Location:.*site-packages", - "Location: [WORKSPACE_DIR]/site-packages", - )] - .to_vec(); - - uv_snapshot!(filters, Command::new(get_bin()) + uv_snapshot!(context.filters(), Command::new(get_bin()) .arg("pip") .arg("show") .arg("markupsafe") @@ -283,13 +261,13 @@ fn show_found_multiple_packages() -> Result<()> { ----- stdout ----- Name: markupsafe Version: 2.1.3 - Location: [WORKSPACE_DIR]/site-packages + Location: [SITE_PACKAGES]/ Requires: Required-by: --- Name: pip Version: 21.3.1 - Location: [WORKSPACE_DIR]/site-packages + Location: [SITE_PACKAGES]/ Requires: Required-by: @@ -331,14 +309,7 @@ fn show_found_one_out_of_three() -> Result<()> { context.assert_command("import markupsafe").success(); - // In addition to the standard filters, remove the temporary directory from the snapshot. - let filters = [( - r"Location:.*site-packages", - "Location: [WORKSPACE_DIR]/site-packages", - )] - .to_vec(); - - uv_snapshot!(filters, Command::new(get_bin()) + uv_snapshot!(context.filters(), Command::new(get_bin()) .arg("pip") .arg("show") .arg("markupsafe") @@ -353,7 +324,7 @@ fn show_found_one_out_of_three() -> Result<()> { ----- stdout ----- Name: markupsafe Version: 2.1.3 - Location: [WORKSPACE_DIR]/site-packages + Location: [SITE_PACKAGES]/ Requires: Required-by: @@ -486,20 +457,7 @@ fn show_editable() -> Result<()> { .assert() .success(); - // In addition to the standard filters, remove the temporary directory from the snapshot. - let filters = [ - ( - r"Location:.*site-packages", - "Location: [WORKSPACE_DIR]/site-packages", - ), - ( - r"Editable project location:.*poetry_editable", - "Editable project location: [EDITABLE_INSTALLS_PREFIX]poetry_editable", - ), - ] - .to_vec(); - - uv_snapshot!(filters, Command::new(get_bin()) + uv_snapshot!(context.filters(), Command::new(get_bin()) .arg("pip") .arg("show") .arg("poetry-editable") @@ -512,8 +470,8 @@ fn show_editable() -> Result<()> { ----- stdout ----- Name: poetry-editable Version: 0.1.0 - Location: [WORKSPACE_DIR]/site-packages - Editable project location: [EDITABLE_INSTALLS_PREFIX]poetry_editable + Location: [SITE_PACKAGES]/ + Editable project location: [WORKSPACE]/scripts/packages/poetry_editable Requires: anyio Required-by: @@ -559,14 +517,9 @@ fn show_required_by_multiple() -> Result<()> { ); context.assert_command("import requests").success(); - let filters = [( - r"Location:.*site-packages", - "Location: [WORKSPACE_DIR]/site-packages", - )] - .to_vec(); // idna is required by anyio and requests - uv_snapshot!(filters, Command::new(get_bin()) + uv_snapshot!(context.filters(), Command::new(get_bin()) .arg("pip") .arg("show") .arg("idna") @@ -579,7 +532,7 @@ fn show_required_by_multiple() -> Result<()> { ----- stdout ----- Name: idna Version: 3.6 - Location: [WORKSPACE_DIR]/site-packages + Location: [SITE_PACKAGES]/ Requires: Required-by: anyio, requests diff --git a/crates/uv/tests/pip_sync.rs b/crates/uv/tests/pip_sync.rs index 19388e427..e21c79bb8 100644 --- a/crates/uv/tests/pip_sync.rs +++ b/crates/uv/tests/pip_sync.rs @@ -10,6 +10,7 @@ use assert_cmd::prelude::*; use assert_fs::fixture::ChildPath; use assert_fs::prelude::*; use indoc::indoc; +use predicates::Predicate; use url::Url; use common::{ @@ -17,7 +18,7 @@ use common::{ }; use uv_fs::Simplified; -use crate::common::{get_bin, TestContext}; +use crate::common::{copy_dir_all, get_bin, TestContext}; mod common; @@ -114,29 +115,22 @@ fn missing_requirements_txt() { #[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"); + let context = TestContext::new("3.12"); + let requirements = context.temp_dir.child("requirements.txt"); + requirements.write_str("anyio")?; + fs::remove_dir_all(&context.venv)?; - uv_snapshot!(Command::new(get_bin()) - .arg("pip") - .arg("sync") - .arg("requirements.txt") - .arg("--strict") - .arg("--cache-dir") - .arg(cache_dir.path()) - .env("VIRTUAL_ENV", venv.as_os_str()) - .current_dir(&temp_dir), @r###" + uv_snapshot!(context.filters(), command(&context).arg("requirements.txt"), @r###" success: false exit_code: 2 ----- stdout ----- ----- stderr ----- - error: failed to read from file `requirements.txt` + error: failed to canonicalize path `[VENV]/` Caused by: No such file or directory (os error 2) "###); - venv.assert(predicates::path::missing()); + assert!(predicates::path::missing().eval(&context.venv)); Ok(()) } @@ -919,7 +913,7 @@ fn warn_on_yanked_version() -> Result<()> { // This version is yanked. requirements_in.write_str("colorama==0.4.2")?; - uv_snapshot!(INSTA_FILTERS, windows_filters=false, command(&context) + uv_snapshot!(context.filters(), windows_filters=false, command(&context) .arg("requirements.txt") .arg("--strict"), @r###" success: true @@ -955,13 +949,7 @@ fn install_local_wheel() -> Result<()> { Url::from_file_path(archive.path()).unwrap() ))?; - // In addition to the standard filters, remove the temporary directory from the snapshot. - let filters: Vec<_> = [(r"file://.*/", "file://[TEMP_DIR]/")] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect(); - - uv_snapshot!(filters, command(&context) + uv_snapshot!(context.filters(), command(&context) .arg("requirements.txt") .arg("--strict"), @r###" success: true @@ -982,7 +970,7 @@ fn install_local_wheel() -> Result<()> { let venv = create_venv(&context.temp_dir, &context.cache_dir, "3.12"); // Reinstall. The wheel should come from the cache, so there shouldn't be a "download". - uv_snapshot!(filters, command(&context) + uv_snapshot!(context.filters(), command(&context) .arg("requirements.txt") .arg("--strict") .env("VIRTUAL_ENV", venv.as_os_str()), @r###" @@ -1006,7 +994,7 @@ fn install_local_wheel() -> Result<()> { filetime::set_file_mtime(&archive, filetime::FileTime::now()).unwrap(); // Reinstall. The wheel should be "downloaded" again. - uv_snapshot!(filters, command(&context) + uv_snapshot!(context.filters(), command(&context) .arg("requirements.txt") .arg("--strict") .env("VIRTUAL_ENV", venv.as_os_str()), @r###" @@ -1028,7 +1016,7 @@ fn install_local_wheel() -> Result<()> { filetime::set_file_mtime(&archive, filetime::FileTime::now()).unwrap(); // Reinstall into the same virtual environment. The wheel should be reinstalled. - uv_snapshot!(filters, command(&context) + uv_snapshot!(context.filters(), command(&context) .arg("requirements.txt") .arg("--strict"), @r###" success: true @@ -1067,13 +1055,7 @@ fn mismatched_version() -> Result<()> { Url::from_file_path(archive.path()).unwrap() ))?; - // In addition to the standard filters, remove the temporary directory from the snapshot. - let filters: Vec<_> = [(r"file://.*/", "file://[TEMP_DIR]/")] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect(); - - uv_snapshot!(filters, command(&context) + uv_snapshot!(context.filters(), command(&context) .arg("requirements.txt") .arg("--strict"), @r###" success: false @@ -1108,13 +1090,7 @@ fn mismatched_name() -> Result<()> { Url::from_file_path(archive.path()).unwrap() ))?; - // In addition to the standard filters, remove the temporary directory from the snapshot. - let filters: Vec<_> = [(r"file://.*/", "file://[TEMP_DIR]/")] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect(); - - uv_snapshot!(filters, command(&context) + uv_snapshot!(context.filters(), command(&context) .arg("requirements.txt") .arg("--strict"), @r###" success: false @@ -1149,13 +1125,7 @@ fn install_local_source_distribution() -> Result<()> { Url::from_file_path(archive.path()).unwrap() ))?; - // In addition to the standard filters, remove the temporary directory from the snapshot. - let filters: Vec<_> = [(r"file://.*/", "file://[TEMP_DIR]/")] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect(); - - uv_snapshot!(filters, command(&context) + uv_snapshot!(context.filters(), command(&context) .arg("requirements.txt") .arg("--strict"), @r###" success: true @@ -1267,10 +1237,10 @@ fn install_url_source_dist_cached() -> Result<()> { let filters = if cfg!(windows) { [("warning: The package `tqdm` requires `colorama ; platform_system == 'Windows'`, but it's not installed.\n", "")] .into_iter() - .chain(INSTA_FILTERS.to_vec()) + .chain(context.filters()) .collect() } else { - INSTA_FILTERS.to_vec() + context.filters() }; uv_snapshot!(filters, command(&context) .arg("requirements.txt") @@ -1290,7 +1260,8 @@ fn install_url_source_dist_cached() -> Result<()> { context.assert_command("import tqdm").success(); // Re-run the installation in a new virtual environment. - let parent = assert_fs::TempDir::new()?; + let parent = context.temp_dir.child("parent"); + parent.create_dir_all()?; let venv = create_venv(&parent, &context.cache_dir, "3.12"); uv_snapshot!(filters, command(&context) @@ -1310,7 +1281,8 @@ fn install_url_source_dist_cached() -> Result<()> { context.assert_command("import tqdm").success(); // Clear the cache, then re-run the installation in a new virtual environment. - let parent = assert_fs::TempDir::new()?; + let parent = context.temp_dir.child("parent"); + parent.create_dir_all()?; let venv = create_venv(&parent, &context.cache_dir, "3.12"); uv_snapshot!(Command::new(get_bin()) @@ -1378,7 +1350,8 @@ fn install_git_source_dist_cached() -> Result<()> { context.assert_command("import werkzeug").success(); // Re-run the installation in a new virtual environment. - let parent = assert_fs::TempDir::new()?; + let parent = context.temp_dir.child("parent"); + parent.create_dir_all()?; let venv = create_venv(&parent, &context.cache_dir, "3.12"); uv_snapshot!(command(&context) @@ -1398,16 +1371,17 @@ fn install_git_source_dist_cached() -> Result<()> { check_command(&venv, "import werkzeug", &context.temp_dir); // Clear the cache, then re-run the installation in a new virtual environment. - let parent = assert_fs::TempDir::new()?; + let parent = context.temp_dir.child("parent"); + parent.create_dir_all()?; let venv = create_venv(&parent, &context.cache_dir, "3.12"); let filters = if cfg!(windows) { [("Removed 2 files", "Removed 3 files")] .into_iter() - .chain(INSTA_FILTERS.to_vec()) + .chain(context.filters()) .collect() } else { - INSTA_FILTERS.to_vec() + context.filters() }; uv_snapshot!(filters, Command::new(get_bin()) .arg("clean") @@ -1473,7 +1447,8 @@ fn install_registry_source_dist_cached() -> Result<()> { context.assert_command("import future").success(); // Re-run the installation in a new virtual environment. - let parent = assert_fs::TempDir::new()?; + let parent = context.temp_dir.child("parent"); + parent.create_dir_all()?; let venv = create_venv(&parent, &context.cache_dir, "3.12"); uv_snapshot!(command(&context) @@ -1493,16 +1468,17 @@ fn install_registry_source_dist_cached() -> Result<()> { context.assert_command("import future").success(); // Clear the cache, then re-run the installation in a new virtual environment. - let parent = assert_fs::TempDir::new()?; + let parent = context.temp_dir.child("parent"); + parent.create_dir_all()?; let venv = create_venv(&parent, &context.cache_dir, "3.12"); let filters = if cfg!(windows) { [("Removed 615 files", "Removed 616 files")] .into_iter() - .chain(INSTA_FILTERS.to_vec()) + .chain(context.filters()) .collect() } else { - INSTA_FILTERS.to_vec() + context.filters() }; uv_snapshot!(filters, Command::new(get_bin()) .arg("clean") @@ -1558,13 +1534,7 @@ fn install_path_source_dist_cached() -> Result<()> { Url::from_file_path(archive.path()).unwrap() ))?; - // In addition to the standard filters, remove the temporary directory from the snapshot. - let filters: Vec<_> = [(r"file://.*/", "file://[TEMP_DIR]/")] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect(); - - uv_snapshot!(filters, command(&context) + uv_snapshot!(context.filters(), command(&context) .arg("requirements.txt") .arg("--strict"), @r###" success: true @@ -1582,10 +1552,11 @@ fn install_path_source_dist_cached() -> Result<()> { context.assert_command("import wheel").success(); // Re-run the installation in a new virtual environment. - let parent = assert_fs::TempDir::new()?; + let parent = context.temp_dir.child("parent"); + parent.create_dir_all()?; let venv = create_venv(&parent, &context.cache_dir, "3.12"); - uv_snapshot!(filters, command(&context) + uv_snapshot!(context.filters(), command(&context) .arg("requirements.txt") .arg("--strict") .env("VIRTUAL_ENV", venv.as_os_str()), @r###" @@ -1602,18 +1573,19 @@ fn install_path_source_dist_cached() -> Result<()> { context.assert_command("import wheel").success(); // Clear the cache, then re-run the installation in a new virtual environment. - let parent = assert_fs::TempDir::new()?; + let parent = context.temp_dir.child("parent"); + parent.create_dir_all()?; let venv = create_venv(&parent, &context.cache_dir, "3.12"); - let filters2 = if cfg!(windows) { + let filters = if cfg!(windows) { [("Removed 3 files", "Removed 4 files")] .into_iter() - .chain(INSTA_FILTERS.to_vec()) + .chain(context.filters()) .collect() } else { - INSTA_FILTERS.to_vec() + context.filters() }; - uv_snapshot!(filters2, Command::new(get_bin()) + uv_snapshot!(filters, Command::new(get_bin()) .arg("clean") .arg("wheel") .arg("--cache-dir") @@ -1629,7 +1601,7 @@ fn install_path_source_dist_cached() -> Result<()> { "### ); - uv_snapshot!(filters, command(&context) + uv_snapshot!(context.filters(), command(&context) .arg("requirements.txt") .arg("--strict") .env("VIRTUAL_ENV", venv.as_os_str()), @r###" @@ -1665,17 +1637,7 @@ fn install_path_built_dist_cached() -> Result<()> { let url = Url::from_file_path(archive.path()).unwrap(); requirements_txt.write_str(&format!("tomli @ {url}"))?; - // In addition to the standard filters, remove the temporary directory from the snapshot. - let url_escaped = regex::escape(url.as_str()); - let filters: Vec<_> = [( - url_escaped.as_str(), - "file://[TEMP_DIR]/tomli-2.0.1-py3-none-any.whl", - )] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect(); - - uv_snapshot!(filters, command(&context) + uv_snapshot!(context.filters(), command(&context) .arg("requirements.txt") .arg("--strict"), @r###" success: true @@ -1693,10 +1655,11 @@ fn install_path_built_dist_cached() -> Result<()> { context.assert_command("import tomli").success(); // Re-run the installation in a new virtual environment. - let parent = assert_fs::TempDir::new()?; + let parent = context.temp_dir.child("parent"); + parent.create_dir_all()?; let venv = create_venv(&context.temp_dir, &context.cache_dir, "3.12"); - uv_snapshot!(filters, command(&context) + uv_snapshot!(context.filters(), command(&context) .arg("requirements.txt") .arg("--strict") .env("VIRTUAL_ENV", venv.as_os_str()), @r###" @@ -1713,21 +1676,23 @@ fn install_path_built_dist_cached() -> Result<()> { 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 parent = context.temp_dir.child("parent"); + parent.create_dir_all()?; let venv = create_venv(&parent, &context.cache_dir, "3.12"); - let filters2 = if cfg!(windows) { + let filters = if cfg!(windows) { + // We do not display sizes on Windows [( "Removed 1 file for tomli", "Removed 1 file for tomli ([SIZE])", )] .into_iter() - .chain(INSTA_FILTERS.to_vec()) + .chain(context.filters()) .collect() } else { - INSTA_FILTERS.to_vec() + context.filters() }; - uv_snapshot!(filters2, Command::new(get_bin()) + uv_snapshot!(filters, Command::new(get_bin()) .arg("clean") .arg("tomli") .arg("--cache-dir") @@ -1743,7 +1708,7 @@ fn install_path_built_dist_cached() -> Result<()> { "### ); - uv_snapshot!(filters, command(&context) + uv_snapshot!(context.filters(), command(&context) .arg("requirements.txt") .arg("--strict") .env("VIRTUAL_ENV", venv.as_os_str()), @r###" @@ -1776,10 +1741,10 @@ fn install_url_built_dist_cached() -> Result<()> { let filters = if cfg!(windows) { [("warning: The package `tqdm` requires `colorama ; platform_system == 'Windows'`, but it's not installed.\n", "")] .into_iter() - .chain(INSTA_FILTERS.to_vec()) + .chain(context.filters()) .collect() } else { - INSTA_FILTERS.to_vec() + context.filters() }; uv_snapshot!(filters, command(&context) .arg("requirements.txt") @@ -1799,7 +1764,8 @@ fn install_url_built_dist_cached() -> Result<()> { context.assert_command("import tqdm").success(); // Re-run the installation in a new virtual environment. - let parent = assert_fs::TempDir::new()?; + let parent = context.temp_dir.child("parent"); + parent.create_dir_all()?; let venv = create_venv(&parent, &context.cache_dir, "3.12"); uv_snapshot!(filters, command(&context) @@ -1819,7 +1785,8 @@ fn install_url_built_dist_cached() -> Result<()> { check_command(&venv, "import tqdm", &context.temp_dir); // Clear the cache, then re-run the installation in a new virtual environment. - let parent = assert_fs::TempDir::new()?; + let parent = context.temp_dir.child("parent"); + parent.create_dir_all()?; let venv = create_venv(&parent, &context.cache_dir, "3.12"); uv_snapshot!(Command::new(get_bin()) @@ -2096,7 +2063,8 @@ fn refresh() -> Result<()> { // Re-run the installation into with `--refresh`. Ensure that we resolve and download the // latest versions of the packages. - let parent = assert_fs::TempDir::new()?; + let parent = context.temp_dir.child("parent"); + parent.create_dir_all()?; let venv = create_venv(&parent, &context.cache_dir, "3.12"); uv_snapshot!(command(&context) @@ -2153,7 +2121,8 @@ fn refresh_package() -> Result<()> { // Re-run the installation into with `--refresh`. Ensure that we resolve and download the // latest versions of the packages. - let parent = assert_fs::TempDir::new()?; + let parent = context.temp_dir.child("parent"); + parent.create_dir_all()?; let venv = create_venv(&parent, &context.cache_dir, "3.12"); uv_snapshot!(command(&context) @@ -2186,40 +2155,20 @@ fn refresh_package() -> Result<()> { fn sync_editable() -> Result<()> { let context = TestContext::new("3.12"); - let current_dir = std::env::current_dir()?; - let workspace_url = regex::escape( - Url::from_directory_path(current_dir.join("..").join("..").canonicalize()?) - .unwrap() - .as_str() - .trim_end_matches(['\\', '/']), - ); - let requirements_txt = context.temp_dir.child("requirements.txt"); requirements_txt.write_str(&indoc::formatdoc! {r" boltons==23.1.1 - -e ../../scripts/packages/maturin_editable + -e {workspace_root}/scripts/packages/maturin_editable numpy==1.26.2 # via poetry-editable - -e file://{current_dir}/../../scripts/packages/poetry_editable + -e file://{workspace_root}/scripts/packages/poetry_editable ", - current_dir = current_dir.simplified_display(), + workspace_root = context.workspace_root.simplified_display(), })?; - let filter_path = regex::escape(&requirements_txt.user_display().to_string()); - let filters = INSTA_FILTERS - .iter() - .chain(&[ - (filter_path.as_str(), "requirements.txt"), - (&workspace_url, "file://[WORKSPACE_DIR]"), - ]) - .copied() - .collect::>(); - // Install the editable packages. - uv_snapshot!(filters, command(&context) - .arg(requirements_txt.path()) - .current_dir(¤t_dir) - .env("CARGO_TARGET_DIR", "../../../target/target_install_editable"), @r###" + uv_snapshot!(context.filters(), command(&context) + .arg(requirements_txt.path()), @r###" success: true exit_code: 0 ----- stdout ----- @@ -2230,19 +2179,17 @@ fn sync_editable() -> Result<()> { Downloaded 2 packages in [TIME] Installed 4 packages in [TIME] + boltons==23.1.1 - + maturin-editable==0.1.0 (from file://[WORKSPACE_DIR]/scripts/packages/maturin_editable) + + maturin-editable==0.1.0 (from file://[WORKSPACE]/scripts/packages/maturin_editable) + numpy==1.26.2 - + poetry-editable==0.1.0 (from file://[WORKSPACE_DIR]/scripts/packages/poetry_editable) + + poetry-editable==0.1.0 (from file://[WORKSPACE]/scripts/packages/poetry_editable) "### ); // Reinstall the editable packages. - uv_snapshot!(filters, command(&context) + uv_snapshot!(context.filters(), command(&context) .arg(requirements_txt.path()) .arg("--reinstall-package") - .arg("poetry-editable") - .current_dir(¤t_dir) - .env("CARGO_TARGET_DIR", "../../../target/target_install_editable"), @r###" + .arg("poetry-editable"), @r###" success: true exit_code: 0 ----- stdout ----- @@ -2251,20 +2198,21 @@ fn sync_editable() -> Result<()> { Built 1 editable in [TIME] Uninstalled 1 package in [TIME] Installed 1 package in [TIME] - - poetry-editable==0.1.0 (from file://[WORKSPACE_DIR]/scripts/packages/poetry_editable) - + poetry-editable==0.1.0 (from file://[WORKSPACE_DIR]/scripts/packages/poetry_editable) + - poetry-editable==0.1.0 (from file://[WORKSPACE]/scripts/packages/poetry_editable) + + poetry-editable==0.1.0 (from file://[WORKSPACE]/scripts/packages/poetry_editable) "### ); // Make sure we have the right base case. - let python_source_file = - "../../scripts/packages/maturin_editable/python/maturin_editable/__init__.py"; + let python_source_file = context + .workspace_root + .join("scripts/packages/maturin_editable/python/maturin_editable/__init__.py"); let python_version_1 = indoc::indoc! {r" from .maturin_editable import * version = 1 "}; - fs_err::write(python_source_file, python_version_1)?; + fs_err::write(&python_source_file, python_version_1)?; let check_installed = indoc::indoc! {r#" from maturin_editable import sum_as_string, version @@ -2280,7 +2228,7 @@ fn sync_editable() -> Result<()> { version = 2 "}; - fs_err::write(python_source_file, python_version_2)?; + fs_err::write(&python_source_file, python_version_2)?; let check_installed = indoc::indoc! {r#" from maturin_editable import sum_as_string, version @@ -2292,12 +2240,10 @@ fn sync_editable() -> Result<()> { context.assert_command(check_installed).success(); // Don't create a git diff. - fs_err::write(python_source_file, python_version_1)?; + fs_err::write(&python_source_file, python_version_1)?; - uv_snapshot!(filters, command(&context) - .arg(requirements_txt.path()) - .current_dir(¤t_dir) - .env("CARGO_TARGET_DIR", "../../../target/target_install_editable"), @r###" + uv_snapshot!(context.filters(), command(&context) + .arg(requirements_txt.path()), @r###" success: true exit_code: 0 ----- stdout ----- @@ -2314,12 +2260,13 @@ fn sync_editable() -> Result<()> { fn sync_editable_and_registry() -> Result<()> { let context = TestContext::new("3.12"); - let current_dir = std::env::current_dir()?; - let workspace_url = regex::escape( - Url::from_directory_path(current_dir.join("..").join("..").canonicalize()?) - .unwrap() - .as_str(), - ); + // Copy the black test editable into the "current" directory + copy_dir_all( + context + .workspace_root + .join("scripts/packages/black_editable"), + context.temp_dir.join("black_editable"), + )?; // Install the registry-based version of Black. let requirements_txt = context.temp_dir.child("requirements.txt"); @@ -2328,20 +2275,9 @@ fn sync_editable_and_registry() -> Result<()> { " })?; - let filter_path = regex::escape(&requirements_txt.user_display().to_string()); - let filters = INSTA_FILTERS - .iter() - .chain(&[ - (filter_path.as_str(), "requirements.txt"), - (workspace_url.as_str(), "file://[WORKSPACE_DIR]/"), - ]) - .copied() - .collect::>(); - uv_snapshot!(filters, command(&context) + uv_snapshot!(context.filters(), command(&context) .arg(requirements_txt.path()) - .arg("--strict") - .current_dir(¤t_dir) - .env("CARGO_TARGET_DIR", "../../../target/target_install_editable"), @r###" + .arg("--strict"), @r###" success: true exit_code: 0 ----- stdout ----- @@ -2363,23 +2299,12 @@ fn sync_editable_and_registry() -> Result<()> { // Use the `file:` syntax for extra coverage. let requirements_txt = context.temp_dir.child("requirements.txt"); requirements_txt.write_str(indoc::indoc! {r" - -e file:../../scripts/packages/black_editable + -e file:./black_editable " })?; - let filter_path = regex::escape(&requirements_txt.user_display().to_string()); - let filters = INSTA_FILTERS - .iter() - .chain(&[ - (filter_path.as_str(), "requirements.txt"), - (workspace_url.as_str(), "file://[WORKSPACE_DIR]/"), - ]) - .copied() - .collect::>(); - uv_snapshot!(filters, command(&context) - .arg(requirements_txt.path()) - .current_dir(¤t_dir) - .env("CARGO_TARGET_DIR", "../../../target/target_install_editable"), @r###" + uv_snapshot!(context.filters(), command(&context) + .arg(requirements_txt.path()), @r###" success: true exit_code: 0 ----- stdout ----- @@ -2389,7 +2314,7 @@ fn sync_editable_and_registry() -> Result<()> { Uninstalled 1 package in [TIME] Installed 1 package in [TIME] - black==24.1.0 - + black==0.1.0 (from file://[WORKSPACE_DIR]/scripts/packages/black_editable) + + black==0.1.0 (from file://[TEMP_DIR]/black_editable) "### ); @@ -2401,19 +2326,8 @@ fn sync_editable_and_registry() -> Result<()> { " })?; - let filter_path = regex::escape(&requirements_txt.user_display().to_string()); - let filters = INSTA_FILTERS - .iter() - .chain(&[ - (filter_path.as_str(), "requirements.txt"), - (workspace_url.as_str(), "file://[WORKSPACE_DIR]/"), - ]) - .copied() - .collect::>(); - uv_snapshot!(filters, command(&context) - .arg(requirements_txt.path()) - .current_dir(¤t_dir) - .env("CARGO_TARGET_DIR", "../../../target/target_install_editable"), @r###" + uv_snapshot!(context.filters(), command(&context) + .arg(requirements_txt.path()), @r###" success: true exit_code: 0 ----- stdout ----- @@ -2430,20 +2344,9 @@ fn sync_editable_and_registry() -> Result<()> { " })?; - let filter_path = regex::escape(&requirements_txt.user_display().to_string()); - let filters = INSTA_FILTERS - .iter() - .chain(&[ - (filter_path.as_str(), "requirements.txt"), - (workspace_url.as_str(), "file://[WORKSPACE_DIR]/"), - ]) - .copied() - .collect::>(); - uv_snapshot!(filters, command(&context) + uv_snapshot!(context.filters(), command(&context) .arg(requirements_txt.path()) - .arg("--strict") - .current_dir(¤t_dir) - .env("CARGO_TARGET_DIR", "../../../target/target_install_editable"), @r###" + .arg("--strict"), @r###" success: true exit_code: 0 ----- stdout ----- @@ -2453,7 +2356,7 @@ fn sync_editable_and_registry() -> Result<()> { Downloaded 1 package in [TIME] Uninstalled 1 package in [TIME] Installed 1 package in [TIME] - - black==0.1.0 (from file://[WORKSPACE_DIR]/scripts/packages/black_editable) + - black==0.1.0 (from file://[TEMP_DIR]/black_editable) + black==23.10.0 warning: The package `black` requires `click>=8.0.0`, but it's not installed. warning: The package `black` requires `mypy-extensions>=0.4.3`, but it's not installed. @@ -2469,24 +2372,13 @@ fn sync_editable_and_registry() -> Result<()> { #[test] fn incompatible_wheel() -> Result<()> { let context = TestContext::new("3.12"); - let wheel_dir = assert_fs::TempDir::new()?; - - let wheel = wheel_dir.child("foo-1.2.3-not-compatible-wheel.whl"); + let wheel = context.temp_dir.child("foo-1.2.3-not-compatible-wheel.whl"); wheel.touch()?; let requirements_txt = context.temp_dir.child("requirements.txt"); - requirements_txt.write_str(&format!( - "foo @ {}", - Url::from_file_path(wheel.path()).unwrap() - ))?; + requirements_txt.write_str(&format!("foo @ {}", wheel.path().simplified_display()))?; - let wheel_dir = regex::escape(&wheel_dir.path().canonicalize()?.user_display().to_string()); - let filters: Vec<_> = [(wheel_dir.as_str(), "[TEMP_DIR]")] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect(); - - uv_snapshot!(filters, command(&context) + uv_snapshot!(context.filters(), command(&context) .arg("requirements.txt") .arg("--strict"), @r###" success: false @@ -2495,7 +2387,7 @@ fn incompatible_wheel() -> Result<()> { ----- stderr ----- error: Failed to determine installation plan - Caused by: A path dependency is incompatible with the current platform: [TEMP_DIR]/foo-1.2.3-not-compatible-wheel.whl + Caused by: A path dependency is incompatible with the current platform: foo-1.2.3-not-compatible-wheel.whl "### ); @@ -2566,17 +2458,10 @@ fn find_links() -> Result<()> { werkzeug @ https://files.pythonhosted.org/packages/c3/fc/254c3e9b5feb89ff5b9076a23218dafbc99c96ac5941e900b71206e6313b/werkzeug-3.0.1-py3-none-any.whl "})?; - let project_root = fs_err::canonicalize(std::env::current_dir()?.join("../.."))?; - let project_root_string = regex::escape(&project_root.user_display().to_string()); - let filters: Vec<_> = [(project_root_string.as_str(), "[PROJECT_ROOT]")] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect(); - - uv_snapshot!(filters, command(&context) + uv_snapshot!(context.filters(), command(&context) .arg("requirements.txt") .arg("--find-links") - .arg(project_root.join("scripts/wheels/")), @r###" + .arg(context.workspace_root.join("scripts/wheels/")), @r###" success: true exit_code: 0 ----- stdout ----- @@ -2785,7 +2670,8 @@ fn invalidate_on_change() -> Result<()> { let context = TestContext::new("3.12"); // Create an editable package. - let editable_dir = assert_fs::TempDir::new()?; + let editable_dir = context.temp_dir.child("editable"); + editable_dir.create_dir_all()?; let pyproject_toml = editable_dir.child("pyproject.toml"); pyproject_toml.write_str( r#"[project] @@ -2802,12 +2688,7 @@ requires-python = ">=3.8" let requirements_in = context.temp_dir.child("requirements.in"); requirements_in.write_str(&format!("-e {}", editable_dir.path().display()))?; - let filters = [(r"\(from file://.*\)", "(from [WORKSPACE_DIR])")] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect::>(); - - uv_snapshot!(filters, command(&context) + uv_snapshot!(context.filters(), command(&context) .arg("requirements.in"), @r###" success: true exit_code: 0 @@ -2816,12 +2697,12 @@ requires-python = ">=3.8" ----- stderr ----- Built 1 editable in [TIME] Installed 1 package in [TIME] - + example==0.0.0 (from [WORKSPACE_DIR]) + + example==0.0.0 (from file://[TEMP_DIR]/editable) "### ); // Re-installing should be a no-op. - uv_snapshot!(filters, command(&context) + uv_snapshot!(context.filters(), command(&context) .arg("requirements.in"), @r###" success: true exit_code: 0 @@ -2845,7 +2726,7 @@ requires-python = ">=3.8" )?; // Re-installing should update the package. - uv_snapshot!(filters, command(&context) + uv_snapshot!(context.filters(), command(&context) .arg("requirements.in"), @r###" success: true exit_code: 0 @@ -2855,8 +2736,8 @@ requires-python = ">=3.8" Built 1 editable in [TIME] Uninstalled 1 package in [TIME] Installed 1 package in [TIME] - - example==0.0.0 (from [WORKSPACE_DIR]) - + example==0.0.0 (from [WORKSPACE_DIR]) + - example==0.0.0 (from file://[TEMP_DIR]/editable) + + example==0.0.0 (from file://[TEMP_DIR]/editable) "### ); @@ -2907,29 +2788,19 @@ fn compile_invalid_pyc_invalidation_mode() -> Result<()> { let context = TestContext::new("3.12"); let requirements_txt = context.temp_dir.child("requirements.txt"); - requirements_txt.touch()?; requirements_txt.write_str("MarkupSafe==2.1.3")?; - let site_packages = regex::escape( - &context - .site_packages() - .canonicalize() - .unwrap() - .user_display() - .to_string(), - ); - let filters: Vec<_> = [ - (site_packages.as_str(), "[SITE-PACKAGES]"), - (r"\.venv/lib/python3.12/site-packages", "[SITE-PACKAGES]"), - (r"\.venv/Lib/site-packages", "[SITE-PACKAGES]"), - ( - r#"\[SITE-PACKAGES\].*.py", received: "#, - r#"[SITE-PACKAGES]/[FIRST-FILE]", received: "#, - ), - ] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect(); + let filters: Vec<_> = context + .filters() + .into_iter() + .chain([ + // The first file can vary so we capture it here + ( + r#"\[SITE_PACKAGES\].*\.py", received: "#, + r#"[SITE_PACKAGES]/[FILE].py", received: "#, + ), + ]) + .collect(); uv_snapshot!(filters, command(&context) .arg("requirements.txt") @@ -2944,10 +2815,10 @@ fn compile_invalid_pyc_invalidation_mode() -> Result<()> { Resolved 1 package in [TIME] Downloaded 1 package in [TIME] Installed 1 package in [TIME] - error: Failed to bytecode-compile Python file in: [SITE-PACKAGES] + error: Failed to bytecode-compile Python file in: [SITE_PACKAGES]/ Caused by: Python process stderr: Invalid value for PYC_INVALIDATION_MODE "bogus", valid are "TIMESTAMP", "CHECKED_HASH", "UNCHECKED_HASH": - Caused by: Bytecode compilation failed, expected "[SITE-PACKAGES]/[FIRST-FILE]", received: "" + Caused by: Bytecode compilation failed, expected "[SITE_PACKAGES]/[FILE].py", received: "" "### ); @@ -2960,7 +2831,8 @@ fn requires_python_editable() -> Result<()> { let context = TestContext::new("3.12"); // Create an editable package with a `Requires-Python` constraint that is not met. - let editable_dir = assert_fs::TempDir::new()?; + let editable_dir = context.temp_dir.child("editable"); + editable_dir.create_dir_all()?; let pyproject_toml = editable_dir.child("pyproject.toml"); pyproject_toml.write_str( r#"[project] @@ -3031,7 +2903,8 @@ fn requires_python_direct_url() -> Result<()> { let context = TestContext::new("3.12"); // Create an editable package with a `Requires-Python` constraint that is not met. - let editable_dir = assert_fs::TempDir::new()?; + let editable_dir = context.temp_dir.child("editable"); + editable_dir.create_dir_all()?; let pyproject_toml = editable_dir.child("pyproject.toml"); pyproject_toml.write_str( r#"[project] diff --git a/crates/uv/tests/pip_uninstall.rs b/crates/uv/tests/pip_uninstall.rs index 390af1bd0..df3f44251 100644 --- a/crates/uv/tests/pip_uninstall.rs +++ b/crates/uv/tests/pip_uninstall.rs @@ -3,9 +3,8 @@ use std::process::Command; use anyhow::Result; use assert_cmd::prelude::*; use assert_fs::prelude::*; -use url::Url; -use common::{uv_snapshot, INSTA_FILTERS}; +use common::uv_snapshot; use crate::common::{get_bin, venv_to_interpreter, TestContext}; @@ -212,41 +211,17 @@ fn missing_record() -> Result<()> { .success(); // Delete the RECORD file. - let dist_info = fs_err::canonicalize(if cfg!(unix) { - context - .venv - .join("lib") - .join("python3.12") - .join("site-packages") - .join("MarkupSafe-2.1.3.dist-info") - } else if cfg!(windows) { - context - .venv - .join("Lib") - .join("site-packages") - .join("MarkupSafe-2.1.3.dist-info") - } else { - unimplemented!("Only Windows and Unix are supported") - }) - .unwrap(); + let dist_info = context.site_packages().join("MarkupSafe-2.1.3.dist-info"); fs_err::remove_file(dist_info.join("RECORD"))?; - let filters: Vec<_> = [( - r"RECORD file not found at: .*", - "RECORD file not found at: [RECORD]", - )] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect(); - - uv_snapshot!(filters, uninstall_command(&context) + uv_snapshot!(context.filters(), uninstall_command(&context) .arg("MarkupSafe"), @r###" success: false exit_code: 2 ----- stdout ----- ----- stderr ----- - error: Cannot uninstall package; RECORD file not found at: [RECORD] + error: Cannot uninstall package; RECORD file not found at: [SITE_PACKAGES]/MarkupSafe-2.1.3.dist-info/RECORD "### ); @@ -257,25 +232,19 @@ fn missing_record() -> Result<()> { fn uninstall_editable_by_name() -> Result<()> { let context = TestContext::new("3.12"); - let current_dir = std::env::current_dir()?; - let workspace_dir = regex::escape( - Url::from_directory_path(current_dir.join("..").join("..").canonicalize()?) - .unwrap() - .as_str(), - ); - - let filters: Vec<_> = [(workspace_dir.as_str(), "file://[WORKSPACE_DIR]/")] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect(); - let requirements_txt = context.temp_dir.child("requirements.txt"); requirements_txt.touch()?; - requirements_txt.write_str("-e ../../scripts/packages/poetry_editable")?; - + requirements_txt.write_str(&format!( + "-e {}", + context + .workspace_root + .join("scripts/packages/poetry_editable") + .as_os_str() + .to_str() + .expect("Path is valid unicode") + ))?; sync_command(&context) .arg(requirements_txt.path()) - .current_dir(¤t_dir) .assert() .success(); @@ -286,7 +255,7 @@ fn uninstall_editable_by_name() -> Result<()> { .success(); // Uninstall the editable by name. - uv_snapshot!(filters, uninstall_command(&context) + uv_snapshot!(context.filters(), uninstall_command(&context) .arg("poetry-editable"), @r###" success: true exit_code: 0 @@ -294,7 +263,7 @@ fn uninstall_editable_by_name() -> Result<()> { ----- stderr ----- Uninstalled 1 package in [TIME] - - poetry-editable==0.1.0 (from file://[WORKSPACE_DIR]/scripts/packages/poetry_editable) + - poetry-editable==0.1.0 (from file://[WORKSPACE]/scripts/packages/poetry_editable) "### ); @@ -311,25 +280,19 @@ fn uninstall_editable_by_name() -> Result<()> { fn uninstall_by_path() -> Result<()> { let context = TestContext::new("3.12"); - let current_dir = std::env::current_dir()?; - let workspace_dir = regex::escape( - Url::from_directory_path(current_dir.join("..").join("..").canonicalize()?) - .unwrap() - .as_str(), - ); - - let filters: Vec<_> = [(workspace_dir.as_str(), "file://[WORKSPACE_DIR]/")] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect(); - let requirements_txt = context.temp_dir.child("requirements.txt"); requirements_txt.touch()?; - requirements_txt.write_str("../../scripts/packages/poetry_editable")?; + requirements_txt.write_str( + context + .workspace_root + .join("scripts/packages/poetry_editable") + .as_os_str() + .to_str() + .expect("Path is valid unicode"), + )?; sync_command(&context) .arg(requirements_txt.path()) - .current_dir(¤t_dir) .assert() .success(); @@ -340,16 +303,15 @@ fn uninstall_by_path() -> Result<()> { .success(); // Uninstall the editable by path. - uv_snapshot!(filters, uninstall_command(&context) - .arg("../../scripts/packages/poetry_editable") - .current_dir(¤t_dir), @r###" + uv_snapshot!(context.filters(), uninstall_command(&context) + .arg(context.workspace_root.join("scripts/packages/poetry_editable")), @r###" success: true exit_code: 0 ----- stdout ----- ----- stderr ----- Uninstalled 1 package in [TIME] - - poetry-editable==0.1.0 (from file://[WORKSPACE_DIR]/scripts/packages/poetry_editable) + - poetry-editable==0.1.0 (from file://[WORKSPACE]/scripts/packages/poetry_editable) "### ); @@ -366,25 +328,19 @@ fn uninstall_by_path() -> Result<()> { fn uninstall_duplicate_by_path() -> Result<()> { let context = TestContext::new("3.12"); - let current_dir = std::env::current_dir()?; - let workspace_dir = regex::escape( - Url::from_directory_path(current_dir.join("..").join("..").canonicalize()?) - .unwrap() - .as_str(), - ); - - let filters: Vec<_> = [(workspace_dir.as_str(), "file://[WORKSPACE_DIR]/")] - .into_iter() - .chain(INSTA_FILTERS.to_vec()) - .collect(); - let requirements_txt = context.temp_dir.child("requirements.txt"); requirements_txt.touch()?; - requirements_txt.write_str("../../scripts/packages/poetry_editable")?; + requirements_txt.write_str( + context + .workspace_root + .join("scripts/packages/poetry_editable") + .as_os_str() + .to_str() + .expect("Path is valid unicode"), + )?; sync_command(&context) .arg(requirements_txt.path()) - .current_dir(¤t_dir) .assert() .success(); @@ -395,17 +351,16 @@ fn uninstall_duplicate_by_path() -> Result<()> { .success(); // Uninstall the editable by both path and name. - uv_snapshot!(filters, uninstall_command(&context) + uv_snapshot!(context.filters(), uninstall_command(&context) .arg("poetry-editable") - .arg("../../scripts/packages/poetry_editable") - .current_dir(¤t_dir), @r###" + .arg(context.workspace_root.join("scripts/packages/poetry_editable")), @r###" success: true exit_code: 0 ----- stdout ----- ----- stderr ----- Uninstalled 1 package in [TIME] - - poetry-editable==0.1.0 (from file://[WORKSPACE_DIR]/scripts/packages/poetry_editable) + - poetry-editable==0.1.0 (from file://[WORKSPACE]/scripts/packages/poetry_editable) "### ); @@ -420,7 +375,6 @@ fn uninstall_duplicate_by_path() -> Result<()> { /// Uninstall a duplicate package in a virtual environment. #[test] -#[cfg(unix)] fn uninstall_duplicate() -> Result<()> { use crate::common::copy_dir_all; @@ -450,12 +404,8 @@ fn uninstall_duplicate() -> Result<()> { // Copy the virtual environment to a new location. copy_dir_all( - context2 - .venv - .join("lib/python3.12/site-packages/pip-22.1.1.dist-info"), - context1 - .venv - .join("lib/python3.12/site-packages/pip-22.1.1.dist-info"), + context2.site_packages().join("pip-22.1.1.dist-info"), + context1.site_packages().join("pip-22.1.1.dist-info"), )?; // Run `pip uninstall`. diff --git a/scripts/scenarios/templates/compile.mustache b/scripts/scenarios/templates/compile.mustache index d0e5e44ae..fa18d1573 100644 --- a/scripts/scenarios/templates/compile.mustache +++ b/scripts/scenarios/templates/compile.mustache @@ -64,7 +64,7 @@ fn {{module_name}}() -> Result<()> { let python_versions = &[{{#environment.additional_python}}"{{.}}", {{/environment.additional_python}}]; // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"{{name}}-", "package-")); let requirements_in = context.temp_dir.child("requirements.in"); diff --git a/scripts/scenarios/templates/install.mustache b/scripts/scenarios/templates/install.mustache index 84c792b99..3d39720de 100644 --- a/scripts/scenarios/templates/install.mustache +++ b/scripts/scenarios/templates/install.mustache @@ -82,7 +82,7 @@ fn {{module_name}}() { let context = TestContext::new("{{environment.python}}"); // In addition to the standard filters, swap out package names for shorter messages - let mut filters = INSTA_FILTERS.to_vec(); + let mut filters = context.filters(); filters.push((r"{{name}}-", "package-")); uv_snapshot!(filters, command(&context)