Update test context to avoid discovery of external Pythons (#4222)

By setting the test search path to an empty path, we avoid accidentally
pulling interpreters from the system during a test case.

Cherry-picked from https://github.com/astral-sh/uv/pull/4214
This commit is contained in:
Zanie Blue 2024-06-10 18:26:53 -04:00 committed by GitHub
parent 98d1ea6bb0
commit 546e23bb1d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 26 additions and 12 deletions

View file

@ -45,6 +45,12 @@ pub const INSTA_FILTERS: &[(&str, &str)] = &[
), ),
]; ];
/// Create a context for tests which simplfiies shared behavior across tests.
///
/// * Set the current directory to a temporary directory (`temp_dir`).
/// * Set the cache dir to a different temporary directory (`cache_dir`).
/// * Set a cutoff for versions used in the resolution so the snapshots don't change after a new release.
/// * Set the venv to a fresh `.venv` in `temp_dir`.
#[derive(Debug)] #[derive(Debug)]
pub struct TestContext { pub struct TestContext {
pub temp_dir: assert_fs::TempDir, pub temp_dir: assert_fs::TempDir,
@ -153,11 +159,7 @@ impl TestContext {
} }
} }
/// Set shared defaults between tests: /// Create a `pip compile` command for testing.
/// * Set the current directory to a temporary directory (`temp_dir`).
/// * Set the cache dir to a different temporary directory (`cache_dir`).
/// * Set a cutoff for versions used in the resolution so the snapshots don't change after a new release.
/// * Set the venv to a fresh `.venv` in `temp_dir`.
pub fn compile(&self) -> std::process::Command { pub fn compile(&self) -> std::process::Command {
let mut command = self.compile_without_exclude_newer(); let mut command = self.compile_without_exclude_newer();
command.arg("--exclude-newer").arg(EXCLUDE_NEWER); command.arg("--exclude-newer").arg(EXCLUDE_NEWER);
@ -178,6 +180,7 @@ impl TestContext {
.arg(self.cache_dir.path()) .arg(self.cache_dir.path())
.env("VIRTUAL_ENV", self.venv.as_os_str()) .env("VIRTUAL_ENV", self.venv.as_os_str())
.env("UV_NO_WRAP", "1") .env("UV_NO_WRAP", "1")
.env("UV_TEST_PYTHON_PATH", "/dev/null")
.current_dir(self.temp_dir.path()); .current_dir(self.temp_dir.path());
if cfg!(all(windows, debug_assertions)) { if cfg!(all(windows, debug_assertions)) {
@ -211,6 +214,7 @@ impl TestContext {
.arg(self.cache_dir.path()) .arg(self.cache_dir.path())
.env("VIRTUAL_ENV", self.venv.as_os_str()) .env("VIRTUAL_ENV", self.venv.as_os_str())
.env("UV_NO_WRAP", "1") .env("UV_NO_WRAP", "1")
.env("UV_TEST_PYTHON_PATH", "/dev/null")
.current_dir(&self.temp_dir); .current_dir(&self.temp_dir);
if cfg!(all(windows, debug_assertions)) { if cfg!(all(windows, debug_assertions)) {
@ -231,6 +235,7 @@ impl TestContext {
.arg(self.cache_dir.path()) .arg(self.cache_dir.path())
.env("VIRTUAL_ENV", self.venv.as_os_str()) .env("VIRTUAL_ENV", self.venv.as_os_str())
.env("UV_NO_WRAP", "1") .env("UV_NO_WRAP", "1")
.env("UV_TEST_PYTHON_PATH", "/dev/null")
.current_dir(&self.temp_dir); .current_dir(&self.temp_dir);
if cfg!(all(windows, debug_assertions)) { if cfg!(all(windows, debug_assertions)) {
@ -263,6 +268,7 @@ impl TestContext {
.arg(self.cache_dir.path()) .arg(self.cache_dir.path())
.env("VIRTUAL_ENV", self.venv.as_os_str()) .env("VIRTUAL_ENV", self.venv.as_os_str())
.env("UV_NO_WRAP", "1") .env("UV_NO_WRAP", "1")
.env("UV_TEST_PYTHON_PATH", "/dev/null")
.current_dir(&self.temp_dir); .current_dir(&self.temp_dir);
if cfg!(all(windows, debug_assertions)) { if cfg!(all(windows, debug_assertions)) {
@ -295,6 +301,7 @@ impl TestContext {
.arg(self.cache_dir.path()) .arg(self.cache_dir.path())
.env("VIRTUAL_ENV", self.venv.as_os_str()) .env("VIRTUAL_ENV", self.venv.as_os_str())
.env("UV_NO_WRAP", "1") .env("UV_NO_WRAP", "1")
.env("UV_TEST_PYTHON_PATH", "/dev/null")
.current_dir(&self.temp_dir); .current_dir(&self.temp_dir);
if cfg!(all(windows, debug_assertions)) { if cfg!(all(windows, debug_assertions)) {

View file

@ -4,8 +4,7 @@ use anyhow::Result;
use assert_fs::prelude::*; use assert_fs::prelude::*;
use indoc::indoc; use indoc::indoc;
use crate::common::get_toolchain; use common::{python_path_with_versions, uv_snapshot, TestContext};
use common::{uv_snapshot, TestContext};
mod common; mod common;
@ -13,6 +12,8 @@ mod common;
#[test] #[test]
fn run_with_python_version() -> Result<()> { fn run_with_python_version() -> Result<()> {
let context = TestContext::new("3.12"); let context = TestContext::new("3.12");
let python_path = python_path_with_versions(&context.temp_dir, &["3.11", "3.12"])
.expect("Failed to create Python test path");
let pyproject_toml = context.temp_dir.child("pyproject.toml"); let pyproject_toml = context.temp_dir.child("pyproject.toml");
pyproject_toml.write_str(indoc! { r#" pyproject_toml.write_str(indoc! { r#"
@ -43,7 +44,8 @@ fn run_with_python_version() -> Result<()> {
.arg("--preview") .arg("--preview")
.arg("python") .arg("python")
.arg("-B") .arg("-B")
.arg("main.py"); .arg("main.py")
.env("UV_TEST_PYTHON_PATH", &python_path);
uv_snapshot!(context.filters(), command_with_args, @r###" uv_snapshot!(context.filters(), command_with_args, @r###"
success: true success: true
exit_code: 0 exit_code: 0
@ -66,10 +68,11 @@ fn run_with_python_version() -> Result<()> {
let command_with_args = command let command_with_args = command
.arg("--preview") .arg("--preview")
.arg("-p") .arg("-p")
.arg(get_toolchain("3.12")) .arg("3.12")
.arg("python") .arg("python")
.arg("-B") .arg("-B")
.arg("main.py"); .arg("main.py")
.env("UV_TEST_PYTHON_PATH", &python_path);
uv_snapshot!(context.filters(), command_with_args, @r###" uv_snapshot!(context.filters(), command_with_args, @r###"
success: true success: true
exit_code: 0 exit_code: 0
@ -87,16 +90,20 @@ fn run_with_python_version() -> Result<()> {
let command_with_args = command let command_with_args = command
.arg("--preview") .arg("--preview")
.arg("-p") .arg("-p")
.arg(get_toolchain("3.11")) .arg("3.11")
.arg("python") .arg("python")
.arg("-B") .arg("-B")
.arg("main.py"); .arg("main.py")
.env("UV_TEST_PYTHON_PATH", &python_path)
.env_remove("VIRTUAL_ENV");
let mut filters = context.filters(); let mut filters = context.filters();
filters.push(( filters.push((
r"Using Python 3.11.\d+ interpreter at: .*", r"Using Python 3.11.\d+ interpreter at: .*",
"Using Python 3.11.[X] interpreter at: [PYTHON]", "Using Python 3.11.[X] interpreter at: [PYTHON]",
)); ));
filters.push((r"3.11.\d+", "3.11.[X]")); filters.push((r"3.11.\d+", "3.11.[X]"));
uv_snapshot!(filters, command_with_args, @r###" uv_snapshot!(filters, command_with_args, @r###"
success: true success: true
exit_code: 0 exit_code: 0