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
119 changes: 86 additions & 33 deletions crates/uv-python/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1181,19 +1181,21 @@ mod tests {
let condaenv = context.tempdir.child("condaenv");
TestContext::mock_conda_prefix(&condaenv, "3.12.0")?;

let python = context.run_with_vars(
&[(EnvVars::CONDA_PREFIX, Some(condaenv.as_os_str()))],
|| {
// Note this python is not treated as a system interpreter
find_python_installation(
&PythonRequest::Default,
EnvironmentPreference::OnlyVirtual,
PythonPreference::OnlySystem,
&context.cache,
Preview::default(),
)
},
)??;
let python = context
.run_with_vars(
&[(EnvVars::CONDA_PREFIX, Some(condaenv.as_os_str()))],
|| {
// Note this python is not treated as a system interpreter
find_python_installation(
&PythonRequest::Default,
EnvironmentPreference::OnlyVirtual,
PythonPreference::OnlySystem,
&context.cache,
Preview::default(),
)
},
)?
.unwrap();
assert_eq!(
python.interpreter().python_full_version().to_string(),
"3.12.0",
Expand Down Expand Up @@ -1274,22 +1276,14 @@ mod tests {
assert_eq!(
python.interpreter().python_full_version().to_string(),
"3.12.0",
"We should find the conda environment"
"We should find the conda environment when name matches"
);

// Test _CONDA_ROOT detection of base environment
let conda_root_env = context.tempdir.child("conda-root");
TestContext::mock_conda_prefix(&conda_root_env, "3.12.2")?;

// When _CONDA_ROOT matches CONDA_PREFIX, it should be treated as a base environment
// When CONDA_DEFAULT_ENV is "base", it should always be treated as base environment
let result = context.run_with_vars(
&[
(EnvVars::CONDA_PREFIX, Some(conda_root_env.as_os_str())),
(EnvVars::CONDA_ROOT, Some(conda_root_env.as_os_str())),
(
EnvVars::CONDA_DEFAULT_ENV,
Some(&OsString::from("custom-name")),
),
("CONDA_PREFIX", Some(condaenv.as_os_str())),
("CONDA_DEFAULT_ENV", Some(&OsString::from("base"))),
],
|| {
find_python_installation(
Expand All @@ -1304,20 +1298,48 @@ mod tests {

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

// When _CONDA_ROOT doesn't match CONDA_PREFIX, it should be treated as a regular conda environment
let other_conda_env = context.tempdir.child("other-conda");
TestContext::mock_conda_prefix(&other_conda_env, "3.12.3")?;
// When environment name matches directory name, it should be treated as a child environment
let myenv_dir = context.tempdir.child("myenv");
TestContext::mock_conda_prefix(&myenv_dir, "3.12.5")?;
let python = context
.run_with_vars(
&[
("CONDA_PREFIX", Some(myenv_dir.as_os_str())),
("CONDA_DEFAULT_ENV", Some(&OsString::from("myenv"))),
],
|| {
find_python_installation(
&PythonRequest::Default,
EnvironmentPreference::OnlyVirtual,
PythonPreference::OnlySystem,
&context.cache,
Preview::default(),
)
},
)?
.unwrap();

let python = context.run_with_vars(
assert_eq!(
python.interpreter().python_full_version().to_string(),
"3.12.5",
"We should find the child conda environment"
);

// Test _CONDA_ROOT detection of base environment
let conda_root_env = context.tempdir.child("conda-root");
TestContext::mock_conda_prefix(&conda_root_env, "3.12.2")?;

// When _CONDA_ROOT matches CONDA_PREFIX, it should be treated as a base environment
let result = context.run_with_vars(
&[
(EnvVars::CONDA_PREFIX, Some(other_conda_env.as_os_str())),
(EnvVars::CONDA_PREFIX, Some(conda_root_env.as_os_str())),
(EnvVars::CONDA_ROOT, Some(conda_root_env.as_os_str())),
(
EnvVars::CONDA_DEFAULT_ENV,
Some(&OsString::from("custom-env")),
Some(&OsString::from("custom-name")),
),
],
|| {
Expand All @@ -1329,7 +1351,38 @@ mod tests {
Preview::default(),
)
},
)??;
)?;

assert!(
matches!(result, Err(PythonNotFound { .. })),
"Base environment detected via _CONDA_ROOT should be excluded from virtual environments; got {result:?}"
);

// When _CONDA_ROOT doesn't match CONDA_PREFIX, it should be treated as a regular conda environment
let other_conda_env = context.tempdir.child("other-conda");
TestContext::mock_conda_prefix(&other_conda_env, "3.12.3")?;

let python = context
.run_with_vars(
&[
(EnvVars::CONDA_PREFIX, Some(other_conda_env.as_os_str())),
(EnvVars::CONDA_ROOT, Some(conda_root_env.as_os_str())),
(
EnvVars::CONDA_DEFAULT_ENV,
Some(&OsString::from("other-conda")),
),
],
|| {
find_python_installation(
&PythonRequest::Default,
EnvironmentPreference::OnlyVirtual,
PythonPreference::OnlySystem,
&context.cache,
Preview::default(),
)
},
)?
.unwrap();

assert_eq!(
python.interpreter().python_full_version().to_string(),
Expand Down
11 changes: 7 additions & 4 deletions crates/uv-python/src/virtualenv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,15 @@ impl CondaEnvironmentKind {
return Self::Child;
}

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

// For other environment names, use the path-based logic
let Some(name) = path.file_name() else {
return Self::Child;
};
Expand Down
Loading