Skip to content

Commit fa53a62

Browse files
authored
Always treat conda environments named base and root as base environments (#15682)
Extends #15679 I'm not sure if we want to do this. It is probably _generally_ true, but I think I'd rather remove the special casing entirely? I think the main case for this is that it could help prevent regressions from #15679 and we can remove it in a breaking release?
1 parent 759eab8 commit fa53a62

File tree

2 files changed

+93
-37
lines changed

2 files changed

+93
-37
lines changed

crates/uv-python/src/lib.rs

Lines changed: 86 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1181,19 +1181,21 @@ mod tests {
11811181
let condaenv = context.tempdir.child("condaenv");
11821182
TestContext::mock_conda_prefix(&condaenv, "3.12.0")?;
11831183

1184-
let python = context.run_with_vars(
1185-
&[(EnvVars::CONDA_PREFIX, Some(condaenv.as_os_str()))],
1186-
|| {
1187-
// Note this python is not treated as a system interpreter
1188-
find_python_installation(
1189-
&PythonRequest::Default,
1190-
EnvironmentPreference::OnlyVirtual,
1191-
PythonPreference::OnlySystem,
1192-
&context.cache,
1193-
Preview::default(),
1194-
)
1195-
},
1196-
)??;
1184+
let python = context
1185+
.run_with_vars(
1186+
&[(EnvVars::CONDA_PREFIX, Some(condaenv.as_os_str()))],
1187+
|| {
1188+
// Note this python is not treated as a system interpreter
1189+
find_python_installation(
1190+
&PythonRequest::Default,
1191+
EnvironmentPreference::OnlyVirtual,
1192+
PythonPreference::OnlySystem,
1193+
&context.cache,
1194+
Preview::default(),
1195+
)
1196+
},
1197+
)?
1198+
.unwrap();
11971199
assert_eq!(
11981200
python.interpreter().python_full_version().to_string(),
11991201
"3.12.0",
@@ -1274,22 +1276,14 @@ mod tests {
12741276
assert_eq!(
12751277
python.interpreter().python_full_version().to_string(),
12761278
"3.12.0",
1277-
"We should find the conda environment"
1279+
"We should find the conda environment when name matches"
12781280
);
12791281

1280-
// Test _CONDA_ROOT detection of base environment
1281-
let conda_root_env = context.tempdir.child("conda-root");
1282-
TestContext::mock_conda_prefix(&conda_root_env, "3.12.2")?;
1283-
1284-
// When _CONDA_ROOT matches CONDA_PREFIX, it should be treated as a base environment
1282+
// When CONDA_DEFAULT_ENV is "base", it should always be treated as base environment
12851283
let result = context.run_with_vars(
12861284
&[
1287-
(EnvVars::CONDA_PREFIX, Some(conda_root_env.as_os_str())),
1288-
(EnvVars::CONDA_ROOT, Some(conda_root_env.as_os_str())),
1289-
(
1290-
EnvVars::CONDA_DEFAULT_ENV,
1291-
Some(&OsString::from("custom-name")),
1292-
),
1285+
("CONDA_PREFIX", Some(condaenv.as_os_str())),
1286+
("CONDA_DEFAULT_ENV", Some(&OsString::from("base"))),
12931287
],
12941288
|| {
12951289
find_python_installation(
@@ -1304,20 +1298,48 @@ mod tests {
13041298

13051299
assert!(
13061300
matches!(result, Err(PythonNotFound { .. })),
1307-
"Base environment detected via _CONDA_ROOT should be excluded from virtual environments; got {result:?}"
1301+
"We should not allow the base environment when looking for virtual environments"
13081302
);
13091303

1310-
// When _CONDA_ROOT doesn't match CONDA_PREFIX, it should be treated as a regular conda environment
1311-
let other_conda_env = context.tempdir.child("other-conda");
1312-
TestContext::mock_conda_prefix(&other_conda_env, "3.12.3")?;
1304+
// When environment name matches directory name, it should be treated as a child environment
1305+
let myenv_dir = context.tempdir.child("myenv");
1306+
TestContext::mock_conda_prefix(&myenv_dir, "3.12.5")?;
1307+
let python = context
1308+
.run_with_vars(
1309+
&[
1310+
("CONDA_PREFIX", Some(myenv_dir.as_os_str())),
1311+
("CONDA_DEFAULT_ENV", Some(&OsString::from("myenv"))),
1312+
],
1313+
|| {
1314+
find_python_installation(
1315+
&PythonRequest::Default,
1316+
EnvironmentPreference::OnlyVirtual,
1317+
PythonPreference::OnlySystem,
1318+
&context.cache,
1319+
Preview::default(),
1320+
)
1321+
},
1322+
)?
1323+
.unwrap();
13131324

1314-
let python = context.run_with_vars(
1325+
assert_eq!(
1326+
python.interpreter().python_full_version().to_string(),
1327+
"3.12.5",
1328+
"We should find the child conda environment"
1329+
);
1330+
1331+
// Test _CONDA_ROOT detection of base environment
1332+
let conda_root_env = context.tempdir.child("conda-root");
1333+
TestContext::mock_conda_prefix(&conda_root_env, "3.12.2")?;
1334+
1335+
// When _CONDA_ROOT matches CONDA_PREFIX, it should be treated as a base environment
1336+
let result = context.run_with_vars(
13151337
&[
1316-
(EnvVars::CONDA_PREFIX, Some(other_conda_env.as_os_str())),
1338+
(EnvVars::CONDA_PREFIX, Some(conda_root_env.as_os_str())),
13171339
(EnvVars::CONDA_ROOT, Some(conda_root_env.as_os_str())),
13181340
(
13191341
EnvVars::CONDA_DEFAULT_ENV,
1320-
Some(&OsString::from("custom-env")),
1342+
Some(&OsString::from("custom-name")),
13211343
),
13221344
],
13231345
|| {
@@ -1329,7 +1351,38 @@ mod tests {
13291351
Preview::default(),
13301352
)
13311353
},
1332-
)??;
1354+
)?;
1355+
1356+
assert!(
1357+
matches!(result, Err(PythonNotFound { .. })),
1358+
"Base environment detected via _CONDA_ROOT should be excluded from virtual environments; got {result:?}"
1359+
);
1360+
1361+
// When _CONDA_ROOT doesn't match CONDA_PREFIX, it should be treated as a regular conda environment
1362+
let other_conda_env = context.tempdir.child("other-conda");
1363+
TestContext::mock_conda_prefix(&other_conda_env, "3.12.3")?;
1364+
1365+
let python = context
1366+
.run_with_vars(
1367+
&[
1368+
(EnvVars::CONDA_PREFIX, Some(other_conda_env.as_os_str())),
1369+
(EnvVars::CONDA_ROOT, Some(conda_root_env.as_os_str())),
1370+
(
1371+
EnvVars::CONDA_DEFAULT_ENV,
1372+
Some(&OsString::from("other-conda")),
1373+
),
1374+
],
1375+
|| {
1376+
find_python_installation(
1377+
&PythonRequest::Default,
1378+
EnvironmentPreference::OnlyVirtual,
1379+
PythonPreference::OnlySystem,
1380+
&context.cache,
1381+
Preview::default(),
1382+
)
1383+
},
1384+
)?
1385+
.unwrap();
13331386

13341387
assert_eq!(
13351388
python.interpreter().python_full_version().to_string(),

crates/uv-python/src/virtualenv.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,12 +104,15 @@ impl CondaEnvironmentKind {
104104
return Self::Child;
105105
}
106106

107-
// These are the expected names for the base environment; we may want to remove this
108-
// restriction in the future as it's not strictly necessary.
109-
if current_env != "base" && current_env != "root" {
110-
return Self::Child;
107+
// If the environment name is "base" or "root", treat it as a base environment
108+
//
109+
// These are the expected names for the base environment; and is retained for backwards
110+
// compatibility, but in a future breaking release we should remove this special-casing.
111+
if current_env == "base" || current_env == "root" {
112+
return Self::Base;
111113
}
112114

115+
// For other environment names, use the path-based logic
113116
let Some(name) = path.file_name() else {
114117
return Self::Child;
115118
};

0 commit comments

Comments
 (0)