From faa5a7c0b897071962d1af5d6fd5aff32494c74b Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Mon, 13 May 2024 11:28:50 +1000 Subject: [PATCH 1/5] Look for Python in windows registry for PythonCore --- native_locator/src/lib.rs | 2 + native_locator/src/main.rs | 11 +- native_locator/src/messaging.rs | 1 + native_locator/src/windows_registry.rs | 148 +++++++++++------- .../{windows_python.rs => windows_store.rs} | 25 +-- 5 files changed, 108 insertions(+), 79 deletions(-) rename native_locator/src/{windows_python.rs => windows_store.rs} (82%) diff --git a/native_locator/src/lib.rs b/native_locator/src/lib.rs index 251e977af00c..ba353c71ce12 100644 --- a/native_locator/src/lib.rs +++ b/native_locator/src/lib.rs @@ -14,3 +14,5 @@ pub mod pipenv; pub mod virtualenv; pub mod venv; pub mod locator; +pub mod windows_registry; +pub mod windows_store; diff --git a/native_locator/src/main.rs b/native_locator/src/main.rs index 6f511ad3dddd..56b6dc65e237 100644 --- a/native_locator/src/main.rs +++ b/native_locator/src/main.rs @@ -24,7 +24,8 @@ mod utils; mod venv; mod virtualenv; mod virtualenvwrapper; -mod windows_python; +mod windows_store; +mod windows_registry; fn main() { let environment = EnvironmentApi {}; @@ -44,7 +45,9 @@ fn main() { #[cfg(unix)] let homebrew_locator = homebrew::Homebrew::with(&environment); #[cfg(windows)] - let windows_locator = windows_python::WindowsPython::with(&environment); + let windows_store = windows_store::WindowsStore::with(&environment); + #[cfg(windows)] + let windows_registry = windows_registry::WindowsRegistry::new(); let conda_locator = conda::Conda::with(&environment); // Step 1: These environments take precedence over all others. @@ -54,7 +57,9 @@ fn main() { find_environments(&homebrew_locator, &mut dispatcher); find_environments(&conda_locator, &mut dispatcher); #[cfg(windows)] - find_environments(&windows_locator, &mut dispatcher); + find_environments(&windows_registry, &mut dispatcher); + #[cfg(windows)] + find_environments(&windows_store, &mut dispatcher); // Step 2: Search in some global locations. for env in list_global_virtual_envs(&environment).iter() { diff --git a/native_locator/src/messaging.rs b/native_locator/src/messaging.rs index 959ec8d36f31..b39cd19bb5b6 100644 --- a/native_locator/src/messaging.rs +++ b/native_locator/src/messaging.rs @@ -83,6 +83,7 @@ pub enum PythonEnvironmentCategory { Pyenv, PyenvVirtualEnv, WindowsStore, + WindowsRegistry, Pipenv, VirtualEnvWrapper, Venv, diff --git a/native_locator/src/windows_registry.rs b/native_locator/src/windows_registry.rs index beb503a4a541..e139529b1341 100644 --- a/native_locator/src/windows_registry.rs +++ b/native_locator/src/windows_registry.rs @@ -1,59 +1,89 @@ -// // Copyright (c) Microsoft Corporation. All rights reserved. -// // Licensed under the MIT License. -// use crate::messaging; -// use std::path::PathBuf; -// use winreg::RegKey; - -// fn get_registry_pythons_from_key( -// dispatcher: &mut impl messaging::MessageDispatcher, -// hk: &RegKey, -// company: &str, -// ) -> Option> { -// let python_key = hk.open_subkey("Software\\Python").ok()?; -// let company_key = python_key.open_subkey(company).ok()?; - -// let mut pythons = vec![]; -// for key in company_key.enum_keys().filter_map(Result::ok) { -// let version_key = company_key.open_subkey(key).ok()?; -// let install_path_key = version_key.open_subkey("InstallPath").ok()?; -// let executable: String = install_path_key.get_value("ExecutablePath").ok()?; -// let version = version_key.get_value("Version").ok()?; - -// dispatcher.report_environment(messaging::PythonEnvironment::new( -// None, -// Some(PathBuf::from(executable.clone())), -// messaging::PythonEnvironmentCategory::WindowsRegistry, -// Some(version), -// None, -// None, -// None, -// None, -// )); - -// pythons.push(PathBuf::from(executable)); -// } - -// Some(pythons) -// } - -// #[cfg(windows)] -// pub fn report_and_get_registry_pythons( -// dispatcher: &mut impl messaging::MessageDispatcher, -// company: &str, -// ) -> Option> { -// let hklm = winreg::RegKey::predef(winreg::enums::HKEY_LOCAL_MACHINE); -// let hkcu = winreg::RegKey::predef(winreg::enums::HKEY_CURRENT_USER); - -// let mut pythons = vec![]; -// if let Some(hklm_pythons) = get_registry_pythons_from_key(dispatcher, &hklm, company) { -// pythons.extend(hklm_pythons); -// } -// if let Some(hkcu_pythons) = get_registry_pythons_from_key(dispatcher, &hkcu, company) { -// pythons.extend(hkcu_pythons); -// } - -// Some(pythons) -// } - -// // PythonCore -// // ContinuumAnalytics +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#[cfg(windows)] +use crate::locator::{Locator, LocatorResult}; +#[cfg(windows)] +use crate::messaging::{PythonEnvironment, PythonEnvironmentCategory}; +#[cfg(windows)] +use crate::utils::PythonEnv; +#[cfg(windows)] +use winreg::RegKey; + +#[cfg(windows)] +fn get_registry_pythons_from_key(hk: &RegKey, company: &str) -> Option> { + let python_key = hk.open_subkey("Software\\Python").ok()?; + let company_key = python_key.open_subkey(company).ok()?; + + let mut pythons = vec![]; + for key in company_key.enum_keys().filter_map(Result::ok) { + let version_key = company_key.open_subkey(key).ok()?; + let install_path_key = version_key.open_subkey("InstallPath").ok()?; + let executable: String = install_path_key.get_value("ExecutablePath").ok()?; + let version = version_key.get_value("Version").ok()?; + + let env = PythonEnvironment::new( + None, + Some(PathBuf::from(executable.clone())), + PythonEnvironmentCategory::WindowsRegistry, + Some(version), + None, + None, + None, + [executable.clone()], + ); + + pythons.push(env); + } + + Some(pythons) +} + +#[cfg(windows)] +pub fn get_registry_pythons(company: &str) -> Option> { + let hklm = winreg::RegKey::predef(winreg::enums::HKEY_LOCAL_MACHINE); + let hkcu = winreg::RegKey::predef(winreg::enums::HKEY_CURRENT_USER); + + let mut pythons = vec![]; + if let Some(hklm_pythons) = get_registry_pythons_from_key(dispatcher, &hklm, company) { + pythons.extend(hklm_pythons); + } + if let Some(hkcu_pythons) = get_registry_pythons_from_key(dispatcher, &hkcu, company) { + pythons.extend(hkcu_pythons); + } + + Some(pythons) +} + +#[cfg(windows)] +pub struct WindowsRegistry {} + +#[cfg(windows)] +impl WindowsRegistry { + #[allow(dead_code)] + pub fn new() -> WindowsRegistry { + WindowsRegistry {} + } +} + +#[cfg(windows)] +impl Locator for WindowsRegistry { + fn resolve(&self, env: &PythonEnv) -> Option { + None + } + + fn find(&self) -> Option { + let environments = get_registry_pythons("PythonCore")?; + if environments.is_empty() { + None + } else { + Some(LocatorResult { + managers: vec![], + environments, + }) + } + } +} + +// PythonCore +// ContinuumAnalytics diff --git a/native_locator/src/windows_python.rs b/native_locator/src/windows_store.rs similarity index 82% rename from native_locator/src/windows_python.rs rename to native_locator/src/windows_store.rs index 071455509be3..3c31673a1193 100644 --- a/native_locator/src/windows_python.rs +++ b/native_locator/src/windows_store.rs @@ -9,10 +9,12 @@ use crate::utils::PythonEnv; use std::path::Path; use std::path::PathBuf; -fn is_windows_python_executable(path: &PathBuf) -> bool { +pub fn is_windows_python_executable(path: &PathBuf) -> bool { let name = path.file_name().unwrap().to_string_lossy().to_lowercase(); + // TODO: Is it safe to assume the number 3? name.starts_with("python3.") && name.ends_with(".exe") } + fn list_windows_store_python_executables( environment: &dyn known::Environment, ) -> Option> { @@ -38,22 +40,18 @@ fn list_windows_store_python_executables( Some(python_envs) } -fn list_registry_pythons() -> Option> { - None -} - -pub struct WindowsPython<'a> { +pub struct WindowsStore<'a> { pub environment: &'a dyn Environment, } -impl WindowsPython<'_> { +impl WindowsStore<'_> { #[allow(dead_code)] - pub fn with<'a>(environment: &'a impl Environment) -> WindowsPython { - WindowsPython { environment } + pub fn with<'a>(environment: &'a impl Environment) -> WindowsStore { + WindowsStore { environment } } } -impl Locator for WindowsPython<'_> { +impl Locator for WindowsStore<'_> { fn resolve(&self, env: &PythonEnv) -> Option { if is_windows_python_executable(&env.executable) { return Some(PythonEnvironment { @@ -80,13 +78,6 @@ impl Locator for WindowsPython<'_> { } }); } - if let Some(envs) = list_registry_pythons() { - envs.iter().for_each(|env| { - if let Some(env) = self.resolve(&&PythonEnv::from(env.clone())) { - environments.push(env); - } - }); - } if environments.is_empty() { None From 856a4743568c1f2a7ce01e1ce7a21d1bc6af5d51 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Mon, 13 May 2024 11:34:36 +1000 Subject: [PATCH 2/5] Fix compilation errors --- native_locator/src/windows_registry.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/native_locator/src/windows_registry.rs b/native_locator/src/windows_registry.rs index e139529b1341..d50936bc52bc 100644 --- a/native_locator/src/windows_registry.rs +++ b/native_locator/src/windows_registry.rs @@ -9,6 +9,8 @@ use crate::messaging::{PythonEnvironment, PythonEnvironmentCategory}; use crate::utils::PythonEnv; #[cfg(windows)] use winreg::RegKey; +#[cfg(windows)] +use std::path::PathBuf; #[cfg(windows)] fn get_registry_pythons_from_key(hk: &RegKey, company: &str) -> Option> { @@ -31,6 +33,7 @@ fn get_registry_pythons_from_key(hk: &RegKey, company: &str) -> Option Option> { let hkcu = winreg::RegKey::predef(winreg::enums::HKEY_CURRENT_USER); let mut pythons = vec![]; - if let Some(hklm_pythons) = get_registry_pythons_from_key(dispatcher, &hklm, company) { + if let Some(hklm_pythons) = get_registry_pythons_from_key(&hklm, company) { pythons.extend(hklm_pythons); } - if let Some(hkcu_pythons) = get_registry_pythons_from_key(dispatcher, &hkcu, company) { + if let Some(hkcu_pythons) = get_registry_pythons_from_key(&hkcu, company) { pythons.extend(hkcu_pythons); } From b1a710a68ff3de51714841ce59b4ffb6d6e0236c Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Mon, 13 May 2024 11:43:54 +1000 Subject: [PATCH 3/5] 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 d50936bc52bc..4e04d6ac164a 100644 --- a/native_locator/src/windows_registry.rs +++ b/native_locator/src/windows_registry.rs @@ -33,7 +33,6 @@ fn get_registry_pythons_from_key(hk: &RegKey, company: &str) -> Option Date: Mon, 13 May 2024 11:48:59 +1000 Subject: [PATCH 4/5] Oops --- native_locator/src/windows_registry.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native_locator/src/windows_registry.rs b/native_locator/src/windows_registry.rs index 4e04d6ac164a..e956425783c5 100644 --- a/native_locator/src/windows_registry.rs +++ b/native_locator/src/windows_registry.rs @@ -32,7 +32,7 @@ fn get_registry_pythons_from_key(hk: &RegKey, company: &str) -> Option Date: Mon, 13 May 2024 12:27:15 +1000 Subject: [PATCH 5/5] Fix args --- native_locator/src/windows_registry.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native_locator/src/windows_registry.rs b/native_locator/src/windows_registry.rs index e956425783c5..a26362a6f9e7 100644 --- a/native_locator/src/windows_registry.rs +++ b/native_locator/src/windows_registry.rs @@ -32,7 +32,7 @@ fn get_registry_pythons_from_key(hk: &RegKey, company: &str) -> Option