Fix pixi environment detection by recognizing Conda prefixes with `conda-meta/pixi` (#16585)

Resolves https://github.com/astral-sh/uv/issues/16295

This PR updates the Conda base-environment heuristic to recognize
Pixi-managed environments by checking for the `conda-meta/pixi` marker
file. Pixi default environments now resolve as isolated child
environments instead of system installations, restoring the expected uv
pip behavior without the `--system` flag.
This commit is contained in:
liam 2025-11-09 23:16:17 -05:00 committed by GitHub
parent 2d9fe7ca70
commit c826f2b042
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 38 additions and 0 deletions

View File

@ -86,6 +86,12 @@ impl CondaEnvironmentKind {
/// `/usr/local/conda/envs/<name>`. Note the name `CONDA_DEFAULT_ENV` is misleading, it's the /// `/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. /// active environment name, not a constant base environment name.
fn from_prefix_path(path: &Path) -> Self { fn from_prefix_path(path: &Path) -> 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) {
return Self::Child;
}
// If `_CONDA_ROOT` is set and matches `CONDA_PREFIX`, it's the base environment. // If `_CONDA_ROOT` is set and matches `CONDA_PREFIX`, it's the base environment.
if let Ok(conda_root) = env::var(EnvVars::CONDA_ROOT) { if let Ok(conda_root) = env::var(EnvVars::CONDA_ROOT) {
if path == Path::new(&conda_root) { if path == Path::new(&conda_root) {
@ -127,6 +133,11 @@ impl CondaEnvironmentKind {
} }
} }
/// Detect whether the current `CONDA_PREFIX` belongs to a Pixi-managed environment.
fn is_pixi_environment(path: &Path) -> bool {
path.join("conda-meta").join("pixi").is_file()
}
/// Locate an active conda environment by inspecting environment variables. /// Locate an active conda environment by inspecting environment variables.
/// ///
/// If `base` is true, the active environment must be the base environment or `None` is returned, /// If `base` is true, the active environment must be the base environment or `None` is returned,
@ -317,10 +328,37 @@ impl PyVenvConfiguration {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::ffi::OsStr;
use indoc::indoc; use indoc::indoc;
use temp_env::with_vars;
use tempfile::tempdir;
use super::*; use super::*;
#[test]
fn pixi_environment_is_treated_as_child() {
let tempdir = tempdir().unwrap();
let prefix = tempdir.path();
let conda_meta = prefix.join("conda-meta");
fs::create_dir_all(&conda_meta).unwrap();
fs::write(conda_meta.join("pixi"), []).unwrap();
let vars = [
(EnvVars::CONDA_ROOT, None),
(EnvVars::CONDA_PREFIX, Some(prefix.as_os_str())),
(EnvVars::CONDA_DEFAULT_ENV, Some(OsStr::new("example"))),
];
with_vars(vars, || {
assert_eq!(
CondaEnvironmentKind::from_prefix_path(prefix),
CondaEnvironmentKind::Child
);
});
}
#[test] #[test]
fn test_set_existing_key() { fn test_set_existing_key() {
let content = indoc! {" let content = indoc! {"