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" "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")?; TestContext::mock_conda_prefix(&baseenv, "3.12.1")?;
// But not if it's a base environment // But not if it's a base environment
@ -1226,21 +1226,23 @@ mod tests {
); );
// Unless, system interpreters are included... // Unless, system interpreters are included...
let python = context.run_with_vars( let python = context
&[ .run_with_vars(
("CONDA_PREFIX", Some(baseenv.as_os_str())), &[
("CONDA_DEFAULT_ENV", Some(&OsString::from("base"))), ("CONDA_PREFIX", Some(baseenv.as_os_str())),
], ("CONDA_DEFAULT_ENV", Some(&OsString::from("base"))),
|| { ],
find_python_installation( || {
&PythonRequest::Default, find_python_installation(
EnvironmentPreference::OnlySystem, &PythonRequest::Default,
PythonPreference::OnlySystem, EnvironmentPreference::OnlySystem,
&context.cache, PythonPreference::OnlySystem,
Preview::default(), &context.cache,
) Preview::default(),
}, )
)??; },
)?
.unwrap();
assert_eq!( assert_eq!(
python.interpreter().python_full_version().to_string(), 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 // If the environment name doesn't match the default, we should not treat it as system
let python = context.run_with_vars( let python = context
&[ .run_with_vars(
("CONDA_PREFIX", Some(condaenv.as_os_str())), &[
("CONDA_DEFAULT_ENV", Some(&OsString::from("base"))), ("CONDA_PREFIX", Some(condaenv.as_os_str())),
], ("CONDA_DEFAULT_ENV", Some(&OsString::from("condaenv"))),
|| { ],
find_python_installation( || {
&PythonRequest::Default, find_python_installation(
EnvironmentPreference::OnlyVirtual, &PythonRequest::Default,
PythonPreference::OnlySystem, EnvironmentPreference::OnlyVirtual,
&context.cache, PythonPreference::OnlySystem,
Preview::default(), &context.cache,
) Preview::default(),
}, )
)??; },
)?
.unwrap();
assert_eq!( assert_eq!(
python.interpreter().python_full_version().to_string(), 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 /// 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 /// `root` which does not match the prefix, e.g. `/usr/local` instead of
/// `/usr/local/conda/envs/<name>`. /// `/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 { fn from_prefix_path(path: &Path) -> Self {
// If we cannot read `CONDA_DEFAULT_ENV`, there's no way to know if the base environment // 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; return Self::Child;
}; };
// These are the expected names for the base environment // 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; return Self::Child;
} }
@ -97,10 +100,12 @@ impl CondaEnvironmentKind {
return Self::Child; return Self::Child;
}; };
if name.to_str().is_some_and(|name| name == default_env) { // If the environment is in a directory matching the name of the environment, it's not
Self::Base // usually a base environment.
} else { if name.to_str().is_some_and(|name| name == current_env) {
Self::Child Self::Child
} else {
Self::Base
} }
} }
} }