Skip to content

Commit c4e4ee6

Browse files
committed
Update python env properties sent back to TS layer (#23378)
1 parent 6a615fc commit c4e4ee6

9 files changed

+74
-64
lines changed

native_locator/src/common_python.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,14 @@ fn report_path_python(dispatcher: &mut impl messaging::MessageDispatcher, path:
2525
let version = utils::get_version(path);
2626
let env_path = get_env_path(path);
2727
dispatcher.report_environment(messaging::PythonEnvironment::new(
28-
"Python".to_string(),
29-
vec![path.to_string()],
28+
None,
29+
Some(path.to_string()),
3030
messaging::PythonEnvironmentCategory::System,
3131
version,
32-
None,
3332
env_path.clone(),
3433
env_path,
34+
None,
35+
Some(vec![path.to_string()]),
3536
));
3637
}
3738

native_locator/src/conda.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,7 @@ pub fn find_and_report(
375375
match conda_binary {
376376
Some(conda_binary) => {
377377
let params = messaging::EnvManager::new(
378-
vec![conda_binary.to_string_lossy().to_string()],
378+
conda_binary.to_string_lossy().to_string(),
379379
get_conda_version(&conda_binary),
380380
);
381381
dispatcher.report_environment_manager(params);
@@ -385,13 +385,16 @@ pub fn find_and_report(
385385
let executable = find_python_binary_path(Path::new(&env.path));
386386
let env_path = env.path.to_string_lossy().to_string();
387387
let params = messaging::PythonEnvironment::new(
388-
env.name.to_string(),
388+
Some(env.name.to_string()),
389389
match executable {
390-
Some(executable) => vec![executable.to_string_lossy().to_string()],
391-
None => vec![],
390+
Some(executable) => Some(executable.to_string_lossy().to_string()),
391+
None => None,
392392
},
393393
messaging::PythonEnvironmentCategory::Conda,
394394
get_conda_python_version(&env.path),
395+
Some(env_path.clone()),
396+
Some(env_path),
397+
None,
395398
if env.named {
396399
Some(vec![
397400
conda_binary.to_string_lossy().to_string(),
@@ -409,8 +412,6 @@ pub fn find_and_report(
409412
"python".to_string(),
410413
])
411414
},
412-
Some(env_path.clone()),
413-
Some(env_path),
414415
);
415416
dispatcher.report_environment(params);
416417
}

native_locator/src/homebrew.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,16 @@ pub fn find_and_report(
4545
continue;
4646
}
4747
reported.insert(exe.to_string_lossy().to_string());
48-
48+
let executable = exe.to_string_lossy().to_string();
4949
let env = crate::messaging::PythonEnvironment::new(
50-
"Python".to_string(),
51-
vec![exe.to_string_lossy().to_string()],
50+
None,
51+
Some(executable.clone()),
5252
crate::messaging::PythonEnvironmentCategory::Homebrew,
5353
version,
5454
None,
5555
None,
5656
None,
57+
Some(vec![executable]),
5758
);
5859
dispatcher.report_environment(env);
5960
}

native_locator/src/messaging.rs

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,28 @@ pub trait MessageDispatcher {
1717
#[derive(Serialize, Deserialize)]
1818
#[serde(rename_all = "camelCase")]
1919
pub struct EnvManager {
20-
pub executable_path: Vec<String>,
20+
pub executable_path: String,
2121
pub version: Option<String>,
2222
}
2323

2424
impl EnvManager {
25-
pub fn new(executable_path: Vec<String>, version: Option<String>) -> Self {
25+
pub fn new(executable_path: String, version: Option<String>) -> Self {
2626
Self {
2727
executable_path,
2828
version,
2929
}
3030
}
3131
}
3232

33+
impl Clone for EnvManager {
34+
fn clone(&self) -> Self {
35+
Self {
36+
executable_path: self.executable_path.clone(),
37+
version: self.version.clone(),
38+
}
39+
}
40+
}
41+
3342
#[derive(Serialize, Deserialize)]
3443
#[serde(rename_all = "camelCase")]
3544
pub struct EnvManagerMessage {
@@ -62,33 +71,36 @@ pub enum PythonEnvironmentCategory {
6271
#[derive(Serialize, Deserialize)]
6372
#[serde(rename_all = "camelCase")]
6473
pub struct PythonEnvironment {
65-
pub name: String,
66-
pub python_executable_path: Vec<String>,
74+
pub name: Option<String>,
75+
pub python_executable_path: Option<String>,
6776
pub category: PythonEnvironmentCategory,
6877
pub version: Option<String>,
69-
pub activated_run: Option<Vec<String>>,
7078
pub env_path: Option<String>,
7179
pub sys_prefix_path: Option<String>,
80+
pub env_manager: Option<EnvManager>,
81+
pub python_run_command: Option<Vec<String>>,
7282
}
7383

7484
impl PythonEnvironment {
7585
pub fn new(
76-
name: String,
77-
python_executable_path: Vec<String>,
86+
name: Option<String>,
87+
python_executable_path: Option<String>,
7888
category: PythonEnvironmentCategory,
7989
version: Option<String>,
80-
activated_run: Option<Vec<String>>,
8190
env_path: Option<String>,
8291
sys_prefix_path: Option<String>,
92+
env_manager: Option<EnvManager>,
93+
python_run_command: Option<Vec<String>>,
8394
) -> Self {
8495
Self {
8596
name,
8697
python_executable_path,
8798
category,
8899
version,
89-
activated_run,
90100
env_path,
91101
sys_prefix_path,
102+
env_manager,
103+
python_run_command,
92104
}
93105
}
94106
}

native_locator/src/pyenv.rs

Lines changed: 23 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use std::path::PathBuf;
77

88
use crate::known;
99
use crate::messaging;
10+
use crate::messaging::EnvManager;
1011
use crate::utils::find_python_binary_path;
1112

1213
#[cfg(windows)]
@@ -102,25 +103,21 @@ fn get_pyenv_version(folder_name: String) -> Option<String> {
102103
fn report_if_pure_python_environment(
103104
executable: PathBuf,
104105
path: &PathBuf,
105-
pyenv_binary_for_activation: String,
106+
manager: Option<EnvManager>,
106107
dispatcher: &mut impl messaging::MessageDispatcher,
107108
) -> Option<()> {
108109
let version = get_pyenv_version(path.file_name().unwrap().to_string_lossy().to_string())?;
109-
110+
let executable = executable.into_os_string().into_string().unwrap();
110111
let env_path = path.to_string_lossy().to_string();
111-
let activated_run = Some(vec![
112-
pyenv_binary_for_activation,
113-
"shell".to_string(),
114-
version.clone(),
115-
]);
116112
dispatcher.report_environment(messaging::PythonEnvironment::new(
117-
version.clone(),
118-
vec![executable.into_os_string().into_string().unwrap()],
113+
None,
114+
Some(executable.clone()),
119115
messaging::PythonEnvironmentCategory::Pyenv,
120116
Some(version),
121-
activated_run,
122117
Some(env_path.clone()),
123118
Some(env_path),
119+
manager,
120+
Some(vec![executable]),
124121
));
125122

126123
Some(())
@@ -154,26 +151,22 @@ fn parse_pyenv_cfg(path: &PathBuf) -> Option<PyEnvCfg> {
154151
fn report_if_virtual_env_environment(
155152
executable: PathBuf,
156153
path: &PathBuf,
157-
pyenv_binary_for_activation: String,
154+
manager: Option<EnvManager>,
158155
dispatcher: &mut impl messaging::MessageDispatcher,
159156
) -> Option<()> {
160157
let pyenv_cfg = parse_pyenv_cfg(path)?;
161158
let folder_name = path.file_name().unwrap().to_string_lossy().to_string();
162-
159+
let executable = executable.into_os_string().into_string().unwrap();
163160
let env_path = path.to_string_lossy().to_string();
164-
let activated_run = Some(vec![
165-
pyenv_binary_for_activation,
166-
"activate".to_string(),
167-
folder_name.clone(),
168-
]);
169161
dispatcher.report_environment(messaging::PythonEnvironment::new(
170-
folder_name,
171-
vec![executable.into_os_string().into_string().unwrap()],
162+
Some(folder_name),
163+
Some(executable.clone()),
172164
messaging::PythonEnvironmentCategory::PyenvVirtualEnv,
173165
Some(pyenv_cfg.version),
174-
activated_run,
175166
Some(env_path.clone()),
176167
Some(env_path),
168+
manager,
169+
Some(vec![executable]),
177170
));
178171

179172
Some(())
@@ -185,20 +178,21 @@ pub fn find_and_report(
185178
) -> Option<()> {
186179
let pyenv_dir = get_pyenv_dir(environment)?;
187180

188-
if let Some(pyenv_binary) = get_pyenv_binary(environment) {
189-
dispatcher.report_environment_manager(messaging::EnvManager::new(vec![pyenv_binary], None));
190-
}
181+
let manager = match get_pyenv_binary(environment) {
182+
Some(pyenv_binary) => {
183+
let manager = messaging::EnvManager::new(pyenv_binary, None);
184+
dispatcher.report_environment_manager(manager.clone());
185+
Some(manager)
186+
}
187+
None => None,
188+
};
191189

192190
let versions_dir = PathBuf::from(&pyenv_dir)
193191
.join("versions")
194192
.into_os_string()
195193
.into_string()
196194
.ok()?;
197195

198-
let pyenv_binary_for_activation = match get_pyenv_binary(environment) {
199-
Some(binary) => binary,
200-
None => "pyenv".to_string(),
201-
};
202196
for entry in fs::read_dir(&versions_dir).ok()? {
203197
if let Ok(path) = entry {
204198
let path = path.path();
@@ -209,7 +203,7 @@ pub fn find_and_report(
209203
if report_if_pure_python_environment(
210204
executable.clone(),
211205
&path,
212-
pyenv_binary_for_activation.clone(),
206+
manager.clone(),
213207
dispatcher,
214208
)
215209
.is_some()
@@ -220,7 +214,7 @@ pub fn find_and_report(
220214
report_if_virtual_env_environment(
221215
executable.clone(),
222216
&path,
223-
pyenv_binary_for_activation.clone(),
217+
manager.clone(),
224218
dispatcher,
225219
);
226220
}

native_locator/src/windows_python.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@ use std::path::Path;
99
fn report_path_python(path: &str, dispatcher: &mut impl messaging::MessageDispatcher) {
1010
let version = utils::get_version(path);
1111
dispatcher.report_environment(messaging::PythonEnvironment::new(
12-
"Python".to_string(),
13-
vec![path.to_string()],
12+
None,
13+
Some(path.to_string()),
1414
messaging::PythonEnvironmentCategory::WindowsStore,
1515
version,
1616
None,
1717
None,
1818
None,
19+
None,
1920
));
2021
}
2122

native_locator/tests/common_python_test.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,6 @@ fn find_python_in_path_this() {
2727
common_python::find_and_report(&mut dispatcher, &known);
2828

2929
assert_eq!(dispatcher.messages.len(), 1);
30-
let expected_json = json!({"name":"Python","pythonExecutablePath":[unix_python_exe.clone()],"category":"system","version":null,"activatedRun":null,"envPath":unix_python.clone(),"sysPrefixPath":unix_python.clone()});
30+
let expected_json = json!({"envManager":null,"name":null,"pythonExecutablePath":unix_python_exe.clone(),"category":"system","version":null,"pythonRunCommand":[unix_python_exe.clone()],"envPath":unix_python.clone(),"sysPrefixPath":unix_python.clone()});
3131
assert_messages(&[expected_json], &dispatcher);
3232
}

native_locator/tests/conda_test.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ fn find_conda_exe_and_empty_envs() {
4444
conda::find_and_report(&mut dispatcher, &known);
4545

4646
let conda_exe = join_test_paths(&[conda_dir.clone().as_str(), "conda"]);
47-
let expected_json = json!({"executablePath":[conda_exe.clone()],"version":null});
47+
let expected_json = json!({"executablePath":conda_exe.clone(),"version":null});
4848
assert_messages(&[expected_json], &dispatcher)
4949
}
5050
#[test]
@@ -80,9 +80,9 @@ fn finds_two_conda_envs_from_txt() {
8080
let conda_1_exe = join_test_paths(&[conda_1.clone().as_str(), "python"]);
8181
let conda_2_exe = join_test_paths(&[conda_2.clone().as_str(), "python"]);
8282

83-
let expected_conda_env = json!({"executablePath":[conda_exe.clone()],"version":null});
84-
let expected_conda_1 = json!({"name":"one","pythonExecutablePath":[conda_1_exe.clone()],"category":"conda","version":"10.0.1","activatedRun":[conda_exe.clone(),"run","-n","one","python"],"envPath":conda_1.clone(), "sysPrefixPath":conda_1.clone()});
85-
let expected_conda_2 = json!({"name":"two","pythonExecutablePath":[conda_2_exe.clone()],"category":"conda","version":null,"activatedRun":[conda_exe.clone(),"run","-n","two","python"],"envPath":conda_2.clone(), "sysPrefixPath":conda_2.clone()});
83+
let expected_conda_env = json!({ "executablePath": conda_exe.clone(), "version": null});
84+
let expected_conda_1 = json!({ "name": "one", "pythonExecutablePath": conda_1_exe.clone(), "category": "conda", "version": "10.0.1", "envPath": conda_1.clone(), "sysPrefixPath": conda_1.clone(), "envManager": null, "pythonRunCommand": [conda_exe.clone(), "run", "-n", "one", "python"]});
85+
let expected_conda_2 = json!({ "name": "two", "pythonExecutablePath": conda_2_exe.clone(), "category": "conda", "version": null, "envPath": conda_2.clone(), "sysPrefixPath": conda_2.clone(), "envManager": null,"pythonRunCommand": [conda_exe.clone(),"run","-n","two","python"]});
8686
assert_messages(
8787
&[expected_conda_env, expected_conda_1, expected_conda_2],
8888
&dispatcher,

native_locator/tests/pyenv_test.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ fn does_not_find_any_pyenv_envs_even_with_pyenv_installed() {
4646
pyenv::find_and_report(&mut dispatcher, &known);
4747

4848
assert_eq!(dispatcher.messages.len(), 1);
49-
let expected_json = json!({"executablePath":[pyenv_exe],"version":null});
49+
let expected_json = json!({"executablePath":pyenv_exe,"version":null});
5050
assert_messages(&[expected_json], &dispatcher)
5151
}
5252

@@ -74,12 +74,12 @@ fn find_pyenv_envs() {
7474
pyenv::find_and_report(&mut dispatcher, &known);
7575

7676
assert_eq!(dispatcher.messages.len(), 6);
77-
let expected_manager = json!({ "executablePath": [pyenv_exe.clone()], "version": null });
78-
let expected_3_9_9 = json!({"name": "3.9.9","pythonExecutablePath": [join_test_paths(&[home.as_str(), ".pyenv/versions/3.9.9/bin/python"])],"category": "pyenv","version": "3.9.9","activatedRun": [pyenv_exe.clone(), "shell", "3.9.9"],"envPath": join_test_paths(&[home.as_str(), ".pyenv/versions/3.9.9"]),"sysPrefixPath": join_test_paths(&[home.as_str(), ".pyenv/versions/3.9.9"])});
79-
let expected_virtual_env = json!( {"name": "my-virtual-env", "version": "3.10.13", "activatedRun": [pyenv_exe.clone(), "activate", "my-virtual-env"], "category": "pyenvVirtualEnv", "envPath": join_test_paths(&[home.as_str(),".pyenv/versions/my-virtual-env"]), "pythonExecutablePath": [join_test_paths(&[home.as_str(),".pyenv/versions/my-virtual-env/bin/python"])], "sysPrefixPath": join_test_paths(&[home.as_str(),".pyenv/versions/my-virtual-env"])});
80-
let expected_3_12_1 = json!({"name": "3.12.1","pythonExecutablePath": [join_test_paths(&[home.as_str(), ".pyenv/versions/3.12.1/bin/python"])],"category": "pyenv","version": "3.12.1","activatedRun": [pyenv_exe.clone(), "shell", "3.12.1"],"envPath": join_test_paths(&[home.as_str(), ".pyenv/versions/3.12.1"]),"sysPrefixPath": join_test_paths(&[home.as_str(), ".pyenv/versions/3.12.1"])});
81-
let expected_3_13_dev = json!({"name": "3.13-dev","pythonExecutablePath": [join_test_paths(&[home.as_str(), ".pyenv/versions/3.13-dev/bin/python"])],"category": "pyenv","version": "3.13-dev","activatedRun": [pyenv_exe.clone(), "shell", "3.13-dev"],"envPath": join_test_paths(&[home.as_str(), ".pyenv/versions/3.13-dev"]),"sysPrefixPath": join_test_paths(&[home.as_str(), ".pyenv/versions/3.13-dev"])});
82-
let expected_3_12_1a3 = json!({"name": "3.12.1a3","pythonExecutablePath": [join_test_paths(&[home.as_str(), ".pyenv/versions/3.12.1a3/bin/python"])],"category": "pyenv","version": "3.12.1a3","activatedRun": [pyenv_exe.clone(), "shell", "3.12.1a3"],"envPath": join_test_paths(&[home.as_str(), ".pyenv/versions/3.12.1a3"]),"sysPrefixPath": join_test_paths(&[home.as_str(), ".pyenv/versions/3.12.1a3"])});
77+
let expected_manager = json!({ "executablePath": pyenv_exe.clone(), "version": null });
78+
let expected_3_9_9 = json!({"name": null,"pythonExecutablePath": join_test_paths(&[home.as_str(), ".pyenv/versions/3.9.9/bin/python"]), "pythonRunCommand": [join_test_paths(&[home.as_str(), ".pyenv/versions/3.9.9/bin/python"])], "category": "pyenv","version": "3.9.9","envPath": join_test_paths(&[home.as_str(), ".pyenv/versions/3.9.9"]),"sysPrefixPath": join_test_paths(&[home.as_str(), ".pyenv/versions/3.9.9"]), "envManager": expected_manager});
79+
let expected_virtual_env = json!({"name": "my-virtual-env", "version": "3.10.13", "category": "pyenvVirtualEnv", "envPath": join_test_paths(&[home.as_str(),".pyenv/versions/my-virtual-env"]), "pythonExecutablePath": join_test_paths(&[home.as_str(),".pyenv/versions/my-virtual-env/bin/python"]), "sysPrefixPath": join_test_paths(&[home.as_str(),".pyenv/versions/my-virtual-env"]), "pythonRunCommand": [join_test_paths(&[home.as_str(),".pyenv/versions/my-virtual-env/bin/python"])], "envManager": expected_manager});
80+
let expected_3_12_1 = json!({"name": null,"pythonExecutablePath": join_test_paths(&[home.as_str(), ".pyenv/versions/3.12.1/bin/python"]), "pythonRunCommand": [join_test_paths(&[home.as_str(), ".pyenv/versions/3.12.1/bin/python"])], "category": "pyenv","version": "3.12.1","envPath": join_test_paths(&[home.as_str(), ".pyenv/versions/3.12.1"]),"sysPrefixPath": join_test_paths(&[home.as_str(), ".pyenv/versions/3.12.1"]), "envManager": expected_manager});
81+
let expected_3_13_dev = json!({"name": null,"pythonExecutablePath": join_test_paths(&[home.as_str(), ".pyenv/versions/3.13-dev/bin/python"]), "pythonRunCommand": [join_test_paths(&[home.as_str(), ".pyenv/versions/3.13-dev/bin/python"])], "category": "pyenv","version": "3.13-dev","envPath": join_test_paths(&[home.as_str(), ".pyenv/versions/3.13-dev"]),"sysPrefixPath": join_test_paths(&[home.as_str(), ".pyenv/versions/3.13-dev"]), "envManager": expected_manager});
82+
let expected_3_12_1a3 = json!({"name": null,"pythonExecutablePath": join_test_paths(&[home.as_str(), ".pyenv/versions/3.12.1a3/bin/python"]), "pythonRunCommand": [join_test_paths(&[home.as_str(), ".pyenv/versions/3.12.1a3/bin/python"])], "category": "pyenv","version": "3.12.1a3","envPath": join_test_paths(&[home.as_str(), ".pyenv/versions/3.12.1a3"]),"sysPrefixPath": join_test_paths(&[home.as_str(), ".pyenv/versions/3.12.1a3"]), "envManager": expected_manager});
8383
assert_messages(
8484
&[
8585
expected_manager,

0 commit comments

Comments
 (0)