From ef7babe22e207c6a22830c5b4d34ecec3b069760 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Tue, 14 May 2024 15:54:24 +1000 Subject: [PATCH 1/2] Remove sysPrefixPath from native locator --- native_locator/src/common_python.rs | 1 - native_locator/src/conda.rs | 203 ++++---- native_locator/src/conda_old.rs | 453 ------------------ native_locator/src/homebrew.rs | 12 +- native_locator/src/messaging.rs | 27 -- native_locator/src/pipenv.rs | 30 +- native_locator/src/pyenv.rs | 34 +- native_locator/src/venv.rs | 1 - native_locator/src/virtualenv.rs | 1 - native_locator/src/virtualenvwrapper.rs | 1 - native_locator/src/windows_store.rs | 10 +- native_locator/tests/common_python_test.rs | 1 - native_locator/tests/conda_test.rs | 2 - native_locator/tests/pyenv_test.rs | 30 +- .../locators/common/nativePythonFinder.ts | 2 +- .../base/locators/lowLevel/nativeLocator.ts | 1 + 16 files changed, 132 insertions(+), 677 deletions(-) delete mode 100644 native_locator/src/conda_old.rs diff --git a/native_locator/src/common_python.rs b/native_locator/src/common_python.rs index f3b7fbbe20c4..3d206529035c 100644 --- a/native_locator/src/common_python.rs +++ b/native_locator/src/common_python.rs @@ -43,7 +43,6 @@ impl Locator for PythonOnPath<'_> { python_executable_path: Some(env.executable.clone()), version: env.version.clone(), category: crate::messaging::PythonEnvironmentCategory::System, - sys_prefix_path: None, env_path: env.path.clone(), env_manager: None, project_path: None, diff --git a/native_locator/src/conda.rs b/native_locator/src/conda.rs index 8f6ae6f8b507..4233461fc264 100644 --- a/native_locator/src/conda.rs +++ b/native_locator/src/conda.rs @@ -63,21 +63,24 @@ fn get_conda_package_json_path(path: &Path, package: &str) -> Option Some(CondaPackage { - path: path.clone(), - version: version.as_str().to_string(), - }), - None => None, + std::fs::read_dir(path) + .ok()? + .filter_map(Result::ok) + .find_map(|entry| { + let path = entry.path(); + let file_name = path.file_name()?.to_string_lossy(); + if file_name.starts_with(&package_name) && file_name.ends_with(".json") { + match regex.clone().ok().unwrap().captures(&file_name)?.get(1) { + Some(version) => Some(CondaPackage { + path: path.clone(), + version: version.as_str().to_string(), + }), + None => None, + } + } else { + None } - } else { - None - } - }) + }) } fn get_conda_executable(path: &PathBuf) -> Option { @@ -109,13 +112,10 @@ fn find_conda_binary_on_path(environment: &dyn known::Environment) -> Option { - if metadata.is_file() || metadata.is_symlink() { - return Some(conda_path); - } + if let Ok(metadata) = std::fs::metadata(&conda_path) { + if metadata.is_file() || metadata.is_symlink() { + return Some(conda_path); } - Err(_) => (), } } } @@ -213,40 +213,37 @@ struct CondaEnvironment { } fn get_conda_environment_info(env_path: &PathBuf, named: bool) -> Option { let metadata = env_path.metadata(); - match metadata { - Ok(metadata) => { - if metadata.is_dir() { - let path = env_path.clone(); - if let Some(python_binary) = find_python_binary_path(&path) { - if let Some(package_info) = get_conda_package_json_path(&path, "python") { - return Some(CondaEnvironment { - name: path.file_name()?.to_string_lossy().to_string(), - path, - named, - python_executable_path: Some(python_binary), - version: Some(package_info.version), - }); - } else { - return Some(CondaEnvironment { - name: path.file_name()?.to_string_lossy().to_string(), - path, - named, - python_executable_path: Some(python_binary), - version: None, - }); - } + if let Ok(metadata) = metadata { + if metadata.is_dir() { + let path = env_path.clone(); + if let Some(python_binary) = find_python_binary_path(&path) { + if let Some(package_info) = get_conda_package_json_path(&path, "python") { + return Some(CondaEnvironment { + name: path.file_name()?.to_string_lossy().to_string(), + path, + named, + python_executable_path: Some(python_binary), + version: Some(package_info.version), + }); } else { return Some(CondaEnvironment { name: path.file_name()?.to_string_lossy().to_string(), path, named, - python_executable_path: None, + python_executable_path: Some(python_binary), version: None, }); } + } else { + return Some(CondaEnvironment { + name: path.file_name()?.to_string_lossy().to_string(), + path, + named, + python_executable_path: None, + version: None, + }); } } - Err(_) => (), } None @@ -258,14 +255,12 @@ fn get_environments_from_envs_folder_in_conda_directory( // iterate through all sub directories in the env folder // for each sub directory, check if it has a python executable // if it does, create a PythonEnvironment object and add it to the list - for entry in std::fs::read_dir(path.join("envs")).ok()? { - match entry { - Ok(entry) => { - if let Some(env) = get_conda_environment_info(&entry.path(), true) { - envs.push(env); - } - } - Err(_) => (), + for entry in std::fs::read_dir(path.join("envs")) + .ok()? + .filter_map(Result::ok) + { + if let Some(env) = get_conda_environment_info(&entry.path(), true) { + envs.push(env); } } @@ -274,21 +269,14 @@ fn get_environments_from_envs_folder_in_conda_directory( fn get_conda_envs_from_environment_txt(environment: &dyn known::Environment) -> Vec { let mut envs = vec![]; - let home = environment.get_user_home(); - match home { - Some(home) => { - let home = Path::new(&home); - let environment_txt = home.join(".conda").join("environments.txt"); - match std::fs::read_to_string(environment_txt) { - Ok(reader) => { - for line in reader.lines() { - envs.push(line.to_string()); - } - } - Err(_) => (), + if let Some(home) = environment.get_user_home() { + let home = Path::new(&home); + let environment_txt = home.join(".conda").join("environments.txt"); + if let Ok(reader) = std::fs::read_to_string(environment_txt) { + for line in reader.lines() { + envs.push(line.to_string()); } } - None => (), } envs } @@ -309,31 +297,28 @@ fn get_conda_conda_rc(environment: &dyn known::Environment) -> Option { if let Some(home) = environment.get_user_home() { let conda_rc = Path::new(&home).join(".condarc"); let mut start_consuming_values = false; - match std::fs::read_to_string(conda_rc) { - Ok(reader) => { - let mut env_dirs = vec![]; - for line in reader.lines() { - if line.starts_with("envs_dirs:") && !start_consuming_values { - start_consuming_values = true; - continue; - } - if start_consuming_values { - if line.trim().starts_with("-") { - if let Some(env_dir) = line.splitn(2, '-').nth(1) { - let env_dir = PathBuf::from(env_dir.trim()); - if env_dir.exists() { - env_dirs.push(env_dir); - } + if let Ok(reader) = std::fs::read_to_string(conda_rc) { + let mut env_dirs = vec![]; + for line in reader.lines() { + if line.starts_with("envs_dirs:") && !start_consuming_values { + start_consuming_values = true; + continue; + } + if start_consuming_values { + if line.trim().starts_with("-") { + if let Some(env_dir) = line.splitn(2, '-').nth(1) { + let env_dir = PathBuf::from(env_dir.trim()); + if env_dir.exists() { + env_dirs.push(env_dir); } - continue; - } else { - break; } + continue; + } else { + break; } } - return Some(Condarc { env_dirs }); } - Err(_) => (), + return Some(Condarc { env_dirs }); } } None @@ -346,21 +331,16 @@ fn get_conda_envs_from_conda_rc( let mut envs: Vec = vec![]; for env in get_conda_conda_rc(environment)?.env_dirs { if let Ok(reader) = std::fs::read_dir(env) { - for entry in reader { - match entry { - Ok(entry) => { - if entry.path().is_dir() - && was_conda_environment_created_by_specific_conda( - &entry.path(), - root_conda_path, - ) - { - if let Some(env) = get_conda_environment_info(&entry.path(), false) { - envs.push(env); - } - } + for entry in reader.filter_map(Result::ok) { + if entry.path().is_dir() + && was_conda_environment_created_by_specific_conda( + &entry.path(), + root_conda_path, + ) + { + if let Some(env) = get_conda_environment_info(&entry.path(), false) { + envs.push(env); } - Err(_) => (), } } } @@ -383,23 +363,17 @@ fn was_conda_environment_created_by_specific_conda( root_conda_path: &PathBuf, ) -> bool { let conda_meta_history = env_path.join("conda-meta").join("history"); - match std::fs::read_to_string(conda_meta_history.clone()) { - Ok(reader) => { - for line in reader.lines() { - let line = line.to_lowercase(); - if line.starts_with("# cmd:") && line.contains(" create ") { - if line.contains(&root_conda_path.to_str().unwrap().to_lowercase()) { - return true; - } else { - return false; - } + if let Ok(reader) = std::fs::read_to_string(conda_meta_history.clone()) { + for line in reader.lines() { + let line = line.to_lowercase(); + if line.starts_with("# cmd:") && line.contains(" create ") { + if line.contains(&root_conda_path.to_str().unwrap().to_lowercase()) { + return true; + } else { + return false; } } } - Err(_) => warn!( - "Error reading conda-meta/history file {:?}", - conda_meta_history - ), } false @@ -555,7 +529,6 @@ fn get_root_python_environment(path: &PathBuf, manager: &EnvManager) -> Option

Option { - if any_path.ends_with("bin/python") { - match any_path.parent() { - Some(parent) => match parent.parent() { - Some(parent) => Some(parent.to_path_buf().join("conda-meta")), - None => None, - }, - None => None, - } - } else if any_path.ends_with("bin") { - match any_path.parent() { - Some(parent) => Some(parent.to_path_buf().join("conda-meta")), - None => None, - } - } else { - Some(any_path.to_path_buf().join("conda-meta")) - } -} - -/// Get the conda-meta directory. For windows 'conda-meta' is in the same directory as the interpreter. -/// This layout is common in Windows. -/// -/// ``` -/// env // <--- Input can be this path -/// |-- conda-meta // <--- Returns this directory -/// |-- python.exe // <--- Input can be this path -/// ``` -#[cfg(windows)] -fn get_conda_meta_path(any_path: &Path) -> Option { - if any_path.ends_with("python.exe") { - match any_path.parent() { - Some(parent) => Some(parent.to_path_buf().join("conda-meta")), - None => None, - } - } else { - Some(any_path.to_path_buf().join("conda-meta")) - } -} - -/// Check if a given path is a conda environment. A conda environment is a directory that contains -/// a 'conda-meta' directory as child. This will find 'conda-meta' in a platform agnostic way. -pub fn is_conda_environment(any_path: &Path) -> bool { - let conda_meta_path = get_conda_meta_path(any_path); - match conda_meta_path { - Some(path) => path.exists(), - None => false, - } -} - -struct CondaPackage { - path: PathBuf, - version: String, -} - -/// Get the path to the json file along with the version of a package in the conda environment from the 'conda-meta' directory. -fn get_conda_package_json_path(any_path: &Path, package: &str) -> Option { - let package_name = format!("{}-", package); - let conda_meta_path = get_conda_meta_path(any_path)?; - let regex = Regex::new(format!("^{}-((\\d+\\.*)*)-.*.json$", package).as_str()); - std::fs::read_dir(conda_meta_path).ok()?.find_map(|entry| { - let path = entry.ok()?.path(); - let file_name = path.file_name()?.to_string_lossy(); - if file_name.starts_with(&package_name) && file_name.ends_with(".json") { - match regex.clone().ok()?.captures(&file_name)?.get(1) { - Some(version) => Some(CondaPackage { - path: path.clone(), - version: version.as_str().to_string(), - }), - None => None, - } - } else { - None - } - }) -} - -/// Checks if the `python` package is installed in the conda environment -#[allow(dead_code)] -pub fn is_python_conda_env(any_path: &Path) -> bool { - let conda_python_json_path = get_conda_package_json_path(any_path, "python"); - match conda_python_json_path { - Some(result) => result.path.exists(), - None => false, - } -} - -/// Get the version of the `python` package in the conda environment -pub fn get_conda_python_version(any_path: &Path) -> Option { - let conda_python_json_path = get_conda_package_json_path(any_path, "python"); - match conda_python_json_path { - Some(result) => Some(result.version.clone()), - None => None, - } -} - -/// Specifically returns the file names that are valid for 'conda' on windows -#[cfg(windows)] -fn get_conda_bin_names() -> Vec<&'static str> { - vec!["conda.exe", "conda.bat"] -} - -/// Specifically returns the file names that are valid for 'conda' on linux/Mac -#[cfg(unix)] -fn get_conda_bin_names() -> Vec<&'static str> { - vec!["conda"] -} - -/// Find the conda binary on the PATH environment variable -fn find_conda_binary_on_path(environment: &dyn known::Environment) -> Option { - let paths = environment.get_env_var("PATH".to_string())?; - for path in env::split_paths(&paths) { - for bin in get_conda_bin_names() { - let conda_path = path.join(bin); - match std::fs::metadata(&conda_path) { - Ok(metadata) => { - if metadata.is_file() || metadata.is_symlink() { - return Some(conda_path); - } - } - Err(_) => (), - } - } - } - None -} - -#[cfg(windows)] -fn get_known_conda_locations(environment: &dyn known::Environment) -> Vec { - let user_profile = environment.get_env_var("USERPROFILE".to_string()).unwrap(); - let program_data = environment.get_env_var("PROGRAMDATA".to_string()).unwrap(); - let all_user_profile = environment - .get_env_var("ALLUSERSPROFILE".to_string()) - .unwrap(); - let home_drive = environment.get_env_var("HOMEDRIVE".to_string()).unwrap(); - let mut known_paths = vec![ - Path::new(&user_profile).join("Anaconda3\\Scripts"), - Path::new(&program_data).join("Anaconda3\\Scripts"), - Path::new(&all_user_profile).join("Anaconda3\\Scripts"), - Path::new(&home_drive).join("Anaconda3\\Scripts"), - Path::new(&user_profile).join("Miniconda3\\Scripts"), - Path::new(&program_data).join("Miniconda3\\Scripts"), - Path::new(&all_user_profile).join("Miniconda3\\Scripts"), - Path::new(&home_drive).join("Miniconda3\\Scripts"), - ]; - known_paths.append(&mut environment.get_know_global_search_locations()); - known_paths -} - -#[cfg(unix)] -fn get_known_conda_locations(environment: &dyn known::Environment) -> Vec { - let mut known_paths = vec![ - PathBuf::from("/opt/anaconda3/bin"), - PathBuf::from("/opt/miniconda3/bin"), - PathBuf::from("/usr/local/anaconda3/bin"), - PathBuf::from("/usr/local/miniconda3/bin"), - PathBuf::from("/usr/anaconda3/bin"), - PathBuf::from("/usr/miniconda3/bin"), - PathBuf::from("/home/anaconda3/bin"), - PathBuf::from("/home/miniconda3/bin"), - PathBuf::from("/anaconda3/bin"), - PathBuf::from("/miniconda3/bin"), - ]; - if let Some(home) = environment.get_user_home() { - known_paths.push(PathBuf::from(home.clone()).join("anaconda3/bin")); - known_paths.push(PathBuf::from(home).join("miniconda3/bin")); - } - known_paths.append(&mut environment.get_know_global_search_locations()); - known_paths -} - -/// Find conda binary in known locations -fn find_conda_binary_in_known_locations(environment: &dyn known::Environment) -> Option { - let conda_bin_names = get_conda_bin_names(); - let known_locations = get_known_conda_locations(environment); - for location in known_locations { - for bin in &conda_bin_names { - let conda_path = location.join(bin); - if let Some(metadata) = std::fs::metadata(&conda_path).ok() { - if metadata.is_file() || metadata.is_symlink() { - return Some(conda_path); - } - } - } - } - None -} - -/// Find the conda binary on the system -pub fn find_conda_binary(environment: &dyn known::Environment) -> Option { - let conda_binary_on_path = find_conda_binary_on_path(environment); - match conda_binary_on_path { - Some(conda_binary_on_path) => Some(conda_binary_on_path), - None => find_conda_binary_in_known_locations(environment), - } -} - -pub fn get_conda_version(conda_binary: &PathBuf) -> Option { - let mut parent = conda_binary.parent()?; - if parent.ends_with("bin") { - parent = parent.parent()?; - } - if parent.ends_with("Library") { - parent = parent.parent()?; - } - match get_conda_package_json_path(&parent, "conda") { - Some(result) => Some(result.version), - None => match get_conda_package_json_path(&parent.parent()?, "conda") { - Some(result) => Some(result.version), - None => None, - }, - } -} - -fn get_conda_envs_from_environment_txt(environment: &dyn known::Environment) -> Vec { - let mut envs = vec![]; - let home = environment.get_user_home(); - match home { - Some(home) => { - let home = Path::new(&home); - let environment_txt = home.join(".conda").join("environments.txt"); - match std::fs::read_to_string(environment_txt) { - Ok(reader) => { - for line in reader.lines() { - envs.push(line.to_string()); - } - } - Err(_) => (), - } - } - None => (), - } - envs -} - -fn get_known_env_locations( - conda_bin: &PathBuf, - environment: &dyn known::Environment, -) -> Vec { - let mut paths = vec![]; - let home = environment.get_user_home(); - match home { - Some(home) => { - let home = Path::new(&home); - let conda_envs = home.join(".conda").join("envs"); - paths.push(conda_envs.to_string_lossy().to_string()); - } - None => (), - } - - match conda_bin.parent() { - Some(parent) => { - paths.push(parent.to_string_lossy().to_string()); - let conda_envs = parent.join("envs"); - paths.push(conda_envs.to_string_lossy().to_string()); - match parent.parent() { - Some(parent) => { - paths.push(parent.to_string_lossy().to_string()); - let conda_envs = parent.join("envs"); - paths.push(conda_envs.to_string_lossy().to_string()); - } - None => (), - } - } - None => (), - } - - paths -} - -fn get_conda_envs_from_known_env_locations( - conda_bin: &PathBuf, - environment: &dyn known::Environment, -) -> Vec { - let mut envs = vec![]; - for location in get_known_env_locations(conda_bin, environment) { - if is_conda_environment(&Path::new(&location)) { - envs.push(location.to_string()); - } - match std::fs::read_dir(location) { - Ok(reader) => { - for entry in reader { - match entry { - Ok(entry) => { - let metadata = entry.metadata(); - match metadata { - Ok(metadata) => { - if metadata.is_dir() { - let path = entry.path(); - if is_conda_environment(&path) { - envs.push(path.to_string_lossy().to_string()); - } - } - } - Err(_) => (), - } - } - Err(_) => (), - } - } - } - Err(_) => (), - } - } - envs -} - -struct CondaEnv { - named: bool, - name: String, - path: PathBuf, -} - -fn get_distinct_conda_envs( - conda_bin: &PathBuf, - environment: &dyn known::Environment, -) -> Vec { - let mut envs = get_conda_envs_from_environment_txt(environment); - let mut known_envs = get_conda_envs_from_known_env_locations(conda_bin, environment); - envs.append(&mut known_envs); - envs.sort(); - envs.dedup(); - - let locations = get_known_env_locations(conda_bin, environment); - let mut conda_envs = vec![]; - for env in envs { - let env = Path::new(&env); - let mut named = false; - let mut name = "".to_string(); - for location in &locations { - let location = Path::new(location).join("envs"); - match env.strip_prefix(location) { - Ok(prefix) => { - named = true; - name = match prefix.to_str() { - Some(name) => { - let name = name.to_string(); - if name == "" { - "base".to_string() - } else { - name.to_string() - } - } - None => "base".to_string(), - }; - break; - } - Err(_) => (), - } - } - conda_envs.push(CondaEnv { - named, - name, - path: PathBuf::from(env), - }); - } - conda_envs -} - -pub struct Conda<'a> { - pub manager: Option, - pub environment: &'a dyn Environment, -} - -impl Conda<'_> { - pub fn with<'a>(environment: &'a impl Environment) -> Conda { - Conda { - environment, - manager: None, - } - } -} - -impl Locator for Conda<'_> { - fn resolve(&self, _env: &PythonEnv) -> Option { - // We will find everything in gather - None - } - - fn find(&mut self) -> Option { - let conda_binary = find_conda_binary(self.environment)?; - let manager = EnvManager::new( - conda_binary.clone(), - get_conda_version(&conda_binary), - EnvManagerType::Conda, - ); - - let envs = get_distinct_conda_envs(&conda_binary, self.environment); - let mut environments: Vec = vec![]; - for env in envs { - let executable = find_python_binary_path(Path::new(&env.path)); - let env = messaging::PythonEnvironment::new( - None, - Some(env.name.to_string()), - executable.clone(), - messaging::PythonEnvironmentCategory::Conda, - get_conda_python_version(&env.path), - Some(env.path.clone()), - Some(env.path.clone()), - Some(manager.clone()), - if env.named { - Some(vec![ - conda_binary.to_string_lossy().to_string(), - "run".to_string(), - "-n".to_string(), - env.name.to_string(), - "python".to_string(), - ]) - } else { - Some(vec![ - conda_binary.to_string_lossy().to_string(), - "run".to_string(), - "-p".to_string(), - env.path.to_string_lossy().to_string(), - "python".to_string(), - ]) - }, - ); - - environments.push(env) - } - - Some(LocatorResult { - managers: vec![manager], - environments, - }) - } -} diff --git a/native_locator/src/homebrew.rs b/native_locator/src/homebrew.rs index 34a02fe9845f..f51e783e12c8 100644 --- a/native_locator/src/homebrew.rs +++ b/native_locator/src/homebrew.rs @@ -8,10 +8,10 @@ use crate::{ utils::PythonEnv, }; use regex::Regex; -use std::{collections::HashSet, fs::DirEntry, io::Error, path::PathBuf}; +use std::{collections::HashSet, fs::DirEntry, path::PathBuf}; -fn is_symlinked_python_executable(path: Result) -> Option { - let path = path.ok()?.path(); +fn is_symlinked_python_executable(path: DirEntry) -> Option { + let path = path.path(); let name = path.file_name()?.to_string_lossy(); if !name.starts_with("python") || name.ends_with("-config") || name.ends_with("-build") { return None; @@ -46,7 +46,10 @@ impl Locator for Homebrew<'_> { let mut reported: HashSet = HashSet::new(); let python_regex = Regex::new(r"/(\d+\.\d+\.\d+)/").unwrap(); let mut environments: Vec = vec![]; - for file in std::fs::read_dir(homebrew_prefix_bin).ok()? { + for file in std::fs::read_dir(homebrew_prefix_bin) + .ok()? + .filter_map(Result::ok) + { if let Some(exe) = is_symlinked_python_executable(file) { let python_version = exe.to_string_lossy().to_string(); let version = match python_regex.captures(&python_version) { @@ -68,7 +71,6 @@ impl Locator for Homebrew<'_> { version, None, None, - None, Some(vec![exe.to_string_lossy().to_string()]), ); environments.push(env); diff --git a/native_locator/src/messaging.rs b/native_locator/src/messaging.rs index b79c5fa172ca..34a2ca1d8c73 100644 --- a/native_locator/src/messaging.rs +++ b/native_locator/src/messaging.rs @@ -100,7 +100,6 @@ pub struct PythonEnvironment { pub category: PythonEnvironmentCategory, pub version: Option, pub env_path: Option, - pub sys_prefix_path: Option, pub env_manager: Option, pub python_run_command: Option>, /** @@ -117,7 +116,6 @@ impl PythonEnvironment { category: PythonEnvironmentCategory, version: Option, env_path: Option, - sys_prefix_path: Option, env_manager: Option, python_run_command: Option>, ) -> Self { @@ -128,36 +126,11 @@ impl PythonEnvironment { category, version, env_path, - sys_prefix_path, env_manager, python_run_command, project_path: None, } } - pub fn new_pipenv( - python_executable_path: Option, - version: Option, - env_path: Option, - sys_prefix_path: Option, - env_manager: Option, - project_path: PathBuf, - ) -> Self { - Self { - display_name: None, - name: None, - python_executable_path: python_executable_path.clone(), - category: PythonEnvironmentCategory::Pipenv, - version, - env_path, - sys_prefix_path, - env_manager, - python_run_command: match python_executable_path { - Some(exe) => Some(vec![exe.to_string_lossy().to_string()]), - None => None, - }, - project_path: Some(project_path), - } - } } #[derive(Serialize, Deserialize)] diff --git a/native_locator/src/pipenv.rs b/native_locator/src/pipenv.rs index 0acd00893310..bb5eab5776fe 100644 --- a/native_locator/src/pipenv.rs +++ b/native_locator/src/pipenv.rs @@ -9,15 +9,12 @@ use std::path::PathBuf; fn get_pipenv_project(env: &PythonEnv) -> Option { let project_file = env.path.clone()?.join(".project"); - if project_file.exists() { - if let Ok(contents) = fs::read_to_string(project_file) { - let project_folder = PathBuf::from(contents.trim().to_string()); - if project_folder.exists() { - return Some(project_folder); - } + if let Ok(contents) = fs::read_to_string(project_file) { + let project_folder = PathBuf::from(contents.trim().to_string()); + if project_folder.exists() { + return Some(project_folder); } } - None } @@ -32,14 +29,17 @@ impl PipEnv { impl Locator for PipEnv { fn resolve(&self, env: &PythonEnv) -> Option { let project_path = get_pipenv_project(env)?; - Some(PythonEnvironment::new_pipenv( - Some(env.executable.clone()), - env.version.clone(), - env.path.clone(), - env.path.clone(), - None, - project_path, - )) + Some(PythonEnvironment { + display_name: None, + name: None, + python_executable_path: Some(env.executable.clone()), + category: crate::messaging::PythonEnvironmentCategory::Pipenv, + version: env.version.clone(), + env_path: env.path.clone(), + env_manager: None, + python_run_command: Some(vec![env.executable.to_str().unwrap().to_string()]), + project_path: Some(project_path), + }) } fn find(&mut self) -> Option { diff --git a/native_locator/src/pyenv.rs b/native_locator/src/pyenv.rs index a94d63bc4751..9137a80df1f7 100644 --- a/native_locator/src/pyenv.rs +++ b/native_locator/src/pyenv.rs @@ -111,7 +111,6 @@ fn get_pure_python_environment( messaging::PythonEnvironmentCategory::Pyenv, Some(version), Some(path.clone()), - Some(path.clone()), manager.clone(), Some(vec![executable .clone() @@ -145,7 +144,6 @@ fn get_virtual_env_environment( messaging::PythonEnvironmentCategory::PyenvVirtualEnv, Some(pyenv_cfg.version), Some(path.clone()), - Some(path.clone()), manager.clone(), Some(vec![executable .clone() @@ -168,23 +166,21 @@ pub fn list_pyenv_environments( .into_string() .ok()?; - for entry in fs::read_dir(&versions_dir).ok()? { - if let Ok(path) = entry { - let path = path.path(); - if !path.is_dir() { - continue; - } - if let Some(executable) = find_python_binary_path(&path) { - if let Some(env) = get_pure_python_environment(&executable, &path, manager) { - envs.push(env); - } else if let Some(env) = get_virtual_env_environment(&executable, &path, manager) { - envs.push(env); - } else if is_conda_environment(&path) { - if let Some(result) = conda_locator.find_in(&path) { - result.environments.iter().for_each(|e| { - envs.push(e.clone()); - }); - } + for entry in fs::read_dir(&versions_dir).ok()?.filter_map(Result::ok) { + let path = entry.path(); + if !path.is_dir() { + continue; + } + if let Some(executable) = find_python_binary_path(&path) { + if let Some(env) = get_pure_python_environment(&executable, &path, manager) { + envs.push(env); + } else if let Some(env) = get_virtual_env_environment(&executable, &path, manager) { + envs.push(env); + } else if is_conda_environment(&path) { + if let Some(result) = conda_locator.find_in(&path) { + result.environments.iter().for_each(|e| { + envs.push(e.clone()); + }); } } } diff --git a/native_locator/src/venv.rs b/native_locator/src/venv.rs index 9e0161a6df7d..94040a536989 100644 --- a/native_locator/src/venv.rs +++ b/native_locator/src/venv.rs @@ -39,7 +39,6 @@ impl Locator for Venv { python_executable_path: Some(env.executable.clone()), version: env.version.clone(), category: crate::messaging::PythonEnvironmentCategory::Venv, - sys_prefix_path: env.path.clone(), env_path: env.path.clone(), env_manager: None, project_path: None, diff --git a/native_locator/src/virtualenv.rs b/native_locator/src/virtualenv.rs index 04c10e0e0d25..2a6909e63fa2 100644 --- a/native_locator/src/virtualenv.rs +++ b/native_locator/src/virtualenv.rs @@ -70,7 +70,6 @@ impl Locator for VirtualEnv { python_executable_path: Some(env.executable.clone()), version: env.version.clone(), category: crate::messaging::PythonEnvironmentCategory::VirtualEnv, - sys_prefix_path: env.path.clone(), env_path: env.path.clone(), env_manager: None, project_path: None, diff --git a/native_locator/src/virtualenvwrapper.rs b/native_locator/src/virtualenvwrapper.rs index 856f6a78d537..d55a89e09dca 100644 --- a/native_locator/src/virtualenvwrapper.rs +++ b/native_locator/src/virtualenvwrapper.rs @@ -93,7 +93,6 @@ impl Locator for VirtualEnvWrapper<'_> { python_executable_path: Some(env.executable.clone()), version: env.version.clone(), category: crate::messaging::PythonEnvironmentCategory::Venv, - sys_prefix_path: env.path.clone(), env_path: env.path.clone(), env_manager: None, project_path: None, diff --git a/native_locator/src/windows_store.rs b/native_locator/src/windows_store.rs index 85f67ffe503e..f08622d08127 100644 --- a/native_locator/src/windows_store.rs +++ b/native_locator/src/windows_store.rs @@ -55,9 +55,8 @@ fn list_windows_store_python_executables( display_name: Some(result.display_name), name: None, python_executable_path: Some(exe.clone()), - version: result.version, + version: None, category: crate::messaging::PythonEnvironmentCategory::WindowsStore, - sys_prefix_path: Some(PathBuf::from(result.env_path.clone())), env_path: Some(PathBuf::from(result.env_path.clone())), env_manager: None, project_path: None, @@ -84,7 +83,6 @@ fn get_package_full_name_from_registry(name: String, hkcu: &RegKey) -> Option, env_path: String, } @@ -97,14 +95,9 @@ fn get_package_display_name_and_location(name: String, hkcu: &RegKey) -> Option< let env_path = package_key.get_value("PackageRootFolder").ok()?; let regex = regex::Regex::new("PythonSoftwareFoundation.Python.((\\d+\\.?)*)_.*").ok()?; - let version = match regex.captures(&name)?.get(1) { - Some(version) => Some(version.as_str().to_string()), - None => None, - }; return Some(StorePythonInfo { display_name, - version, env_path, }); } @@ -134,7 +127,6 @@ impl Locator for WindowsStore<'_> { python_executable_path: Some(env.executable.clone()), version: None, category: crate::messaging::PythonEnvironmentCategory::WindowsStore, - sys_prefix_path: None, env_path: None, env_manager: None, project_path: None, diff --git a/native_locator/tests/common_python_test.rs b/native_locator/tests/common_python_test.rs index 06ed5ff7811d..7db280c9496b 100644 --- a/native_locator/tests/common_python_test.rs +++ b/native_locator/tests/common_python_test.rs @@ -42,7 +42,6 @@ fn find_python_in_path_this() { version: None, python_run_command: Some(vec![unix_python_exe.clone().to_str().unwrap().to_string()]), env_path: Some(unix_python.clone()), - sys_prefix_path: None, }; assert_messages( &[json!(env)], diff --git a/native_locator/tests/conda_test.rs b/native_locator/tests/conda_test.rs index fb3d59e59b5d..1705dc72bf47 100644 --- a/native_locator/tests/conda_test.rs +++ b/native_locator/tests/conda_test.rs @@ -126,7 +126,6 @@ fn finds_two_conda_envs_from_txt() { category: python_finder::messaging::PythonEnvironmentCategory::Conda, version: Some("10.0.1".to_string()), env_path: Some(conda_1.clone()), - sys_prefix_path: Some(conda_1.clone()), env_manager: Some(expected_conda_manager.clone()), python_run_command: Some(vec![ conda_exe.clone().to_str().unwrap().to_string(), @@ -144,7 +143,6 @@ fn finds_two_conda_envs_from_txt() { category: python_finder::messaging::PythonEnvironmentCategory::Conda, version: None, env_path: Some(conda_2.clone()), - sys_prefix_path: Some(conda_2.clone()), env_manager: Some(expected_conda_manager.clone()), python_run_command: Some(vec![ conda_exe.clone().to_str().unwrap().to_string(), diff --git a/native_locator/tests/pyenv_test.rs b/native_locator/tests/pyenv_test.rs index 7ad6904867fa..42249586864d 100644 --- a/native_locator/tests/pyenv_test.rs +++ b/native_locator/tests/pyenv_test.rs @@ -124,10 +124,6 @@ fn find_pyenv_envs() { env_path: Some(join_test_paths(&[ home.to_str().unwrap(), ".pyenv/versions/3.9.9" - ])), - sys_prefix_path: Some(join_test_paths(&[ - home.to_str().unwrap(), - ".pyenv/versions/3.9.9" ])), env_manager: Some(expected_manager.clone()) }); @@ -138,7 +134,7 @@ fn find_pyenv_envs() { python_executable_path: Some(join_test_paths(&[ home.to_str().unwrap(), ".pyenv/versions/my-virtual-env/bin/python", - ])), + ])), python_run_command: Some(vec![join_test_paths(&[ home.to_str().unwrap(), ".pyenv/versions/my-virtual-env/bin/python", @@ -152,20 +148,16 @@ fn find_pyenv_envs() { home.to_str().unwrap(), ".pyenv/versions/my-virtual-env", ])), - sys_prefix_path: Some(join_test_paths(&[ - home.to_str().unwrap(), - ".pyenv/versions/my-virtual-env", - ])), - env_manager: Some(expected_manager.clone()), - }; - let expected_3_12_1 = PythonEnvironment { + env_manager: Some(expected_manager.clone()), + }; + let expected_3_12_1 = PythonEnvironment { display_name: None, project_path: None, name: None, python_executable_path: Some(join_test_paths(&[ home.to_str().unwrap(), ".pyenv/versions/3.12.1/bin/python", - ])), + ])), python_run_command: Some(vec![join_test_paths(&[ home.to_str().unwrap(), ".pyenv/versions/3.12.1/bin/python", @@ -179,10 +171,6 @@ fn find_pyenv_envs() { home.to_str().unwrap(), ".pyenv/versions/3.12.1", ])), - sys_prefix_path: Some(join_test_paths(&[ - home.to_str().unwrap(), - ".pyenv/versions/3.12.1", - ])), env_manager: Some(expected_manager.clone()), }; let expected_3_13_dev = PythonEnvironment { @@ -206,10 +194,6 @@ fn find_pyenv_envs() { home.to_str().unwrap(), ".pyenv/versions/3.13-dev", ])), - sys_prefix_path: Some(join_test_paths(&[ - home.to_str().unwrap(), - ".pyenv/versions/3.13-dev", - ])), env_manager: Some(expected_manager.clone()), }; let expected_3_12_1a3 = PythonEnvironment { @@ -233,10 +217,6 @@ fn find_pyenv_envs() { home.to_str().unwrap(), ".pyenv/versions/3.12.1a3", ])), - sys_prefix_path: Some(join_test_paths(&[ - home.to_str().unwrap(), - ".pyenv/versions/3.12.1a3", - ])), env_manager: Some(expected_manager.clone()), }; let environments = get_environments_from_result(&result); diff --git a/src/client/pythonEnvironments/base/locators/common/nativePythonFinder.ts b/src/client/pythonEnvironments/base/locators/common/nativePythonFinder.ts index dbc5914e4715..7d005dd7484a 100644 --- a/src/client/pythonEnvironments/base/locators/common/nativePythonFinder.ts +++ b/src/client/pythonEnvironments/base/locators/common/nativePythonFinder.ts @@ -16,13 +16,13 @@ const NATIVE_LOCATOR = isWindows() : path.join(EXTENSION_ROOT_DIR, 'native_locator', 'bin', 'python-finder'); export interface NativeEnvInfo { + displayName?: string; name: string; pythonExecutablePath?: string; category: string; version?: string; pythonRunCommand?: string[]; envPath?: string; - sysPrefixPath?: string; /** * Path to the project directory when dealing with pipenv virtual environments. */ diff --git a/src/client/pythonEnvironments/base/locators/lowLevel/nativeLocator.ts b/src/client/pythonEnvironments/base/locators/lowLevel/nativeLocator.ts index d39a0af1a61f..4e9d372520f6 100644 --- a/src/client/pythonEnvironments/base/locators/lowLevel/nativeLocator.ts +++ b/src/client/pythonEnvironments/base/locators/lowLevel/nativeLocator.ts @@ -25,6 +25,7 @@ function categoryToKind(category: string): PythonEnvKind { return PythonEnvKind.Conda; case 'system': case 'homebrew': + case 'windowsregistry': return PythonEnvKind.System; case 'pyenv': return PythonEnvKind.Pyenv; From 574eea4ac19e5cfcddd3962efc58759ed70a3afc Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Tue, 14 May 2024 16:08:51 +1000 Subject: [PATCH 2/2] Fix args --- native_locator/src/windows_registry.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/native_locator/src/windows_registry.rs b/native_locator/src/windows_registry.rs index 279ef46d173e..4f8e97710fc2 100644 --- a/native_locator/src/windows_registry.rs +++ b/native_locator/src/windows_registry.rs @@ -58,7 +58,6 @@ fn get_registry_pythons_from_key(hk: &RegKey, company: &str) -> Option