Skip to content

Commit eafeb02

Browse files
committed
Revert "Includes sys.prefix in cached environment keys to avoid --with collisions across projects (#14403)"
This reverts commit ec54dce.
1 parent 537082c commit eafeb02

File tree

3 files changed

+12
-42
lines changed

3 files changed

+12
-42
lines changed

crates/uv-python/src/environment.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ impl PythonEnvironment {
174174
/// N.B. This function also works for system Python environments and users depend on this.
175175
pub fn from_root(root: impl AsRef<Path>, cache: &Cache) -> Result<Self, Error> {
176176
debug!(
177-
"Checking for Python environment at: {}",
177+
"Checking for Python environment at: `{}`",
178178
root.as_ref().user_display()
179179
);
180180
match root.as_ref().try_exists() {

crates/uv/src/commands/project/environment.rs

Lines changed: 8 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -107,15 +107,13 @@ impl CachedEnvironment {
107107
printer: Printer,
108108
preview: PreviewMode,
109109
) -> Result<Self, ProjectError> {
110-
// Resolve the "base" interpreter, which resolves to an underlying parent interpreter if the
111-
// given interpreter is a virtual environment.
112-
let base_interpreter = Self::base_interpreter(interpreter, cache)?;
110+
let interpreter = Self::base_interpreter(interpreter, cache)?;
113111

114112
// Resolve the requirements with the interpreter.
115113
let resolution = Resolution::from(
116114
resolve_environment(
117115
spec,
118-
&base_interpreter,
116+
&interpreter,
119117
build_constraints.clone(),
120118
&settings.resolver,
121119
network_settings,
@@ -138,34 +136,13 @@ impl CachedEnvironment {
138136
hash_digest(&distributions)
139137
};
140138

141-
// Construct a hash for the environment.
142-
//
143-
// Use the canonicalized base interpreter path since that's the interpreter we performed the
144-
// resolution with and the interpreter the environment will be created with.
145-
//
146-
// We also include the canonicalized `sys.prefix` of the non-base interpreter, that is, the
147-
// virtual environment's path. Originally, we shared cached environments independent of the
148-
// environment they'd be layered on top of. However, this causes collisions as the overlay
149-
// `.pth` file can be overridden by another instance of uv. Including this element in the key
150-
// avoids this problem at the cost of creating separate cached environments for identical
151-
// `--with` invocations across projects. We use `sys.prefix` rather than `sys.executable` so
152-
// we can canonicalize it without invalidating the purpose of the element — it'd probably be
153-
// safe to just use the absolute `sys.executable` as well.
154-
//
155-
// TODO(zanieb): Since we're not sharing these environmments across projects, we should move
156-
// [`CachedEvnvironment::set_overlay`] etc. here since the values there should be constant
157-
// now.
158-
//
159-
// TODO(zanieb): We should include the version of the base interpreter in the hash, so if
160-
// the interpreter at the canonicalized path changes versions we construct a new
161-
// environment.
162-
let environment_hash = cache_digest(&(
163-
&canonicalize_executable(base_interpreter.sys_executable())?,
164-
&interpreter.sys_prefix().canonicalize()?,
165-
));
139+
// Hash the interpreter based on its path.
140+
// TODO(charlie): Come up with a robust hash for the interpreter.
141+
let interpreter_hash =
142+
cache_digest(&canonicalize_executable(interpreter.sys_executable())?);
166143

167144
// Search in the content-addressed cache.
168-
let cache_entry = cache.entry(CacheBucket::Environments, environment_hash, resolution_hash);
145+
let cache_entry = cache.entry(CacheBucket::Environments, interpreter_hash, resolution_hash);
169146

170147
if cache.refresh().is_none() {
171148
if let Ok(root) = cache.resolve_link(cache_entry.path()) {
@@ -179,7 +156,7 @@ impl CachedEnvironment {
179156
let temp_dir = cache.venv_dir()?;
180157
let venv = uv_virtualenv::create_venv(
181158
temp_dir.path(),
182-
base_interpreter,
159+
interpreter,
183160
uv_virtualenv::Prompt::None,
184161
false,
185162
false,

crates/uv/tests/it/run.rs

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1302,7 +1302,6 @@ fn run_with_pyvenv_cfg_file() -> Result<()> {
13021302
uv = [UV_VERSION]
13031303
version_info = 3.12.[X]
13041304
include-system-site-packages = false
1305-
relocatable = true
13061305
extends-environment = [PARENT_VENV]
13071306
13081307
@@ -4778,7 +4777,6 @@ fn run_groups_include_requires_python() -> Result<()> {
47784777
baz = ["iniconfig"]
47794778
dev = ["sniffio", {include-group = "foo"}, {include-group = "baz"}]
47804779
4781-
47824780
[tool.uv.dependency-groups]
47834781
foo = {requires-python="<3.13"}
47844782
bar = {requires-python=">=3.13"}
@@ -4923,8 +4921,8 @@ fn run_repeated() -> Result<()> {
49234921
Resolved 1 package in [TIME]
49244922
"###);
49254923

4926-
// Re-running as a tool does require reinstalling `typing-extensions`, since the base venv is
4927-
// different.
4924+
// Re-running as a tool doesn't require reinstalling `typing-extensions`, since the environment
4925+
// is cached.
49284926
uv_snapshot!(
49294927
context.filters(),
49304928
context.tool_run().arg("--with").arg("typing-extensions").arg("python").arg("-c").arg("import typing_extensions; import iniconfig"), @r#"
@@ -4934,8 +4932,6 @@ fn run_repeated() -> Result<()> {
49344932
49354933
----- stderr -----
49364934
Resolved 1 package in [TIME]
4937-
Installed 1 package in [TIME]
4938-
+ typing-extensions==4.10.0
49394935
Traceback (most recent call last):
49404936
File "<string>", line 1, in <module>
49414937
import typing_extensions; import iniconfig
@@ -4982,8 +4978,7 @@ fn run_without_overlay() -> Result<()> {
49824978
+ typing-extensions==4.10.0
49834979
"###);
49844980

4985-
// Import `iniconfig` in the context of a `tool run` command, which should fail. Note that
4986-
// typing-extensions gets installed again, because the venv is not shared.
4981+
// Import `iniconfig` in the context of a `tool run` command, which should fail.
49874982
uv_snapshot!(
49884983
context.filters(),
49894984
context.tool_run().arg("--with").arg("typing-extensions").arg("python").arg("-c").arg("import typing_extensions; import iniconfig"), @r#"
@@ -4993,8 +4988,6 @@ fn run_without_overlay() -> Result<()> {
49934988
49944989
----- stderr -----
49954990
Resolved 1 package in [TIME]
4996-
Installed 1 package in [TIME]
4997-
+ typing-extensions==4.10.0
49984991
Traceback (most recent call last):
49994992
File "<string>", line 1, in <module>
50004993
import typing_extensions; import iniconfig

0 commit comments

Comments
 (0)