Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 33 additions & 15 deletions crates/uv/tests/it/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -456,6 +482,7 @@ impl TestContext {
python_version,
python_versions,
filters,
extra_env: vec![],
_root: root,
}
}
Expand Down Expand Up @@ -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")
Comment on lines +540 to +541
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This bans Python downloads in most tests.

.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());
}
Expand Down Expand Up @@ -677,36 +710,21 @@ 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
}

/// 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
}
Expand Down
35 changes: 11 additions & 24 deletions crates/uv/tests/it/lock_conflict.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -7297,15 +7285,15 @@ 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(
r#"
[project]
name = "ads-mega-model"
version = "0.1.0"
requires-python = "==3.10.12"
requires-python = "==3.10.*"
dependencies = [
"wandb==0.17.6",
]
Expand Down Expand Up @@ -7344,7 +7332,6 @@ fn overlapping_resolution_markers() -> Result<()> {
----- stdout -----

----- stderr -----
Using CPython 3.10.12
Resolved 45 packages in [TIME]
"###);

Expand All @@ -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'",
Expand Down Expand Up @@ -7662,12 +7649,12 @@ fn overlapping_resolution_markers() -> Result<()> {

[[package]]
name = "nvidia-nvjitlink-cu12"
version = "12.6.85"
version = "12.8.61"
Comment on lines +7665 to +7652
Copy link
Copy Markdown
Member Author

@zanieb zanieb Jan 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confused this changed 🤔

source = { registry = "https://pypi.org/simple" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/9d/d7/c5383e47c7e9bf1c99d5bd2a8c935af2b6d705ad831a7ec5c97db4d82f4f/nvidia_nvjitlink_cu12-12.6.85-py3-none-manylinux2010_x86_64.manylinux_2_12_x86_64.whl", hash = "sha256:eedc36df9e88b682efe4309aa16b5b4e78c2407eac59e8c10a6a47535164369a", size = 19744971 },
{ url = "https://files.pythonhosted.org/packages/31/db/dc71113d441f208cdfe7ae10d4983884e13f464a6252450693365e166dcf/nvidia_nvjitlink_cu12-12.6.85-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cf4eaa7d4b6b543ffd69d6abfb11efdeb2db48270d94dfd3a452c24150829e41", size = 19270338 },
{ url = "https://files.pythonhosted.org/packages/89/76/93c1467b1387387440a4d25102d86b7794535449b689f8e2dc22c1c8ff7f/nvidia_nvjitlink_cu12-12.6.85-py3-none-win_amd64.whl", hash = "sha256:e61120e52ed675747825cdd16febc6a0730537451d867ee58bee3853b1b13d1c", size = 161908572 },
{ url = "https://files.pythonhosted.org/packages/03/f8/9d85593582bd99b8d7c65634d2304780aefade049b2b94d96e44084be90b/nvidia_nvjitlink_cu12-12.8.61-py3-none-manylinux2010_x86_64.manylinux_2_12_x86_64.whl", hash = "sha256:45fd79f2ae20bd67e8bc411055939049873bfd8fac70ff13bd4865e0b9bdab17", size = 39243473 },
{ url = "https://files.pythonhosted.org/packages/af/53/698f3758f48c5fcb1112721e40cc6714da3980d3c7e93bae5b29dafa9857/nvidia_nvjitlink_cu12-12.8.61-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:9b80ecab31085dda3ce3b41d043be0ec739216c3fc633b8abe212d5a30026df0", size = 38374634 },
{ url = "https://files.pythonhosted.org/packages/7f/c6/0d1b2bfeb2ef42c06db0570c4d081e5cde4450b54c09e43165126cfe6ff6/nvidia_nvjitlink_cu12-12.8.61-py3-none-win_amd64.whl", hash = "sha256:1166a964d25fdc0eae497574d38824305195a5283324a21ccb0ce0c802cbf41c", size = 268514099 },
]

[[package]]
Expand Down
27 changes: 18 additions & 9 deletions crates/uv/tests/it/python_install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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###"
Expand Down Expand Up @@ -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###"
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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###"
Expand Down Expand Up @@ -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###"
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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###"
Expand Down Expand Up @@ -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");

Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions scripts/packages/anyio_local/.python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.12
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Annoying, but... uv build treats this package as the start of the workspace and it picks up the .python-version pin in our repository (3.13) which cannot be satisfied during the build tests (which use 3.12).

The better solution here is to copy this project into the test context instead of using this possibly dirty directory in each test! but I don't want to deal with that here.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is such a mood 😭

1 change: 1 addition & 0 deletions scripts/packages/built-by-uv/.python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.12