mirror of
https://github.com/astral-sh/uv.git
synced 2025-07-07 21:35:00 +00:00
Require tests to opt-in to managed Python installation (#10912)
First of all, I want to test automatic managed installs (see #10913) and need to set that up. Second of all, some tests were _implicitly_ downloading interpreters instead of using the one from their context — which is unexpected and naughty and very slow.
This commit is contained in:
parent
a05b0e0346
commit
fd5131cb7c
5 changed files with 60 additions and 44 deletions
|
@ -102,6 +102,9 @@ pub struct TestContext {
|
|||
/// Standard filters for this test context.
|
||||
filters: Vec<(String, String)>,
|
||||
|
||||
/// Extra environment variables to apply to all commands.
|
||||
extra_env: Vec<(OsString, OsString)>,
|
||||
|
||||
#[allow(dead_code)]
|
||||
_root: tempfile::TempDir,
|
||||
}
|
||||
|
@ -233,6 +236,29 @@ impl TestContext {
|
|||
self
|
||||
}
|
||||
|
||||
/// Add extra directories and configuration for managed Python installations.
|
||||
#[must_use]
|
||||
pub fn with_managed_python_dirs(mut self) -> Self {
|
||||
let managed = self.temp_dir.join("managed");
|
||||
let bin = self.temp_dir.join("bin");
|
||||
|
||||
self.extra_env.push((
|
||||
EnvVars::PATH.into(),
|
||||
env::join_paths(std::iter::once(bin.clone()).chain(env::split_paths(
|
||||
&env::var(EnvVars::PATH).unwrap_or_default(),
|
||||
)))
|
||||
.unwrap(),
|
||||
));
|
||||
self.extra_env
|
||||
.push((EnvVars::UV_PYTHON_BIN_DIR.into(), bin.into()));
|
||||
self.extra_env
|
||||
.push((EnvVars::UV_PYTHON_INSTALL_DIR.into(), managed.into()));
|
||||
self.extra_env
|
||||
.push((EnvVars::UV_PYTHON_DOWNLOADS.into(), "automatic".into()));
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// Discover the path to the XDG state directory. We use this, rather than the OS-specific
|
||||
/// temporary directory, because on macOS (and Windows on GitHub Actions), they involve
|
||||
/// symlinks. (On macOS, the temporary directory is, like `/var/...`, which resolves to
|
||||
|
@ -456,6 +482,7 @@ impl TestContext {
|
|||
python_version,
|
||||
python_versions,
|
||||
filters,
|
||||
extra_env: vec![],
|
||||
_root: root,
|
||||
}
|
||||
}
|
||||
|
@ -510,12 +537,18 @@ impl TestContext {
|
|||
.env(EnvVars::PATH, path)
|
||||
.env(EnvVars::HOME, self.home_dir.as_os_str())
|
||||
.env(EnvVars::UV_PYTHON_INSTALL_DIR, "")
|
||||
// Installations are not allowed by default; see `Self::with_managed_python_dirs`
|
||||
.env(EnvVars::UV_PYTHON_DOWNLOADS, "never")
|
||||
.env(EnvVars::UV_TEST_PYTHON_PATH, self.python_path())
|
||||
.env(EnvVars::UV_EXCLUDE_NEWER, EXCLUDE_NEWER)
|
||||
.env_remove(EnvVars::UV_CACHE_DIR)
|
||||
.env_remove(EnvVars::UV_TOOL_BIN_DIR)
|
||||
.current_dir(self.temp_dir.path());
|
||||
|
||||
for (key, value) in &self.extra_env {
|
||||
command.env(key, value);
|
||||
}
|
||||
|
||||
if activate_venv {
|
||||
command.env(EnvVars::VIRTUAL_ENV, self.venv.as_os_str());
|
||||
}
|
||||
|
@ -677,21 +710,10 @@ impl TestContext {
|
|||
/// Create a `uv python install` command with options shared across scenarios.
|
||||
pub fn python_install(&self) -> Command {
|
||||
let mut command = self.new_command();
|
||||
let managed = self.temp_dir.join("managed");
|
||||
let bin = self.temp_dir.join("bin");
|
||||
self.add_shared_args(&mut command, true);
|
||||
command
|
||||
.arg("python")
|
||||
.arg("install")
|
||||
.env(EnvVars::UV_PYTHON_INSTALL_DIR, managed)
|
||||
.env(EnvVars::UV_PYTHON_BIN_DIR, bin.as_os_str())
|
||||
.env(
|
||||
EnvVars::PATH,
|
||||
env::join_paths(std::iter::once(bin).chain(env::split_paths(
|
||||
&env::var(EnvVars::PATH).unwrap_or_default(),
|
||||
)))
|
||||
.unwrap(),
|
||||
)
|
||||
.current_dir(&self.temp_dir);
|
||||
command
|
||||
}
|
||||
|
@ -699,14 +721,10 @@ impl TestContext {
|
|||
/// Create a `uv python uninstall` command with options shared across scenarios.
|
||||
pub fn python_uninstall(&self) -> Command {
|
||||
let mut command = self.new_command();
|
||||
let managed = self.temp_dir.join("managed");
|
||||
let bin = self.temp_dir.join("bin");
|
||||
self.add_shared_args(&mut command, true);
|
||||
command
|
||||
.arg("python")
|
||||
.arg("uninstall")
|
||||
.env(EnvVars::UV_PYTHON_INSTALL_DIR, managed)
|
||||
.env(EnvVars::UV_PYTHON_BIN_DIR, bin)
|
||||
.current_dir(&self.temp_dir);
|
||||
command
|
||||
}
|
||||
|
|
|
@ -3394,7 +3394,7 @@ fn shared_optional_dependency_mixed1() -> Result<()> {
|
|||
/// Regression test for: <https://github.com/astral-sh/uv/issues/9640>
|
||||
#[test]
|
||||
fn shared_optional_dependency_extra2() -> Result<()> {
|
||||
let context = TestContext::new("3.12");
|
||||
let context = TestContext::new("3.11");
|
||||
|
||||
let pyproject_toml = context.temp_dir.child("pyproject.toml");
|
||||
pyproject_toml.write_str(
|
||||
|
@ -3432,9 +3432,6 @@ fn shared_optional_dependency_extra2() -> Result<()> {
|
|||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Using CPython 3.11.11
|
||||
Removed virtual environment at: .venv
|
||||
Creating virtual environment at: .venv
|
||||
Resolved 5 packages in [TIME]
|
||||
Prepared 3 packages in [TIME]
|
||||
Installed 3 packages in [TIME]
|
||||
|
@ -3536,7 +3533,7 @@ fn shared_optional_dependency_extra2() -> Result<()> {
|
|||
/// Regression test for: <https://github.com/astral-sh/uv/issues/9640>
|
||||
#[test]
|
||||
fn shared_optional_dependency_group2() -> Result<()> {
|
||||
let context = TestContext::new("3.12");
|
||||
let context = TestContext::new("3.11");
|
||||
|
||||
let pyproject_toml = context.temp_dir.child("pyproject.toml");
|
||||
pyproject_toml.write_str(
|
||||
|
@ -3574,9 +3571,6 @@ fn shared_optional_dependency_group2() -> Result<()> {
|
|||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Using CPython 3.11.11
|
||||
Removed virtual environment at: .venv
|
||||
Creating virtual environment at: .venv
|
||||
Resolved 5 packages in [TIME]
|
||||
Prepared 3 packages in [TIME]
|
||||
Installed 3 packages in [TIME]
|
||||
|
@ -3682,7 +3676,7 @@ fn shared_optional_dependency_group2() -> Result<()> {
|
|||
/// Regression test for: <https://github.com/astral-sh/uv/issues/9640>
|
||||
#[test]
|
||||
fn shared_optional_dependency_mixed2() -> Result<()> {
|
||||
let context = TestContext::new("3.12");
|
||||
let context = TestContext::new("3.11");
|
||||
|
||||
let pyproject_toml = context.temp_dir.child("pyproject.toml");
|
||||
pyproject_toml.write_str(
|
||||
|
@ -3722,9 +3716,6 @@ fn shared_optional_dependency_mixed2() -> Result<()> {
|
|||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Using CPython 3.11.11
|
||||
Removed virtual environment at: .venv
|
||||
Creating virtual environment at: .venv
|
||||
Resolved 5 packages in [TIME]
|
||||
Prepared 3 packages in [TIME]
|
||||
Installed 3 packages in [TIME]
|
||||
|
@ -4364,7 +4355,7 @@ fn shared_dependency_mixed() -> Result<()> {
|
|||
/// Ref <https://github.com/astral-sh/uv/issues/9289>
|
||||
#[test]
|
||||
fn extras_are_namespaced() -> Result<()> {
|
||||
let context = TestContext::new("3.12");
|
||||
let context = TestContext::new("3.11");
|
||||
|
||||
let root_pyproject_toml = context.temp_dir.child("pyproject.toml");
|
||||
root_pyproject_toml.write_str(
|
||||
|
@ -4423,9 +4414,6 @@ conflicts = [
|
|||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Using CPython 3.11.11
|
||||
Removed virtual environment at: .venv
|
||||
Creating virtual environment at: .venv
|
||||
Resolved 7 packages in [TIME]
|
||||
Prepared 3 packages in [TIME]
|
||||
Installed 3 packages in [TIME]
|
||||
|
@ -7297,7 +7285,7 @@ fn deduplicate_resolution_markers() -> Result<()> {
|
|||
|
||||
#[test]
|
||||
fn overlapping_resolution_markers() -> Result<()> {
|
||||
let context = TestContext::new("3.12");
|
||||
let context = TestContext::new("3.10");
|
||||
|
||||
let pyproject_toml = context.temp_dir.child("pyproject.toml");
|
||||
pyproject_toml.write_str(
|
||||
|
@ -7305,7 +7293,7 @@ fn overlapping_resolution_markers() -> Result<()> {
|
|||
[project]
|
||||
name = "ads-mega-model"
|
||||
version = "0.1.0"
|
||||
requires-python = "==3.10.12"
|
||||
requires-python = "==3.10.*"
|
||||
dependencies = [
|
||||
"wandb==0.17.6",
|
||||
]
|
||||
|
@ -7344,7 +7332,6 @@ fn overlapping_resolution_markers() -> Result<()> {
|
|||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Using CPython 3.10.12
|
||||
Resolved 45 packages in [TIME]
|
||||
"###);
|
||||
|
||||
|
@ -7356,7 +7343,7 @@ fn overlapping_resolution_markers() -> Result<()> {
|
|||
lock,
|
||||
@r###"
|
||||
version = 1
|
||||
requires-python = "==3.10.12"
|
||||
requires-python = "==3.10.*"
|
||||
resolution-markers = [
|
||||
"sys_platform == 'linux' and extra != 'extra-14-ads-mega-model-cpu' and extra == 'extra-14-ads-mega-model-cu118'",
|
||||
"sys_platform != 'linux' and extra != 'extra-14-ads-mega-model-cpu' and extra == 'extra-14-ads-mega-model-cu118'",
|
||||
|
|
|
@ -13,7 +13,8 @@ use crate::common::{uv_snapshot, TestContext};
|
|||
fn python_install() {
|
||||
let context: TestContext = TestContext::new_with_versions(&[])
|
||||
.with_filtered_python_keys()
|
||||
.with_filtered_exe_suffix();
|
||||
.with_filtered_exe_suffix()
|
||||
.with_managed_python_dirs();
|
||||
|
||||
// Install the latest version
|
||||
uv_snapshot!(context.filters(), context.python_install(), @r###"
|
||||
|
@ -95,7 +96,8 @@ fn python_install() {
|
|||
fn python_install_preview() {
|
||||
let context: TestContext = TestContext::new_with_versions(&[])
|
||||
.with_filtered_python_keys()
|
||||
.with_filtered_exe_suffix();
|
||||
.with_filtered_exe_suffix()
|
||||
.with_managed_python_dirs();
|
||||
|
||||
// Install the latest version
|
||||
uv_snapshot!(context.filters(), context.python_install().arg("--preview"), @r###"
|
||||
|
@ -269,7 +271,8 @@ fn python_install_preview() {
|
|||
fn python_install_preview_upgrade() {
|
||||
let context = TestContext::new_with_versions(&[])
|
||||
.with_filtered_python_keys()
|
||||
.with_filtered_exe_suffix();
|
||||
.with_filtered_exe_suffix()
|
||||
.with_managed_python_dirs();
|
||||
|
||||
let bin_python = context
|
||||
.temp_dir
|
||||
|
@ -408,7 +411,8 @@ fn python_install_preview_upgrade() {
|
|||
fn python_install_freethreaded() {
|
||||
let context: TestContext = TestContext::new_with_versions(&[])
|
||||
.with_filtered_python_keys()
|
||||
.with_filtered_exe_suffix();
|
||||
.with_filtered_exe_suffix()
|
||||
.with_managed_python_dirs();
|
||||
|
||||
// Install the latest version
|
||||
uv_snapshot!(context.filters(), context.python_install().arg("--preview").arg("3.13t"), @r###"
|
||||
|
@ -482,7 +486,8 @@ fn python_install_freethreaded() {
|
|||
fn python_install_invalid_request() {
|
||||
let context: TestContext = TestContext::new_with_versions(&[])
|
||||
.with_filtered_python_keys()
|
||||
.with_filtered_exe_suffix();
|
||||
.with_filtered_exe_suffix()
|
||||
.with_managed_python_dirs();
|
||||
|
||||
// Request something that is not a Python version
|
||||
uv_snapshot!(context.filters(), context.python_install().arg("foobar"), @r###"
|
||||
|
@ -519,7 +524,8 @@ fn python_install_invalid_request() {
|
|||
fn python_install_default() {
|
||||
let context: TestContext = TestContext::new_with_versions(&[])
|
||||
.with_filtered_python_keys()
|
||||
.with_filtered_exe_suffix();
|
||||
.with_filtered_exe_suffix()
|
||||
.with_managed_python_dirs();
|
||||
|
||||
let bin_python_minor_13 = context
|
||||
.temp_dir
|
||||
|
@ -815,7 +821,7 @@ fn read_link_path(path: &Path) -> String {
|
|||
|
||||
#[test]
|
||||
fn python_install_unknown() {
|
||||
let context: TestContext = TestContext::new_with_versions(&[]);
|
||||
let context: TestContext = TestContext::new_with_versions(&[]).with_managed_python_dirs();
|
||||
|
||||
// An unknown request
|
||||
uv_snapshot!(context.filters(), context.python_install().arg("foobar"), @r###"
|
||||
|
@ -848,7 +854,8 @@ fn python_install_preview_broken_link() {
|
|||
|
||||
let context: TestContext = TestContext::new_with_versions(&[])
|
||||
.with_filtered_python_keys()
|
||||
.with_filtered_exe_suffix();
|
||||
.with_filtered_exe_suffix()
|
||||
.with_managed_python_dirs();
|
||||
|
||||
let bin_python = context.temp_dir.child("bin").child("python3.13");
|
||||
|
||||
|
@ -883,7 +890,9 @@ fn python_dylib_install_name_is_patched_on_install() {
|
|||
use assert_cmd::assert::OutputAssertExt;
|
||||
use uv_python::managed::platform_key_from_env;
|
||||
|
||||
let context: TestContext = TestContext::new_with_versions(&[]).with_filtered_python_keys();
|
||||
let context: TestContext = TestContext::new_with_versions(&[])
|
||||
.with_filtered_python_keys()
|
||||
.with_managed_python_dirs();
|
||||
|
||||
// Install the latest version
|
||||
context
|
||||
|
|
1
scripts/packages/anyio_local/.python-version
Normal file
1
scripts/packages/anyio_local/.python-version
Normal file
|
@ -0,0 +1 @@
|
|||
3.12
|
1
scripts/packages/built-by-uv/.python-version
Normal file
1
scripts/packages/built-by-uv/.python-version
Normal file
|
@ -0,0 +1 @@
|
|||
3.12
|
Loading…
Add table
Add a link
Reference in a new issue