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
6 changes: 6 additions & 0 deletions crates/uv-static/src/env_vars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,12 @@ impl EnvVars {
#[attr_added_in("0.9.15")]
pub const UV_INTERNAL__TEST_LFS_DISABLED: &'static str = "UV_INTERNAL__TEST_LFS_DISABLED";

/// Marker variable to track whether `PYTHONHOME` was set by uv.
/// Used by the Windows trampoline to distinguish uv-set values from user-set values.
#[attr_hidden]
#[attr_added_in("next release")]
pub const UV_INTERNAL__PYTHONHOME: &'static str = "UV_INTERNAL__PYTHONHOME";

/// Path to system-level configuration directory on Unix systems.
#[attr_added_in("0.4.26")]
pub const XDG_CONFIG_DIRS: &'static str = "XDG_CONFIG_DIRS";
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
41 changes: 28 additions & 13 deletions crates/uv-trampoline/src/bounce.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,20 +146,35 @@ fn make_child_cmdline() -> CString {
// be correctly detected when using trampolines.
std::env::set_var(EnvVars::PYVENV_LAUNCHER, &executable_name);

// If this is not a virtual environment and `PYTHONHOME` has
// not been set, then set `PYTHONHOME` to the parent directory of
// the executable. This ensures that the correct installation
// directories are added to `sys.path` when running with a junction
// trampoline.
let python_home_set =
std::env::var(EnvVars::PYTHONHOME).is_ok_and(|home| !home.is_empty());
if !is_virtualenv(python_exe.as_path()) && !python_home_set {
std::env::set_var(
EnvVars::PYTHONHOME,
python_exe
// If this is not a virtual environment, set `PYTHONHOME` to
// the parent directory of the executable. This ensures that
// the correct installation directories are added to `sys.path`
// when running with a junction trampoline.
//
// We use a marker variable (`UV_INTERNAL__PYTHONHOME`) to track
// whether `PYTHONHOME` was set by uv. This allows us to:
// - Override inherited `PYTHONHOME` from parent Python processes
// - Preserve user-defined `PYTHONHOME` values
if !is_virtualenv(python_exe.as_path()) {
let python_home = std::env::var(EnvVars::PYTHONHOME).ok();
let marker = std::env::var(EnvVars::UV_INTERNAL__PYTHONHOME).ok();

// Only set `PYTHONHOME` if:
// - It's not set, OR
// - It was set by uv (marker matches current `PYTHONHOME`)
let should_override = match (&python_home, &marker) {
(None, _) => true,
(Some(home), Some(m)) if home == m => true,
_ => false,
};

if should_override {
let home = python_exe
.parent()
.expect("Python executable should have a parent directory"),
);
.expect("Python executable should have a parent directory");
std::env::set_var(EnvVars::PYTHONHOME, home);
std::env::set_var(EnvVars::UV_INTERNAL__PYTHONHOME, home);
}
}
}
}
Expand Down
Loading