Invert the logic for determining if a path is a base conda environment (#15679)

Closes https://github.com/astral-sh/uv/issues/15604

The previous logic does not match the discussion in the original issue
about this feature, nor does it match the comment for the function. I'm
confused because I know this logic is working for some people? I'm
consequently a little wary of making this change. I'm following up with
some additional changes that should ensure this is robust, e.g., #15680
This commit is contained in:
Zanie Blue 2025-09-17 06:04:29 -05:00 committed by GitHub
parent 9ec7971b4a
commit ee5f155f7e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 45 additions and 36 deletions

View file

@ -1200,7 +1200,7 @@ mod tests {
"We should allow the active conda python"
);
let baseenv = context.tempdir.child("base");
let baseenv = context.tempdir.child("conda");
TestContext::mock_conda_prefix(&baseenv, "3.12.1")?;
// But not if it's a base environment
@ -1226,21 +1226,23 @@ mod tests {
);
// Unless, system interpreters are included...
let python = context.run_with_vars(
&[
("CONDA_PREFIX", Some(baseenv.as_os_str())),
("CONDA_DEFAULT_ENV", Some(&OsString::from("base"))),
],
|| {
find_python_installation(
&PythonRequest::Default,
EnvironmentPreference::OnlySystem,
PythonPreference::OnlySystem,
&context.cache,
Preview::default(),
)
},
)??;
let python = context
.run_with_vars(
&[
("CONDA_PREFIX", Some(baseenv.as_os_str())),
("CONDA_DEFAULT_ENV", Some(&OsString::from("base"))),
],
|| {
find_python_installation(
&PythonRequest::Default,
EnvironmentPreference::OnlySystem,
PythonPreference::OnlySystem,
&context.cache,
Preview::default(),
)
},
)?
.unwrap();
assert_eq!(
python.interpreter().python_full_version().to_string(),
@ -1249,21 +1251,23 @@ mod tests {
);
// If the environment name doesn't match the default, we should not treat it as system
let python = context.run_with_vars(
&[
("CONDA_PREFIX", Some(condaenv.as_os_str())),
("CONDA_DEFAULT_ENV", Some(&OsString::from("base"))),
],
|| {
find_python_installation(
&PythonRequest::Default,
EnvironmentPreference::OnlyVirtual,
PythonPreference::OnlySystem,
&context.cache,
Preview::default(),
)
},
)??;
let python = context
.run_with_vars(
&[
("CONDA_PREFIX", Some(condaenv.as_os_str())),
("CONDA_DEFAULT_ENV", Some(&OsString::from("condaenv"))),
],
|| {
find_python_installation(
&PythonRequest::Default,
EnvironmentPreference::OnlyVirtual,
PythonPreference::OnlySystem,
&context.cache,
Preview::default(),
)
},
)?
.unwrap();
assert_eq!(
python.interpreter().python_full_version().to_string(),

View file

@ -82,14 +82,17 @@ impl CondaEnvironmentKind {
/// When the base environment is used, `CONDA_DEFAULT_ENV` will be set to a name, i.e., `base` or
/// `root` which does not match the prefix, e.g. `/usr/local` instead of
/// `/usr/local/conda/envs/<name>`.
///
/// Note the name `CONDA_DEFAULT_ENV` is misleading, it's the current environment, not the base
/// environment name.
fn from_prefix_path(path: &Path) -> Self {
// If we cannot read `CONDA_DEFAULT_ENV`, there's no way to know if the base environment
let Ok(default_env) = env::var(EnvVars::CONDA_DEFAULT_ENV) else {
let Ok(current_env) = env::var(EnvVars::CONDA_DEFAULT_ENV) else {
return Self::Child;
};
// These are the expected names for the base environment
if default_env != "base" && default_env != "root" {
if current_env != "base" && current_env != "root" {
return Self::Child;
}
@ -97,10 +100,12 @@ impl CondaEnvironmentKind {
return Self::Child;
};
if name.to_str().is_some_and(|name| name == default_env) {
Self::Base
} else {
// If the environment is in a directory matching the name of the environment, it's not
// usually a base environment.
if name.to_str().is_some_and(|name| name == current_env) {
Self::Child
} else {
Self::Base
}
}
}