From 327c7415f309a2564cc7f1ebeea8afdaa81e4037 Mon Sep 17 00:00:00 2001 From: Aria Desires Date: Fri, 19 Jun 2026 14:45:30 -0400 Subject: [PATCH] Reapply "Fix transparent Python upgrades in project environments" (#19925) This reverts commit a05827265413fc168105aa14ef5d65243eadaaee. --- crates/uv-virtualenv/src/virtualenv.rs | 6 +- crates/uv/tests/python/python_upgrade.rs | 84 +++++++++++++++++++++++- 2 files changed, 88 insertions(+), 2 deletions(-) diff --git a/crates/uv-virtualenv/src/virtualenv.rs b/crates/uv-virtualenv/src/virtualenv.rs index ddc15ca349..2669f2a28d 100644 --- a/crates/uv-virtualenv/src/virtualenv.rs +++ b/crates/uv-virtualenv/src/virtualenv.rs @@ -528,7 +528,11 @@ pub(crate) fn create( ("uv".to_string(), version().to_string()), ( "version_info".to_string(), - interpreter.markers().python_full_version().string.clone(), + if using_minor_version_link { + interpreter.python_minor_version().to_string() + } else { + interpreter.markers().python_full_version().string.clone() + }, ), ( "include-system-site-packages".to_string(), diff --git a/crates/uv/tests/python/python_upgrade.rs b/crates/uv/tests/python/python_upgrade.rs index 33411f0fb8..529517922a 100644 --- a/crates/uv/tests/python/python_upgrade.rs +++ b/crates/uv/tests/python/python_upgrade.rs @@ -2,6 +2,7 @@ use anyhow::Result; use assert_cmd::assert::OutputAssertExt; use assert_fs::fixture::{FileTouch, FileWriteStr}; use assert_fs::prelude::PathChild; +use insta::assert_snapshot; use uv_python::managed::platform_key_from_env; use uv_static::EnvVars; use uv_test::{LATEST_PYTHON_3_12, uv_snapshot}; @@ -839,6 +840,73 @@ fn python_upgrade_build_version() { "); } +// A project environment should survive a transparent Python patch upgrade. +#[test] +fn python_sync_transparent_patch_upgrade_reuses_environment() -> Result<()> { + let context = uv_test::test_context_with_versions!(&[]) + .with_python_download_cache() + .with_filtered_python_keys() + .with_filtered_exe_suffix() + .with_managed_python_dirs() + .with_filtered_latest_python_versions() + .with_pyvenv_cfg_filters(); + + context.temp_dir.child("pyproject.toml").write_str( + r#" + [project] + name = "project" + version = "0.1.0" + requires-python = ">=3.10" + "#, + )?; + + context.python_install().arg("3.10.17").assert().success(); + context + .sync() + .arg("--python") + .arg("3.10") + .assert() + .success(); + + // The minor-only `version_info` allows compatibility checks to accept a newer patch. + let pyvenv_cfg = fs_err::read_to_string(context.venv.child("pyvenv.cfg"))?; + insta::with_settings!({ filters => context.filters() }, { + assert_snapshot!(pyvenv_cfg, @r" + home = [PYTHON_HOME] + implementation = CPython + uv = [UV_VERSION] + version_info = 3.10 + include-system-site-packages = false + prompt = project + "); + }); + + context.python_upgrade().arg("3.10").assert().success(); + + // The sync should not report removing or creating the environment. + uv_snapshot!(context.filters(), context.sync().arg("--python").arg("3.10"), @r" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Resolved 1 package in [TIME] + Checked in [TIME] + "); + + // The reused environment should run the upgraded Python patch. + uv_snapshot!(context.filters(), context.python_command().arg("--version"), @r" + success: true + exit_code: 0 + ----- stdout ----- + Python 3.10.[LATEST] + + ----- stderr ----- + "); + + Ok(()) +} + // Regression test for . // // A virtual environment created by `uv sync` should pin to a patch version @@ -852,7 +920,8 @@ fn python_sync_honors_pinned_patch_version() -> Result<()> { .with_filtered_python_keys() .with_filtered_exe_suffix() .with_managed_python_dirs() - .with_filtered_latest_python_versions(); + .with_filtered_latest_python_versions() + .with_pyvenv_cfg_filters(); let pyproject_toml = context.temp_dir.child("pyproject.toml"); pyproject_toml.write_str( @@ -898,6 +967,19 @@ fn python_sync_honors_pinned_patch_version() -> Result<()> { Checked in [TIME] "); + // An exact-patch environment must retain the patch in `version_info`. + let pyvenv_cfg = fs_err::read_to_string(context.venv.child("pyvenv.cfg"))?; + insta::with_settings!({ filters => context.filters() }, { + assert_snapshot!(pyvenv_cfg, @r" + home = [PYTHON_HOME] + implementation = CPython + uv = [UV_VERSION] + version_info = 3.10.17 + include-system-site-packages = false + prompt = project + "); + }); + // Install a newer patch version, which moves the mutable `cpython-3.10` // minor-version link to the newer release. uv_snapshot!(context.filters(), context.python_upgrade().arg("3.10"), @r"