Skip to content

Commit 9dac444

Browse files
authored
Fix conda environment discovery for child environments under envs folder (#275)
Fixes #236
1 parent 95d03d6 commit 9dac444

File tree

2 files changed

+73
-0
lines changed

2 files changed

+73
-0
lines changed

crates/pet-conda/src/environment_locations.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,23 @@ pub fn get_environments(conda_dir: &Path) -> Vec<PathBuf> {
197197
}
198198
} else if is_conda_env(conda_dir) {
199199
envs.push(conda_dir.to_path_buf());
200+
// If this is a conda environment under an `envs` folder, check if the grandparent
201+
// is the conda install directory (base env) and include it as well.
202+
// E.g. if conda_dir is `/opt/homebrew/Caskroom/miniforge/base/envs/test`,
203+
// then the grandparent `/opt/homebrew/Caskroom/miniforge/base` is the base env.
204+
// This ensures the base conda environment is discovered when only child envs are
205+
// listed in environments.txt (see https://github.com/microsoft/python-environment-tools/issues/236)
206+
if let Some(parent) = conda_dir.parent() {
207+
if parent.file_name().map(|n| n == "envs").unwrap_or(false) {
208+
if let Some(grandparent) = parent.parent() {
209+
if is_conda_install(grandparent) && !envs.contains(&grandparent.to_path_buf()) {
210+
// Recursively get environments from the conda install directory
211+
// This will add the base env and any other sibling envs
212+
envs.append(&mut get_environments(grandparent));
213+
}
214+
}
215+
}
216+
}
200217
} else if conda_dir.join("envs").exists() {
201218
// This could be a directory where conda environments are stored.
202219
// I.e. its not necessarily the root conda install directory.

crates/pet-conda/tests/environment_locations_test.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,59 @@ fn list_conda_envs_in_install_location() {
3939
]
4040
);
4141
}
42+
43+
/// Test that when get_environments is called with a child environment under the `envs` folder,
44+
/// it also discovers the parent conda install (base environment) and all sibling environments.
45+
/// This is the fix for https://github.com/microsoft/python-environment-tools/issues/236
46+
/// where the base conda environment wasn't discovered when only child envs were listed
47+
/// in environments.txt (e.g., from Homebrew Cask installs like /opt/homebrew/Caskroom/miniforge/base).
48+
#[cfg(unix)]
49+
#[test]
50+
fn list_conda_envs_discovers_base_from_child_env() {
51+
use common::resolve_test_path;
52+
use pet_conda::environment_locations::get_environments;
53+
54+
// Call get_environments with a child environment path (not the install directory)
55+
let child_env_path = resolve_test_path(&["unix", "anaconda3-2023.03", "envs", "myenv"]);
56+
57+
let mut locations = get_environments(&child_env_path);
58+
locations.sort();
59+
60+
// Should discover not only the child env, but also the base env (conda install dir)
61+
// and all sibling environments
62+
assert_eq!(
63+
locations,
64+
vec![
65+
resolve_test_path(&["unix", "anaconda3-2023.03"]),
66+
resolve_test_path(&["unix", "anaconda3-2023.03", "envs", "env_python_3"]),
67+
resolve_test_path(&["unix", "anaconda3-2023.03", "envs", "myenv"]),
68+
resolve_test_path(&["unix", "anaconda3-2023.03", "envs", "without_python"]),
69+
]
70+
);
71+
}
72+
73+
/// Test that get_environments works correctly with an env_python_3 child environment
74+
/// (another sibling to verify the fix works for any child env under envs folder).
75+
#[cfg(unix)]
76+
#[test]
77+
fn list_conda_envs_discovers_base_from_another_child_env() {
78+
use common::resolve_test_path;
79+
use pet_conda::environment_locations::get_environments;
80+
81+
// Call get_environments with a different child environment path
82+
let child_env_path = resolve_test_path(&["unix", "anaconda3-2023.03", "envs", "env_python_3"]);
83+
84+
let mut locations = get_environments(&child_env_path);
85+
locations.sort();
86+
87+
// Should discover the base env and all sibling environments
88+
assert_eq!(
89+
locations,
90+
vec![
91+
resolve_test_path(&["unix", "anaconda3-2023.03"]),
92+
resolve_test_path(&["unix", "anaconda3-2023.03", "envs", "env_python_3"]),
93+
resolve_test_path(&["unix", "anaconda3-2023.03", "envs", "myenv"]),
94+
resolve_test_path(&["unix", "anaconda3-2023.03", "envs", "without_python"]),
95+
]
96+
);
97+
}

0 commit comments

Comments
 (0)