Remove special casing for base and default conda environment names (#17758)
Under the `special-conda-env-names` preview feature, instead, just using our path-based logic. --------- Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -285,8 +285,9 @@ pub enum Error {
|
||||
/// - Discovered virtual environment (e.g. `.venv` in a parent directory)
|
||||
///
|
||||
/// Notably, "system" environments are excluded. See [`python_executables_from_installed`].
|
||||
fn python_executables_from_virtual_environments<'a>()
|
||||
-> impl Iterator<Item = Result<(PythonSource, PathBuf), Error>> + 'a {
|
||||
fn python_executables_from_virtual_environments<'a>(
|
||||
preview: Preview,
|
||||
) -> impl Iterator<Item = Result<(PythonSource, PathBuf), Error>> + 'a {
|
||||
let from_active_environment = iter::once_with(|| {
|
||||
virtualenv_from_env()
|
||||
.into_iter()
|
||||
@@ -296,8 +297,8 @@ fn python_executables_from_virtual_environments<'a>()
|
||||
.flatten();
|
||||
|
||||
// N.B. we prefer the conda environment over discovered virtual environments
|
||||
let from_conda_environment = iter::once_with(|| {
|
||||
conda_environment_from_env(CondaEnvironmentKind::Child)
|
||||
let from_conda_environment = iter::once_with(move || {
|
||||
conda_environment_from_env(CondaEnvironmentKind::Child, preview)
|
||||
.into_iter()
|
||||
.map(virtualenv_python_executable)
|
||||
.map(|path| Ok((PythonSource::CondaPrefix, path)))
|
||||
@@ -524,15 +525,15 @@ fn python_executables<'a>(
|
||||
.flatten();
|
||||
|
||||
// Check if the base conda environment is active
|
||||
let from_base_conda_environment = iter::once_with(|| {
|
||||
conda_environment_from_env(CondaEnvironmentKind::Base)
|
||||
let from_base_conda_environment = iter::once_with(move || {
|
||||
conda_environment_from_env(CondaEnvironmentKind::Base, preview)
|
||||
.into_iter()
|
||||
.map(virtualenv_python_executable)
|
||||
.map(|path| Ok((PythonSource::BaseCondaPrefix, path)))
|
||||
})
|
||||
.flatten();
|
||||
|
||||
let from_virtual_environments = python_executables_from_virtual_environments();
|
||||
let from_virtual_environments = python_executables_from_virtual_environments(preview);
|
||||
let from_installed =
|
||||
python_executables_from_installed(version, implementation, platform, preference, preview);
|
||||
|
||||
|
||||
@@ -136,7 +136,7 @@ mod tests {
|
||||
use temp_env::with_vars;
|
||||
use test_log::test;
|
||||
use uv_client::BaseClientBuilder;
|
||||
use uv_preview::Preview;
|
||||
use uv_preview::{Preview, PreviewFeature};
|
||||
use uv_static::EnvVars;
|
||||
|
||||
use uv_cache::Cache;
|
||||
@@ -1335,6 +1335,36 @@ mod tests {
|
||||
"We should not allow the base environment when looking for virtual environments"
|
||||
);
|
||||
|
||||
// With the `special-conda-env-names` preview feature, "base" is not special-cased
|
||||
// and uses path-based heuristics instead. When the directory name matches the env name,
|
||||
// it should be treated as a child environment.
|
||||
let base_dir = context.tempdir.child("base");
|
||||
TestContext::mock_conda_prefix(&base_dir, "3.12.6")?;
|
||||
let python = context
|
||||
.run_with_vars(
|
||||
&[
|
||||
(EnvVars::CONDA_PREFIX, Some(base_dir.as_os_str())),
|
||||
(EnvVars::CONDA_DEFAULT_ENV, Some(&OsString::from("base"))),
|
||||
(EnvVars::CONDA_ROOT, None),
|
||||
],
|
||||
|| {
|
||||
find_python_installation(
|
||||
&PythonRequest::Default,
|
||||
EnvironmentPreference::OnlyVirtual,
|
||||
PythonPreference::OnlySystem,
|
||||
&context.cache,
|
||||
Preview::new(&[PreviewFeature::SpecialCondaEnvNames]),
|
||||
)
|
||||
},
|
||||
)?
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
python.interpreter().python_full_version().to_string(),
|
||||
"3.12.6",
|
||||
"With special-conda-env-names preview, 'base' named env in matching dir should be treated as child"
|
||||
);
|
||||
|
||||
// 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")?;
|
||||
|
||||
@@ -8,6 +8,7 @@ use std::{
|
||||
use fs_err as fs;
|
||||
use thiserror::Error;
|
||||
|
||||
use uv_preview::{Preview, PreviewFeature};
|
||||
use uv_pypi_types::Scheme;
|
||||
use uv_static::EnvVars;
|
||||
|
||||
@@ -85,7 +86,7 @@ impl CondaEnvironmentKind {
|
||||
/// name, e.g., `base`, which does not match the `CONDA_PREFIX`, e.g., `/usr/local` instead of
|
||||
/// `/usr/local/conda/envs/<name>`. Note the name `CONDA_DEFAULT_ENV` is misleading, it's the
|
||||
/// active environment name, not a constant base environment name.
|
||||
fn from_prefix_path(path: &Path) -> Self {
|
||||
fn from_prefix_path(path: &Path, preview: Preview) -> Self {
|
||||
// Pixi never creates true "base" envs and names project envs "default", confusing our
|
||||
// heuristics, so treat Pixi prefixes as child envs outright.
|
||||
if is_pixi_environment(path) {
|
||||
@@ -113,8 +114,10 @@ impl CondaEnvironmentKind {
|
||||
// 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" {
|
||||
// compatibility, but can be removed with the `special-conda-env-names` preview feature.
|
||||
if !preview.is_enabled(PreviewFeature::SpecialCondaEnvNames)
|
||||
&& (current_env == "base" || current_env == "root")
|
||||
{
|
||||
return Self::Base;
|
||||
}
|
||||
|
||||
@@ -142,11 +145,14 @@ fn is_pixi_environment(path: &Path) -> bool {
|
||||
///
|
||||
/// If `base` is true, the active environment must be the base environment or `None` is returned,
|
||||
/// and vice-versa.
|
||||
pub(crate) fn conda_environment_from_env(kind: CondaEnvironmentKind) -> Option<PathBuf> {
|
||||
pub(crate) fn conda_environment_from_env(
|
||||
kind: CondaEnvironmentKind,
|
||||
preview: Preview,
|
||||
) -> Option<PathBuf> {
|
||||
let dir = env::var_os(EnvVars::CONDA_PREFIX).filter(|value| !value.is_empty())?;
|
||||
let path = PathBuf::from(dir);
|
||||
|
||||
if kind != CondaEnvironmentKind::from_prefix_path(&path) {
|
||||
if kind != CondaEnvironmentKind::from_prefix_path(&path, preview) {
|
||||
return None;
|
||||
}
|
||||
|
||||
@@ -353,7 +359,7 @@ mod tests {
|
||||
|
||||
with_vars(vars, || {
|
||||
assert_eq!(
|
||||
CondaEnvironmentKind::from_prefix_path(prefix),
|
||||
CondaEnvironmentKind::from_prefix_path(prefix, Preview::default()),
|
||||
CondaEnvironmentKind::Child
|
||||
);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user