Skip to content

Commit

Permalink
Updates with logging
Browse files Browse the repository at this point in the history
  • Loading branch information
DonJayamanne committed May 25, 2024
1 parent 2b35e50 commit 1109496
Showing 1 changed file with 156 additions and 91 deletions.
247 changes: 156 additions & 91 deletions native_locator/src/windows_registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,89 +18,132 @@ use winreg::RegKey;

#[cfg(windows)]
fn get_registry_pythons_from_key_for_company(
hk: &RegKey,
key_container: &str,
company_key: &RegKey,
company: &str,
conda_locator: &mut dyn CondaLocator,
) -> Option<LocatorResult> {
use crate::messaging::Architecture;
use log::{trace, warn};

let mut environments = vec![];
use crate::messaging::Architecture;
let mut managers: Vec<EnvManager> = vec![];
let python_key = hk.open_subkey("Software\\Python").ok()?;
let company_key = python_key.open_subkey(company).ok()?;
let mut environments = vec![];
let company_display_name: Option<String> = company_key.get_value("DisplayName").ok();
for key in company_key.enum_keys().filter_map(Result::ok) {
if let Some(key) = company_key.open_subkey(key).ok() {
if let Some(install_path_key) = key.open_subkey("InstallPath").ok() {
let env_path: String = install_path_key.get_value("").ok().unwrap_or_default();
let env_path = PathBuf::from(env_path);
for installed_python in company_key.enum_keys().filter_map(Result::ok) {
match company_key.open_subkey(installed_python.clone()) {
Ok(installed_python_key) => {
match installed_python_key.open_subkey("InstallPath") {
Ok(install_path_key) => {
let env_path: String =
install_path_key.get_value("").ok().unwrap_or_default();
let env_path = PathBuf::from(env_path);
trace!(
"Found Python ({}) in {}\\Software\\Python\\{}\\{}",
env_path.to_str().unwrap_or_default(),
key_container,
company,
installed_python,
);

// Possible this is a conda install folder.
if let Some(conda_result) = conda_locator.find_in(&env_path) {
for manager in conda_result.managers {
let mut mgr = manager.clone();
mgr.company = Some(company.to_string());
mgr.company_display_name = company_display_name.clone();
managers.push(mgr)
}
for env in conda_result.environments {
let mut env = env.clone();
// Possible this is a conda install folder.
if let Some(conda_result) = conda_locator.find_in(&env_path) {
for manager in conda_result.managers {
let mut mgr = manager.clone();
mgr.company = Some(company.to_string());
mgr.company_display_name = company_display_name.clone();
managers.push(mgr)
}
for env in conda_result.environments {
let mut env = env.clone();
env.company = Some(company.to_string());
env.company_display_name = company_display_name.clone();
if let Some(mgr) = env.env_manager {
let mut mgr = mgr.clone();
mgr.company = Some(company.to_string());
mgr.company_display_name = company_display_name.clone();
env.env_manager = Some(mgr);
}
environments.push(env);
}
continue;
}

let env_path = if env_path.exists() {
Some(env_path)
} else {
None
};
let executable: String = install_path_key
.get_value("ExecutablePath")
.ok()
.unwrap_or_default();
if executable.len() == 0 {
warn!(
"Executable is empty {}\\Software\\Python\\{}\\{}\\ExecutablePath",
key_container, company, installed_python
);
continue;
}
let executable = PathBuf::from(executable);
if !executable.exists() {
warn!(
"Python executable ({}) file not found for {}\\Software\\Python\\{}\\{}",
executable.to_str().unwrap_or_default(),
key_container,
company,
installed_python
);
continue;
}
let version: String = installed_python_key
.get_value("Version")
.ok()
.unwrap_or_default();
let architecture: String = installed_python_key
.get_value("SysArchitecture")
.ok()
.unwrap_or_default();
let display_name: String = installed_python_key
.get_value("DisplayName")
.ok()
.unwrap_or_default();

let mut env = PythonEnvironment::new(
Some(display_name),
None,
Some(executable.clone()),
PythonEnvironmentCategory::WindowsRegistry,
if version.len() > 0 {
Some(version)
} else {
None
},
env_path,
None,
Some(vec![executable.to_string_lossy().to_string()]),
);
if architecture.contains("32") {
env.arch = Some(Architecture::X86);
} else if architecture.contains("64") {
env.arch = Some(Architecture::X64);
}
env.company = Some(company.to_string());
env.company_display_name = company_display_name.clone();
if let Some(mgr) = env.env_manager {
let mut mgr = mgr.clone();
mgr.company = Some(company.to_string());
mgr.company_display_name = company_display_name.clone();
env.env_manager = Some(mgr);
}
environments.push(env);
}
continue;
}

let env_path = if env_path.exists() {
Some(env_path)
} else {
None
};
let executable: String = install_path_key
.get_value("ExecutablePath")
.ok()
.unwrap_or_default();
if executable.len() == 0 {
continue;
}
let executable = PathBuf::from(executable);
if !executable.exists() {
continue;
Err(err) => {
warn!(
"Failed to open {}\\Software\\Python\\{}\\{}\\InstallPath, {:?}",
key_container, company, installed_python, err
);
}
}
let version: String = key.get_value("Version").ok().unwrap_or_default();
let architecture: String =
key.get_value("SysArchitecture").ok().unwrap_or_default();
let display_name: String = key.get_value("DisplayName").ok().unwrap_or_default();

let mut env = PythonEnvironment::new(
Some(display_name),
None,
Some(executable.clone()),
PythonEnvironmentCategory::WindowsRegistry,
if version.len() > 0 {
Some(version)
} else {
None
},
env_path,
None,
Some(vec![executable.to_string_lossy().to_string()]),
}
Err(err) => {
warn!(
"Failed to open {}\\Software\\Python\\{}\\{}, {:?}",
key_container, company, installed_python, err
);
if architecture.contains("32") {
env.arch = Some(Architecture::X86);
} else if architecture.contains("64") {
env.arch = Some(Architecture::X64);
}
env.company = Some(company.to_string());
env.company_display_name = company_display_name.clone();
environments.push(env);
}
}
}
Expand All @@ -113,32 +156,54 @@ fn get_registry_pythons_from_key_for_company(

#[cfg(windows)]
fn get_registry_pythons(conda_locator: &mut dyn CondaLocator) -> Option<LocatorResult> {
use log::warn;
use log::{trace, warn};

let mut environments = vec![];
let mut managers: Vec<EnvManager> = vec![];

for (name, key) in [
vec![
"HKLM",
winreg::RegKey::predef(winreg::enums::HKEY_LOCAL_MACHINE),
],
vec![
"HKCU",
winreg::RegKey::predef(winreg::enums::HKEY_CURRENT_USER),
],
] {
if let Some(python_key) = key.open_subkey("Software\\Python").ok() {
for company in python_key.enum_keys().filter_map(Result::ok) {
if let Some(result) =
get_registry_pythons_from_key_for_company(&key, &company, conda_locator)
{
managers.extend(result.managers);
environments.extend(result.environments);
struct RegistryKey {
pub name: &'static str,
pub key: winreg::RegKey,
}
let search_keys = [
RegistryKey {
name: "HKLM",
key: winreg::RegKey::predef(winreg::enums::HKEY_LOCAL_MACHINE),
},
RegistryKey {
name: "HKCU",
key: winreg::RegKey::predef(winreg::enums::HKEY_CURRENT_USER),
},
];
for (name, key) in search_keys.iter().map(|f| (f.name, &f.key)) {
match key.open_subkey("Software\\Python") {
Ok(python_key) => {
for company in python_key.enum_keys().filter_map(Result::ok) {
trace!("Searching {}\\Software\\Python\\{}", name, company);
match python_key.open_subkey(&company) {
Ok(company_key) => {
if let Some(result) = get_registry_pythons_from_key_for_company(
name,
&company_key,
&company,
conda_locator,
) {
managers.extend(result.managers);
environments.extend(result.environments);
}
}
Err(err) => {
warn!(
"Failed to open {}\\Software\\Python\\{}, {:?}",
name, company, err
);
}
}
}
}
} else {
warn!("Failed to open {}\\Software\\Python key", name)
Err(err) => {
warn!("Failed to open {}\\Software\\Python, {:?}", name, err)
}
}
}
Some(LocatorResult {
Expand Down Expand Up @@ -169,7 +234,7 @@ impl Locator for WindowsRegistry<'_> {
fn find(&mut self) -> Option<LocatorResult> {
if let Some(result) = get_registry_pythons(self.conda_locator) {
if !result.environments.is_empty() || !result.managers.is_empty() {
return Some(result);
// return Some(result);
}
}
None
Expand Down

0 comments on commit 1109496

Please sign in to comment.