Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 1 addition & 24 deletions crates/pet-conda/src/environment_locations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,13 @@ use std::{

const APP_NAME: &str = "conda";

pub fn get_conda_environment_paths(
env_vars: &EnvVariables,
additional_env_dirs: &Vec<PathBuf>,
) -> Vec<PathBuf> {
pub fn get_conda_environment_paths(env_vars: &EnvVariables) -> Vec<PathBuf> {
let mut env_paths = thread::scope(|s| {
let mut envs = vec![];
for thread in [
s.spawn(|| get_conda_envs_from_environment_txt(env_vars)),
s.spawn(|| get_conda_environment_paths_from_conda_rc(env_vars)),
s.spawn(|| get_conda_environment_paths_from_known_paths(env_vars)),
s.spawn(|| get_conda_environment_paths_from_additional_paths(additional_env_dirs)),
s.spawn(|| get_known_conda_install_locations(env_vars)),
] {
if let Ok(mut env_paths) = thread.join() {
Expand Down Expand Up @@ -121,25 +117,6 @@ fn get_conda_environment_paths_from_known_paths(env_vars: &EnvVariables) -> Vec<
env_paths
}

fn get_conda_environment_paths_from_additional_paths(
additional_env_dirs: &Vec<PathBuf>,
) -> Vec<PathBuf> {
let mut env_paths: Vec<PathBuf> = vec![];
for path in additional_env_dirs {
if let Ok(entries) = fs::read_dir(path) {
for entry in entries.filter_map(Result::ok) {
let path = entry.path();
if path.is_dir() {
env_paths.push(path);
}
}
}
}
env_paths.append(&mut additional_env_dirs.clone());
trace!("Conda environments in additional paths {:?}", env_paths);
env_paths
}

pub fn get_environments(conda_dir: &Path) -> Vec<PathBuf> {
let mut envs: Vec<PathBuf> = vec![];

Expand Down
49 changes: 14 additions & 35 deletions crates/pet-conda/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use pet_core::{
os_environment::Environment,
python_environment::{PythonEnvironment, PythonEnvironmentKind},
reporter::Reporter,
Locator, LocatorResult,
Locator,
};
use pet_python_utils::env::PythonEnv;
use serde::{Deserialize, Serialize};
Expand All @@ -35,7 +35,7 @@ mod telemetry;
pub mod utils;

pub trait CondaLocator: Send + Sync {
fn find_in(&self, path: &Path) -> Option<LocatorResult>;
fn find_and_report(&self, reporter: &dyn Reporter, path: &Path);
fn find_and_report_missing_envs(
&self,
reporter: &dyn Reporter,
Expand All @@ -53,8 +53,6 @@ pub struct CondaTelemetryInfo {
}

pub struct Conda {
/// Directories where conda environments are found (env_dirs returned from `conda info --json`)
pub env_dirs: Arc<Mutex<Vec<PathBuf>>>,
pub environments: Arc<Mutex<HashMap<PathBuf, PythonEnvironment>>>,
pub managers: Arc<Mutex<HashMap<PathBuf, CondaManager>>>,
pub env_vars: EnvVariables,
Expand All @@ -63,12 +61,15 @@ pub struct Conda {
impl Conda {
pub fn from(env: &dyn Environment) -> Conda {
Conda {
env_dirs: Arc::new(Mutex::new(vec![])),
environments: Arc::new(Mutex::new(HashMap::new())),
managers: Arc::new(Mutex::new(HashMap::new())),
env_vars: EnvVariables::from(env),
}
}
fn clear(&self) {
self.environments.lock().unwrap().clear();
self.managers.lock().unwrap().clear();
}
}

impl CondaLocator for Conda {
Expand All @@ -80,19 +81,6 @@ impl CondaLocator for Conda {
// Look for environments that we couldn't find without spawning conda.
let user_provided_conda_exe = conda_executable.is_some();
let conda_info = CondaInfo::from(conda_executable)?;

// Keep track of these directories for next refresh
// This way we can search these directories again and they will be reported.
{
let mut env_dirs = self.env_dirs.lock().unwrap();
env_dirs.append(&mut conda_info.envs_dirs.clone());
conda_info.envs_dirs.iter().for_each(|p| {
if !env_dirs.contains(p) {
env_dirs.push(p.clone());
}
});
}

let environments = self.environments.lock().unwrap().clone();
let new_envs = conda_info
.envs
Expand Down Expand Up @@ -133,9 +121,9 @@ impl CondaLocator for Conda {
}
}

fn find_in(&self, conda_dir: &Path) -> Option<LocatorResult> {
fn find_and_report(&self, reporter: &dyn Reporter, conda_dir: &Path) {
if !is_conda_install(conda_dir) {
return None;
return;
}
if let Some(manager) = CondaManager::from(conda_dir) {
if let Some(conda_dir) = manager.conda_dir.clone() {
Expand All @@ -147,29 +135,23 @@ impl CondaLocator for Conda {
managers.insert(conda_dir.clone(), manager.clone());
drop(managers);

let mut new_environments = vec![];

// Find all the environments in the conda install folder. (under `envs` folder)
for conda_env in
get_conda_environments(&get_environments(&conda_dir), &manager.clone().into())
{
// If reported earlier, no point processing this again.
let mut environments = self.environments.lock().unwrap();
if environments.contains_key(&conda_env.prefix) {
continue;
}
let env = conda_env
.to_python_environment(Some(conda_dir.clone()), Some(manager.to_manager()));
environments.insert(conda_env.prefix.clone(), env.clone());
new_environments.push(env);
reporter.report_manager(&manager.to_manager());
reporter.report_environment(&env);
}

return Some(LocatorResult {
environments: new_environments,
managers: vec![manager.to_manager()],
});
}
}
None
}
}

Expand All @@ -192,7 +174,7 @@ impl Conda {

impl Locator for Conda {
fn get_name(&self) -> &'static str {
"Conda"
"Conda" // Do not change this name, as this is used in telemetry.
}
fn supported_categories(&self) -> Vec<PythonEnvironmentKind> {
vec![PythonEnvironmentKind::Conda]
Expand Down Expand Up @@ -261,15 +243,12 @@ impl Locator for Conda {

fn find(&self, reporter: &dyn Reporter) {
// if we're calling this again, then clear what ever cache we have.
let mut environments = self.environments.lock().unwrap();
environments.clear();
drop(environments);
self.clear();

let env_vars = self.env_vars.clone();
let additional_paths = self.env_dirs.lock().unwrap().clone();
thread::scope(|s| {
// 1. Get a list of all know conda environments file paths
let possible_conda_envs = get_conda_environment_paths(&env_vars, &additional_paths);
let possible_conda_envs = get_conda_environment_paths(&env_vars);
for path in possible_conda_envs {
s.spawn(move || {
// 2. Get the details of the conda environment
Expand Down
3 changes: 3 additions & 0 deletions crates/pet-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ pub struct Configuration {
pub trait Locator: Send + Sync {
/// Returns the name of the locator.
fn get_name(&self) -> &'static str;
/// Configures the locator with the given configuration.
/// Override this method if you need to have some custom configuration.
/// E.g. storing some of the configuration information in the locator.
fn configure(&self, _config: &Configuration) {
//
}
Expand Down
2 changes: 1 addition & 1 deletion crates/pet-homebrew/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ fn from(env: &PythonEnv) -> Option<PythonEnvironment> {

impl Locator for Homebrew {
fn get_name(&self) -> &'static str {
"Homebrew"
"Homebrew" // Do not change this name, as this is used in telemetry.
}
fn supported_categories(&self) -> Vec<PythonEnvironmentKind> {
vec![PythonEnvironmentKind::Homebrew]
Expand Down
2 changes: 1 addition & 1 deletion crates/pet-linux-global-python/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ impl Default for LinuxGlobalPython {
}
impl Locator for LinuxGlobalPython {
fn get_name(&self) -> &'static str {
"LinuxGlobalPython"
"LinuxGlobalPython" // Do not change this name, as this is used in telemetry.
}
fn supported_categories(&self) -> Vec<PythonEnvironmentKind> {
vec![PythonEnvironmentKind::LinuxGlobal]
Expand Down
2 changes: 1 addition & 1 deletion crates/pet-mac-commandlinetools/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ impl Default for MacCmdLineTools {
}
impl Locator for MacCmdLineTools {
fn get_name(&self) -> &'static str {
"MacCmdLineTools"
"MacCmdLineTools" // Do not change this name, as this is used in telemetry.
}
fn supported_categories(&self) -> Vec<PythonEnvironmentKind> {
vec![PythonEnvironmentKind::MacCommandLineTools]
Expand Down
2 changes: 1 addition & 1 deletion crates/pet-mac-python-org/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ impl Default for MacPythonOrg {
}
impl Locator for MacPythonOrg {
fn get_name(&self) -> &'static str {
"MacPythonOrg"
"MacPythonOrg" // Do not change this name, as this is used in telemetry.
}
fn supported_categories(&self) -> Vec<PythonEnvironmentKind> {
vec![PythonEnvironmentKind::MacPythonOrg]
Expand Down
2 changes: 1 addition & 1 deletion crates/pet-mac-xcode/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ impl Default for MacXCode {
}
impl Locator for MacXCode {
fn get_name(&self) -> &'static str {
"MacXCode"
"MacXCode" // Do not change this name, as this is used in telemetry.
}
fn supported_categories(&self) -> Vec<PythonEnvironmentKind> {
vec![PythonEnvironmentKind::MacCommandLineTools]
Expand Down
2 changes: 1 addition & 1 deletion crates/pet-pipenv/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ impl PipEnv {
}
impl Locator for PipEnv {
fn get_name(&self) -> &'static str {
"PipEnv"
"PipEnv" // Do not change this name, as this is used in telemetry.
}
fn supported_categories(&self) -> Vec<PythonEnvironmentKind> {
vec![PythonEnvironmentKind::Pipenv]
Expand Down
53 changes: 22 additions & 31 deletions crates/pet-poetry/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

use env_variables::EnvVariables;
use environment_locations::list_environments;
use log::error;
use manager::PoetryManager;
use pet_core::{
os_environment::Environment,
Expand All @@ -15,10 +14,7 @@ use pet_python_utils::env::PythonEnv;
use pet_virtualenv::is_virtualenv;
use std::{
path::PathBuf,
sync::{
atomic::{AtomicBool, Ordering},
Arc, Mutex,
},
sync::{Arc, Mutex},
};
use telemetry::report_missing_envs;

Expand All @@ -43,27 +39,31 @@ pub struct Poetry {
pub workspace_directories: Arc<Mutex<Vec<PathBuf>>>,
pub env_vars: EnvVariables,
pub poetry_executable: Arc<Mutex<Option<PathBuf>>>,
searched: AtomicBool,
search_result: Arc<Mutex<Option<LocatorResult>>>,
}

impl Poetry {
pub fn new(environment: &dyn Environment) -> Self {
Poetry {
searched: AtomicBool::new(false),
search_result: Arc::new(Mutex::new(None)),
workspace_directories: Arc::new(Mutex::new(vec![])),
env_vars: EnvVariables::from(environment),
poetry_executable: Arc::new(Mutex::new(None)),
}
}
fn clear(&self) {
self.poetry_executable.lock().unwrap().take();
self.search_result.lock().unwrap().take();
}
pub fn from(environment: &dyn Environment) -> Poetry {
Poetry::new(environment)
}
fn find_with_cache(&self) -> Option<LocatorResult> {
if self.searched.load(Ordering::Relaxed) {
return self.search_result.lock().unwrap().clone();
let mut search_result = self.search_result.lock().unwrap();
if let Some(result) = search_result.clone() {
return Some(result);
}

// First find the manager
let manager = manager::PoetryManager::find(
self.poetry_executable.lock().unwrap().clone(),
Expand All @@ -76,28 +76,18 @@ impl Poetry {
if let Some(manager) = &manager {
result.managers.push(manager.to_manager());
}
if let Ok(values) = self.workspace_directories.lock() {
let workspace_dirs = values.clone();
drop(values);
let envs = list_environments(&self.env_vars, &workspace_dirs.clone(), manager)
.unwrap_or_default();
result.environments.extend(envs.clone());
}

match self.search_result.lock().as_mut() {
Ok(search_result) => {
if result.managers.is_empty() && result.environments.is_empty() {
search_result.take();
None
} else {
search_result.replace(result.clone());
Some(result)
}
}
Err(err) => {
error!("Failed to cache to Poetry environments: {:?}", err);
None
}
let workspace_dirs = self.workspace_directories.lock().unwrap().clone();
let envs = list_environments(&self.env_vars, &workspace_dirs, manager).unwrap_or_default();
result.environments.extend(envs.clone());

// Having a value in the search result means that we have already searched for environments
search_result.replace(result.clone());

if result.managers.is_empty() && result.environments.is_empty() {
None
} else {
Some(result)
}
}
}
Expand Down Expand Up @@ -136,7 +126,7 @@ impl PoetryLocator for Poetry {

impl Locator for Poetry {
fn get_name(&self) -> &'static str {
"Poetry"
"Poetry" // Do not change this name, as this is used in telemetry.
}
fn configure(&self, config: &Configuration) {
if let Some(workspace_directories) = &config.workspace_directories {
Expand Down Expand Up @@ -174,6 +164,7 @@ impl Locator for Poetry {
}

fn find(&self, reporter: &dyn Reporter) {
self.clear();
if let Some(result) = self.find_with_cache() {
for manager in result.managers {
reporter.report_manager(&manager.clone());
Expand Down
Loading