diff --git a/native_locator/src/common_python.rs b/native_locator/src/common_python.rs
index 039965bae502..76ce116ea995 100644
--- a/native_locator/src/common_python.rs
+++ b/native_locator/src/common_python.rs
@@ -38,6 +38,7 @@ impl Locator for PythonOnPath<'_> {
return None;
}
Some(PythonEnvironment {
+ display_name: None,
name: None,
python_executable_path: Some(env.executable.clone()),
version: env.version.clone(),
diff --git a/native_locator/src/conda.rs b/native_locator/src/conda.rs
index 65e0fd073292..8f6ae6f8b507 100644
--- a/native_locator/src/conda.rs
+++ b/native_locator/src/conda.rs
@@ -549,6 +549,7 @@ fn get_root_python_environment(path: &PathBuf, manager: &EnvManager) -> Option
{
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,
diff --git a/native_locator/src/homebrew.rs b/native_locator/src/homebrew.rs
index 36a8cfb8f46d..34a02fe9845f 100644
--- a/native_locator/src/homebrew.rs
+++ b/native_locator/src/homebrew.rs
@@ -61,6 +61,7 @@ impl Locator for Homebrew<'_> {
}
reported.insert(exe.to_string_lossy().to_string());
let env = crate::messaging::PythonEnvironment::new(
+ None,
None,
Some(exe.clone()),
crate::messaging::PythonEnvironmentCategory::Homebrew,
diff --git a/native_locator/src/main.rs b/native_locator/src/main.rs
index 3620fe284bda..ee976bf756d2 100644
--- a/native_locator/src/main.rs
+++ b/native_locator/src/main.rs
@@ -41,24 +41,24 @@ fn main() {
let pipenv_locator = pipenv::PipEnv::new();
let mut path_locator = common_python::PythonOnPath::with(&environment);
let mut conda_locator = conda::Conda::with(&environment);
- let mut pyenv_locator = pyenv::PyEnv::with(&environment, &mut conda_locator);
#[cfg(unix)]
let mut homebrew_locator = homebrew::Homebrew::with(&environment);
#[cfg(windows)]
let mut windows_store = windows_store::WindowsStore::with(&environment);
#[cfg(windows)]
- let mut windows_registry = windows_registry::WindowsRegistry::new();
+ let mut windows_registry = windows_registry::WindowsRegistry::with(&mut conda_locator);
// Step 1: These environments take precedence over all others.
// As they are very specific and guaranteed to be specific type.
+ #[cfg(windows)]
+ find_environments(&mut windows_registry, &mut dispatcher);
+ let mut pyenv_locator = pyenv::PyEnv::with(&environment, &mut conda_locator);
find_environments(&mut pyenv_locator, &mut dispatcher);
#[cfg(unix)]
find_environments(&mut homebrew_locator, &mut dispatcher);
find_environments(&mut conda_locator, &mut dispatcher);
#[cfg(windows)]
- find_environments(&mut windows_registry, &mut dispatcher);
- #[cfg(windows)]
find_environments(&mut windows_store, &mut dispatcher);
// Step 2: Search in some global locations.
diff --git a/native_locator/src/messaging.rs b/native_locator/src/messaging.rs
index dddcb6e1b595..b79c5fa172ca 100644
--- a/native_locator/src/messaging.rs
+++ b/native_locator/src/messaging.rs
@@ -94,6 +94,7 @@ pub enum PythonEnvironmentCategory {
#[serde(rename_all = "camelCase")]
#[derive(Debug)]
pub struct PythonEnvironment {
+ pub display_name: Option,
pub name: Option,
pub python_executable_path: Option,
pub category: PythonEnvironmentCategory,
@@ -110,6 +111,7 @@ pub struct PythonEnvironment {
impl PythonEnvironment {
pub fn new(
+ display_name: Option,
name: Option,
python_executable_path: Option,
category: PythonEnvironmentCategory,
@@ -120,6 +122,7 @@ impl PythonEnvironment {
python_run_command: Option>,
) -> Self {
Self {
+ display_name,
name,
python_executable_path,
category,
@@ -140,6 +143,7 @@ impl PythonEnvironment {
project_path: PathBuf,
) -> Self {
Self {
+ display_name: None,
name: None,
python_executable_path: python_executable_path.clone(),
category: PythonEnvironmentCategory::Pipenv,
diff --git a/native_locator/src/pyenv.rs b/native_locator/src/pyenv.rs
index 5832718b4c44..a94d63bc4751 100644
--- a/native_locator/src/pyenv.rs
+++ b/native_locator/src/pyenv.rs
@@ -105,6 +105,7 @@ fn get_pure_python_environment(
) -> Option {
let version = get_pyenv_version(&path.file_name().unwrap().to_string_lossy().to_string())?;
Some(messaging::PythonEnvironment::new(
+ None,
None,
Some(executable.clone()),
messaging::PythonEnvironmentCategory::Pyenv,
@@ -138,6 +139,7 @@ fn get_virtual_env_environment(
let pyenv_cfg = find_and_parse_pyvenv_cfg(executable)?;
let folder_name = path.file_name().unwrap().to_string_lossy().to_string();
Some(messaging::PythonEnvironment::new(
+ None,
Some(folder_name),
Some(executable.clone()),
messaging::PythonEnvironmentCategory::PyenvVirtualEnv,
diff --git a/native_locator/src/venv.rs b/native_locator/src/venv.rs
index 05ddaf7f7522..9e0161a6df7d 100644
--- a/native_locator/src/venv.rs
+++ b/native_locator/src/venv.rs
@@ -26,6 +26,7 @@ impl Locator for Venv {
fn resolve(&self, env: &PythonEnv) -> Option {
if is_venv(&env) {
return Some(PythonEnvironment {
+ display_name: None,
name: Some(
env.path
.clone()
diff --git a/native_locator/src/virtualenv.rs b/native_locator/src/virtualenv.rs
index 2268a8253b06..04c10e0e0d25 100644
--- a/native_locator/src/virtualenv.rs
+++ b/native_locator/src/virtualenv.rs
@@ -57,6 +57,7 @@ impl Locator for VirtualEnv {
fn resolve(&self, env: &PythonEnv) -> Option {
if is_virtualenv(env) {
return Some(PythonEnvironment {
+ display_name: None,
name: Some(
env.path
.clone()
diff --git a/native_locator/src/virtualenvwrapper.rs b/native_locator/src/virtualenvwrapper.rs
index 9e5d28e9f445..856f6a78d537 100644
--- a/native_locator/src/virtualenvwrapper.rs
+++ b/native_locator/src/virtualenvwrapper.rs
@@ -80,6 +80,7 @@ impl Locator for VirtualEnvWrapper<'_> {
fn resolve(&self, env: &PythonEnv) -> Option {
if is_virtualenvwrapper(env, self.environment) {
return Some(PythonEnvironment {
+ display_name: None,
name: Some(
env.path
.clone()
diff --git a/native_locator/src/windows_registry.rs b/native_locator/src/windows_registry.rs
index ef886b28dbdd..279ef46d173e 100644
--- a/native_locator/src/windows_registry.rs
+++ b/native_locator/src/windows_registry.rs
@@ -1,16 +1,20 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
+#[cfg(windows)]
+use crate::conda::CondaLocator;
#[cfg(windows)]
use crate::locator::{Locator, LocatorResult};
#[cfg(windows)]
+use crate::messaging::EnvManager;
+#[cfg(windows)]
use crate::messaging::{PythonEnvironment, PythonEnvironmentCategory};
#[cfg(windows)]
use crate::utils::PythonEnv;
#[cfg(windows)]
-use winreg::RegKey;
-#[cfg(windows)]
use std::path::PathBuf;
+#[cfg(windows)]
+use winreg::RegKey;
#[cfg(windows)]
fn get_registry_pythons_from_key(hk: &RegKey, company: &str) -> Option> {
@@ -19,23 +23,47 @@ fn get_registry_pythons_from_key(hk: &RegKey, company: &str) -> Option 0 {
+ Some(version)
+ } else {
+ None
+ },
+ env_path,
+ None,
+ None,
+ Some(vec![executable.to_string_lossy().to_string()]),
+ );
+ pythons.push(env);
+ }
+ }
}
Some(pythons)
@@ -53,39 +81,77 @@ pub fn get_registry_pythons(company: &str) -> Option> {
if let Some(hkcu_pythons) = get_registry_pythons_from_key(&hkcu, company) {
pythons.extend(hkcu_pythons);
}
-
Some(pythons)
}
#[cfg(windows)]
-pub struct WindowsRegistry {}
+pub fn get_registry_pythons_anaconda(conda_locator: &mut dyn CondaLocator) -> LocatorResult {
+ 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(&hklm, "ContinuumAnalytics") {
+ pythons.extend(hklm_pythons);
+ }
+ if let Some(hkcu_pythons) = get_registry_pythons_from_key(&hkcu, "ContinuumAnalytics") {
+ pythons.extend(hkcu_pythons);
+ }
+
+ let mut environments: Vec = vec![];
+ let mut managers: Vec = vec![];
+
+ for env in pythons.iter() {
+ if let Some(env_path) = env.clone().env_path {
+ if let Some(mut result) = conda_locator.find_in(&env_path) {
+ environments.append(&mut result.environments);
+ managers.append(&mut result.managers);
+ }
+ }
+ }
+
+ LocatorResult {
+ managers,
+ environments,
+ }
+}
#[cfg(windows)]
-impl WindowsRegistry {
+pub struct WindowsRegistry<'a> {
+ pub conda_locator: &'a mut dyn CondaLocator,
+}
+
+#[cfg(windows)]
+impl WindowsRegistry<'_> {
#[allow(dead_code)]
- pub fn new() -> WindowsRegistry {
- WindowsRegistry {}
+ pub fn with<'a>(conda_locator: &'a mut impl CondaLocator) -> WindowsRegistry<'a> {
+ WindowsRegistry { conda_locator }
}
}
#[cfg(windows)]
-impl Locator for WindowsRegistry {
- fn resolve(&self, env: &PythonEnv) -> Option {
+impl Locator for WindowsRegistry<'_> {
+ fn resolve(&self, _env: &PythonEnv) -> Option {
None
}
fn find(&mut self) -> Option {
- let environments = get_registry_pythons("PythonCore")?;
- if environments.is_empty() {
+ let mut environments: Vec = vec![];
+ let mut managers: Vec = vec![];
+
+ let mut result = get_registry_pythons("PythonCore").unwrap_or_default();
+ environments.append(&mut result);
+
+ let mut result = get_registry_pythons_anaconda(self.conda_locator) ;
+ environments.append(&mut result.environments);
+ managers.append(&mut result.managers);
+
+ if environments.is_empty() && managers.is_empty() {
None
} else {
Some(LocatorResult {
- managers: vec![],
+ managers,
environments,
})
}
}
}
-
-// PythonCore
-// ContinuumAnalytics
diff --git a/native_locator/src/windows_store.rs b/native_locator/src/windows_store.rs
index 2f2a0c2f81ce..5a0fd7b6ebd0 100644
--- a/native_locator/src/windows_store.rs
+++ b/native_locator/src/windows_store.rs
@@ -55,6 +55,7 @@ impl Locator for WindowsStore<'_> {
fn resolve(&self, env: &PythonEnv) -> Option {
if is_windows_python_executable(&env.executable) {
return Some(PythonEnvironment {
+ display_name: None,
name: None,
python_executable_path: Some(env.executable.clone()),
version: None,
diff --git a/native_locator/tests/common_python_test.rs b/native_locator/tests/common_python_test.rs
index a21f3349f38c..06ed5ff7811d 100644
--- a/native_locator/tests/common_python_test.rs
+++ b/native_locator/tests/common_python_test.rs
@@ -33,6 +33,7 @@ fn find_python_in_path_this() {
assert_eq!(environments.len(), 1);
let env = PythonEnvironment {
+ display_name: None,
env_manager: None,
project_path: None,
name: None,
diff --git a/native_locator/tests/conda_test.rs b/native_locator/tests/conda_test.rs
index 77fed4a2393d..fb3d59e59b5d 100644
--- a/native_locator/tests/conda_test.rs
+++ b/native_locator/tests/conda_test.rs
@@ -119,6 +119,7 @@ fn finds_two_conda_envs_from_txt() {
tool: EnvManagerType::Conda,
};
let expected_conda_1 = PythonEnvironment {
+ display_name: None,
name: Some("one".to_string()),
project_path: None,
python_executable_path: Some(conda_1_exe.clone()),
@@ -133,9 +134,10 @@ fn finds_two_conda_envs_from_txt() {
"-n".to_string(),
"one".to_string(),
"python".to_string(),
- ]),
- };
- let expected_conda_2 = PythonEnvironment {
+ ]),
+ };
+ let expected_conda_2 = PythonEnvironment {
+ display_name: None,
name: Some("two".to_string()),
project_path: None,
python_executable_path: Some(conda_2_exe.clone()),
diff --git a/native_locator/tests/pyenv_test.rs b/native_locator/tests/pyenv_test.rs
index 45df29031fb7..7ad6904867fa 100644
--- a/native_locator/tests/pyenv_test.rs
+++ b/native_locator/tests/pyenv_test.rs
@@ -105,6 +105,7 @@ fn find_pyenv_envs() {
);
let expected_3_9_9 = json!(PythonEnvironment {
+ display_name: None,
project_path: None,
name: None,
python_executable_path: Some(join_test_paths(&[
@@ -123,20 +124,21 @@ 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(&[
+ ])),
+ sys_prefix_path: Some(join_test_paths(&[
home.to_str().unwrap(),
".pyenv/versions/3.9.9"
])),
env_manager: Some(expected_manager.clone())
});
let expected_virtual_env = PythonEnvironment {
+ display_name: None,
project_path: None,
name: Some("my-virtual-env".to_string()),
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",
@@ -153,16 +155,17 @@ fn find_pyenv_envs() {
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 +182,11 @@ fn find_pyenv_envs() {
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 {
+ display_name: None,
project_path: None,
name: None,
python_executable_path: Some(join_test_paths(&[
@@ -205,10 +209,11 @@ fn find_pyenv_envs() {
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 {
+ display_name: None,
project_path: None,
name: None,
python_executable_path: Some(join_test_paths(&[