Skip to content

Commit 817b4cb

Browse files
authored
Update refresh request (#126)
1 parent 381df9c commit 817b4cb

File tree

29 files changed

+384
-319
lines changed

29 files changed

+384
-319
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/pet-conda/src/environment_locations.rs

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use std::{
1313
env, fs,
1414
path::{Path, PathBuf},
1515
thread,
16+
time::SystemTime,
1617
};
1718

1819
const APP_NAME: &str = "conda";
@@ -21,6 +22,7 @@ pub fn get_conda_environment_paths(
2122
env_vars: &EnvVariables,
2223
conda_executable: &Option<PathBuf>,
2324
) -> Vec<PathBuf> {
25+
let start = SystemTime::now();
2426
let mut env_paths = thread::scope(|s| {
2527
let mut envs = vec![];
2628
for thread in [
@@ -43,7 +45,7 @@ pub fn get_conda_environment_paths(
4345
// & then iterate through the list of envs in the envs directory.
4446
// let env_paths = vec![];
4547
let mut threads = vec![];
46-
for path in env_paths {
48+
for path in env_paths.iter().filter(|f| f.exists()) {
4749
let path = path.clone();
4850
threads.push(thread::spawn(move || get_environments(&path)));
4951
}
@@ -57,6 +59,10 @@ pub fn get_conda_environment_paths(
5759

5860
result.sort();
5961
result.dedup();
62+
trace!(
63+
"Time taken to get conda environment paths: {:?}",
64+
start.elapsed().unwrap()
65+
);
6066
result
6167
}
6268

@@ -68,13 +74,24 @@ fn get_conda_environment_paths_from_conda_rc(env_vars: &EnvVariables) -> Vec<Pat
6874
// Use the conda rc directories as well.
6975
let mut env_dirs = vec![];
7076
for rc_file_dir in get_conda_rc_search_paths(env_vars) {
77+
if !rc_file_dir.exists() {
78+
continue;
79+
}
80+
7181
if let Some(conda_rc) = Condarc::from_path(&rc_file_dir) {
7282
trace!(
7383
"Conda environments in .condarc {:?} {:?}",
7484
conda_rc.files,
7585
conda_rc.env_dirs
7686
);
77-
env_dirs.append(&mut conda_rc.env_dirs.clone());
87+
env_dirs.append(
88+
&mut conda_rc
89+
.env_dirs
90+
.clone()
91+
.into_iter()
92+
.filter(|f| f.exists())
93+
.collect(),
94+
);
7895
}
7996

8097
if rc_file_dir.is_dir() {
@@ -151,6 +168,9 @@ fn get_conda_environment_paths_from_known_paths(env_vars: &EnvVariables) -> Vec<
151168
}
152169
}
153170
env_paths.append(&mut env_vars.known_global_search_locations.clone());
171+
env_paths.sort();
172+
env_paths.dedup();
173+
let env_paths = env_paths.into_iter().filter(|f| f.exists()).collect();
154174
trace!("Conda environments in known paths {:?}", env_paths);
155175
env_paths
156176
}
@@ -217,7 +237,9 @@ pub fn get_conda_envs_from_environment_txt(env_vars: &EnvVariables) -> Vec<PathB
217237
for line in reader.lines() {
218238
let line = norm_case(&PathBuf::from(line.to_string()));
219239
trace!("Conda env in environments.txt file {:?}", line);
220-
envs.push(line);
240+
if line.exists() {
241+
envs.push(line);
242+
}
221243
}
222244
}
223245
}
@@ -364,7 +386,7 @@ pub fn get_known_conda_install_locations(
364386
}
365387
if let Some(home) = env_vars.home.clone() {
366388
// https://stackoverflow.com/questions/35709497/anaconda-python-where-are-the-virtual-environments-stored
367-
for prefix in [
389+
let mut prefixes = vec![
368390
home.clone(),
369391
// https://towardsdatascience.com/manage-your-python-virtual-environment-with-conda-a0d2934d5195
370392
home.join("opt"),
@@ -375,9 +397,14 @@ pub fn get_known_conda_install_locations(
375397
PathBuf::from("/usr/share"),
376398
PathBuf::from("/usr/local"),
377399
PathBuf::from("/usr"),
378-
PathBuf::from("/opt/homebrew"),
379-
PathBuf::from("/home/linuxbrew/.linuxbrew"),
380-
] {
400+
];
401+
if std::env::consts::OS == "macos" {
402+
prefixes.push(PathBuf::from("/opt/homebrew"));
403+
} else {
404+
prefixes.push(PathBuf::from("/home/linuxbrew/.linuxbrew"));
405+
}
406+
407+
for prefix in prefixes {
381408
known_paths.push(prefix.clone().join("anaconda"));
382409
known_paths.push(prefix.clone().join("anaconda3"));
383410
known_paths.push(prefix.clone().join("miniconda"));
@@ -395,8 +422,7 @@ pub fn get_known_conda_install_locations(
395422
}
396423
known_paths.sort();
397424
known_paths.dedup();
398-
399-
known_paths
425+
known_paths.into_iter().filter(|f| f.exists()).collect()
400426
}
401427

402428
pub fn get_conda_dir_from_exe(conda_executable: &Option<PathBuf>) -> Option<PathBuf> {

crates/pet-conda/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use pet_core::{
1515
os_environment::Environment,
1616
python_environment::{PythonEnvironment, PythonEnvironmentKind},
1717
reporter::Reporter,
18-
Locator,
18+
Locator, LocatorKind,
1919
};
2020
use pet_fs::path::norm_case;
2121
use serde::{Deserialize, Serialize};
@@ -203,8 +203,8 @@ impl Conda {
203203
}
204204

205205
impl Locator for Conda {
206-
fn get_name(&self) -> &'static str {
207-
"Conda" // Do not change this name, as this is used in telemetry.
206+
fn get_kind(&self) -> LocatorKind {
207+
LocatorKind::Conda
208208
}
209209
fn configure(&self, config: &pet_core::Configuration) {
210210
if let Some(ref conda_exe) = config.conda_executable {

crates/pet-conda/tests/environment_locations_test.rs

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -3,52 +3,6 @@
33

44
mod common;
55

6-
#[cfg(unix)]
7-
#[test]
8-
fn read_environment_txt() {
9-
use common::{create_env_variables, resolve_test_path};
10-
use pet_conda::environment_locations::get_conda_envs_from_environment_txt;
11-
use std::path::PathBuf;
12-
13-
let root = resolve_test_path(&["unix", "root_empty"]).into();
14-
let home = resolve_test_path(&["unix", "user_home_with_environments_txt"]).into();
15-
let env = create_env_variables(home, root);
16-
17-
let mut environments = get_conda_envs_from_environment_txt(&env);
18-
environments.sort();
19-
20-
let mut expected = vec![
21-
"/Users/username/miniconda3",
22-
"/Users/username/miniconda3/envs/xyz",
23-
"/Users/username/miniconda3/envs/conda1",
24-
"/Users/username/miniconda3/envs/conda2",
25-
"/Users/username/miniconda3/envs/conda3",
26-
"/Users/username/miniconda3/envs/conda4",
27-
"/Users/username/miniconda3/envs/conda5",
28-
"/Users/username/miniconda3/envs/conda6",
29-
"/Users/username/miniconda3/envs/conda7",
30-
"/Users/username/miniconda3/envs/conda8",
31-
"/Users/username/.pyenv/versions/miniconda3-latest",
32-
"/Users/username/.pyenv/versions/miniconda3-latest/envs/myenv",
33-
"/Users/username/.pyenv/versions/miniforge3-4.10.1-1",
34-
"/Users/username/.pyenv/versions/anaconda3-2023.03",
35-
"/Users/username/miniforge3/envs/sample1",
36-
"/Users/username/temp/conda_work_folder",
37-
"/Users/username/temp/conda_work_folder_3.12",
38-
"/Users/username/temp/conda_work_folder__no_python",
39-
"/Users/username/temp/conda_work_folder_from_root",
40-
"/Users/username/temp/sample-conda-envs-folder/hello_world",
41-
"/Users/username/temp/sample-conda-envs-folder2/another",
42-
"/Users/username/temp/sample-conda-envs-folder2/xyz",
43-
]
44-
.iter()
45-
.map(PathBuf::from)
46-
.collect::<Vec<PathBuf>>();
47-
expected.sort();
48-
49-
assert_eq!(environments, expected);
50-
}
51-
526
#[cfg(unix)]
537
#[test]
548
fn non_existent_envrionments_txt() {

crates/pet-core/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ edition = "2021"
77
msvc_spectre_libs = { version = "0.1.1", features = ["error"] }
88

99
[dependencies]
10+
clap = { version = "4.5.4", features = ["derive", "cargo"] }
1011
pet-fs = { path = "../pet-fs" }
1112
serde = { version = "1.0.152", features = ["derive"] }
1213
lazy_static = "1.4.0"

crates/pet-core/src/lib.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ pub struct LocatorResult {
2727
pub struct Configuration {
2828
/// These are paths like workspace folders, where we can look for environments.
2929
pub workspace_directories: Option<Vec<PathBuf>>,
30+
pub executables: Option<Vec<PathBuf>>,
3031
pub conda_executable: Option<PathBuf>,
3132
pub poetry_executable: Option<PathBuf>,
3233
/// Custom locations where environments can be found.
@@ -37,9 +38,27 @@ pub struct Configuration {
3738
pub cache_directory: Option<PathBuf>,
3839
}
3940

41+
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
42+
pub enum LocatorKind {
43+
Conda,
44+
Homebrew,
45+
LinuxGlobal,
46+
MacCommandLineTools,
47+
MacPythonOrg,
48+
MacXCode,
49+
PipEnv,
50+
Poetry,
51+
PyEnv,
52+
Venv,
53+
VirtualEnv,
54+
VirtualEnvWrapper,
55+
WindowsRegistry,
56+
WindowsStore,
57+
}
58+
4059
pub trait Locator: Send + Sync {
4160
/// Returns the name of the locator.
42-
fn get_name(&self) -> &'static str;
61+
fn get_kind(&self) -> LocatorKind;
4362
/// Configures the locator with the given configuration.
4463
/// Override this method if you need to have some custom configuration.
4564
/// E.g. storing some of the configuration information in the locator.

crates/pet-core/src/python_environment.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
// Copyright (c) Microsoft Corporation.
22
// Licensed under the MIT License.
33

4+
use clap::{Parser, ValueEnum};
45
use log::error;
56
use pet_fs::path::norm_case;
67
use serde::{Deserialize, Serialize};
78
use std::path::PathBuf;
89

910
use crate::{arch::Architecture, manager::EnvManager};
1011

11-
#[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Debug, Hash)]
12+
#[derive(Parser, ValueEnum, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Debug, Hash)]
1213
pub enum PythonEnvironmentKind {
1314
Conda,
1415
Homebrew,
15-
Pyenv, // Relates to Python installations in pyenv that are from Python org.
16+
Pyenv,
1617
GlobalPaths, // Python found in global locations like PATH, /usr/bin etc.
1718
PyenvVirtualEnv, // Pyenv virtualenvs.
1819
Pipenv,
@@ -21,7 +22,6 @@ pub enum PythonEnvironmentKind {
2122
MacCommandLineTools,
2223
LinuxGlobal,
2324
MacXCode,
24-
Unknown,
2525
Venv,
2626
VirtualEnv,
2727
VirtualEnvWrapper,

crates/pet-homebrew/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use pet_core::{
99
os_environment::Environment,
1010
python_environment::{PythonEnvironment, PythonEnvironmentKind},
1111
reporter::Reporter,
12-
Locator,
12+
Locator, LocatorKind,
1313
};
1414
use pet_fs::path::resolve_symlink;
1515
use pet_python_utils::executable::find_executables;
@@ -110,8 +110,8 @@ fn from(env: &PythonEnv) -> Option<PythonEnvironment> {
110110
}
111111

112112
impl Locator for Homebrew {
113-
fn get_name(&self) -> &'static str {
114-
"Homebrew" // Do not change this name, as this is used in telemetry.
113+
fn get_kind(&self) -> LocatorKind {
114+
LocatorKind::Homebrew
115115
}
116116
fn supported_categories(&self) -> Vec<PythonEnvironmentKind> {
117117
vec![PythonEnvironmentKind::Homebrew]

crates/pet-linux-global-python/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use pet_core::{
1414
env::PythonEnv,
1515
python_environment::{PythonEnvironment, PythonEnvironmentBuilder, PythonEnvironmentKind},
1616
reporter::Reporter,
17-
Locator,
17+
Locator, LocatorKind,
1818
};
1919
use pet_fs::path::resolve_symlink;
2020
use pet_python_utils::{env::ResolvedPythonEnv, executable::find_executables};
@@ -53,8 +53,8 @@ impl Default for LinuxGlobalPython {
5353
}
5454
}
5555
impl Locator for LinuxGlobalPython {
56-
fn get_name(&self) -> &'static str {
57-
"LinuxGlobalPython" // Do not change this name, as this is used in telemetry.
56+
fn get_kind(&self) -> LocatorKind {
57+
LocatorKind::LinuxGlobal
5858
}
5959
fn supported_categories(&self) -> Vec<PythonEnvironmentKind> {
6060
vec![PythonEnvironmentKind::LinuxGlobal]

crates/pet-mac-commandlinetools/src/lib.rs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@
22
// Licensed under the MIT License.
33

44
use pet_core::{
5+
arch::Architecture,
56
env::PythonEnv,
67
python_environment::{PythonEnvironment, PythonEnvironmentBuilder, PythonEnvironmentKind},
78
reporter::Reporter,
8-
Locator,
9+
Locator, LocatorKind,
910
};
1011
use pet_fs::path::resolve_symlink;
1112
use pet_python_utils::version;
@@ -26,8 +27,8 @@ impl Default for MacCmdLineTools {
2627
}
2728
}
2829
impl Locator for MacCmdLineTools {
29-
fn get_name(&self) -> &'static str {
30-
"MacCmdLineTools" // Do not change this name, as this is used in telemetry.
30+
fn get_kind(&self) -> LocatorKind {
31+
LocatorKind::MacCommandLineTools
3132
}
3233
fn supported_categories(&self) -> Vec<PythonEnvironmentKind> {
3334
vec![PythonEnvironmentKind::MacCommandLineTools]
@@ -57,6 +58,7 @@ impl Locator for MacCmdLineTools {
5758
let mut version = env.version.clone();
5859
let mut prefix = env.prefix.clone();
5960
let mut symlinks = vec![env.executable.clone()];
61+
let mut arch = None;
6062

6163
let existing_symlinks = env.symlinks.clone();
6264
if let Some(existing_symlinks) = existing_symlinks {
@@ -113,6 +115,11 @@ impl Locator for MacCmdLineTools {
113115
// Use the latest accurate information we have.
114116
version = Some(resolved_env.version);
115117
prefix = Some(resolved_env.prefix);
118+
arch = if resolved_env.is64_bit {
119+
Some(Architecture::X64)
120+
} else {
121+
Some(Architecture::X86)
122+
};
116123
}
117124
}
118125
}
@@ -165,18 +172,25 @@ impl Locator for MacCmdLineTools {
165172
version = version::from_header_files(prefix);
166173
}
167174
}
175+
168176
if version.is_none() || prefix.is_none() {
169177
if let Some(resolved_env) = ResolvedPythonEnv::from(&env.executable) {
170178
resolved_environments.push(resolved_env.clone());
171179
version = Some(resolved_env.version);
172180
prefix = Some(resolved_env.prefix);
181+
arch = if resolved_env.is64_bit {
182+
Some(Architecture::X64)
183+
} else {
184+
Some(Architecture::X86)
185+
};
173186
}
174187
}
175188

176189
let env = PythonEnvironmentBuilder::new(Some(PythonEnvironmentKind::MacCommandLineTools))
177190
.executable(Some(env.executable.clone()))
178191
.version(version)
179192
.prefix(prefix)
193+
.arch(arch)
180194
.symlinks(Some(symlinks.clone()))
181195
.build();
182196

0 commit comments

Comments
 (0)