Skip to content
Closed
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
11 changes: 10 additions & 1 deletion crates/uv-python/src/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use uv_pep508::{MarkerEnvironment, StringVersion};
use uv_platform::{Arch, Libc, Os};
use uv_platform_tags::{Platform, Tags, TagsError, TagsOptions};
use uv_pypi_types::{ResolverMarkerEnvironment, Scheme};
use uv_static::EnvVars;

use crate::implementation::LenientImplementationName;
use crate::managed::ManagedPythonInstallations;
Expand Down Expand Up @@ -1149,6 +1150,8 @@ impl InterpreterInfo {
};

let canonical = canonicalize_executable(&absolute).map_err(handle_io_error)?;
let python_executable = env::var_os(EnvVars::PYTHONEXECUTABLE).map(PathBuf::from);
let pyvenv_launcher = env::var_os(EnvVars::PYVENV_LAUNCHER).map(PathBuf::from);

let cache_entry = cache.entry(
CacheBucket::Interpreter,
Expand All @@ -1170,7 +1173,13 @@ impl InterpreterInfo {
// absolute path refers to different interpreters with matching ctimes, e.g., if you
// have a `.venv/bin/python` pointing to both Python 3.12 and Python 3.13 that were
// modified at the same time.
format!("{}.msgpack", cache_digest(&(&absolute, &canonical))),
//
// Launcher overrides can also change the reported executable and virtual environment
// without changing either executable path.
format!(
"{}.msgpack",
cache_digest(&(&absolute, &canonical, &python_executable, &pyvenv_launcher))
),
);

// We check the timestamp of the canonicalized executable to check if an underlying
Expand Down
5 changes: 5 additions & 0 deletions crates/uv-static/src/env_vars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1077,6 +1077,11 @@ impl EnvVars {
#[attr_added_in("0.7.13")]
pub const PYTHONHOME: &'static str = "PYTHONHOME";

/// Overrides the executable Python uses to determine its environment.
#[attr_hidden]
#[attr_added_in("next release")]
pub const PYTHONEXECUTABLE: &'static str = "PYTHONEXECUTABLE";

/// Used to correctly detect virtual environments when using trampolines.
#[attr_hidden]
#[attr_added_in("0.7.13")]
Expand Down
6 changes: 3 additions & 3 deletions crates/uv/tests/python/python_find.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ fn python_find_cached_launcher_override() {
// `PYTHONEXECUTABLE` makes the requested `other` interpreter report `.venv`.
uv_snapshot!(context.filters(), context.python_find()
.arg(&requested_python)
.env("PYTHONEXECUTABLE", &override_python), @"
.env(EnvVars::PYTHONEXECUTABLE, &override_python), @"
exit_code: 0 (success)
----- stdout -----
[VENV]/bin/python3
Expand All @@ -155,10 +155,10 @@ fn python_find_cached_launcher_override() {
// Without `PYTHONEXECUTABLE`, this should return `other`, not the cached `.venv`.
uv_snapshot!(context.filters(), context.python_find()
.arg(&requested_python)
.env_remove("PYTHONEXECUTABLE"), @"
.env_remove(EnvVars::PYTHONEXECUTABLE), @"
exit_code: 0 (success)
----- stdout -----
[VENV]/bin/python3
[TEMP_DIR]/other/bin/python3
");
}

Expand Down
9 changes: 0 additions & 9 deletions hawk.toml
Original file line number Diff line number Diff line change
Expand Up @@ -207,15 +207,6 @@ kind = "inherent_associated_constant"
level = "expect"
reason = "read by generated activation scripts"

[[override]]
lint = "hawk::dead_public"
crate = "uv_static"
item = "env_vars::EnvVars::PYVENV_LAUNCHER"
kind = "inherent_associated_constant"
level = "expect"
target = "cfg(not(windows))"
reason = "used by Windows trampoline launchers"

[[override]]
lint = "hawk::dead_public"
crate = "uv_static"
Expand Down
Loading