Skip to content

Commit f33a69b

Browse files
authored
Hardcode exe returned for windows store envs (#86)
1 parent 721ebdd commit f33a69b

File tree

7 files changed

+82
-43
lines changed

7 files changed

+82
-43
lines changed

crates/pet-core/src/python_environment.rs

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
use log::error;
55
use pet_fs::path::norm_case;
6-
use pet_python_utils::executable::get_shortest_executable;
76
use serde::{Deserialize, Serialize};
87
use std::path::PathBuf;
98

@@ -317,8 +316,10 @@ impl PythonEnvironmentBuilder {
317316
Some(all.clone())
318317
};
319318
if let Some(executable) = &self.executable {
320-
self.executable =
321-
Some(get_shortest_executable(&Some(all.clone())).unwrap_or(executable.clone()));
319+
self.executable = Some(
320+
get_shortest_executable(&self.category, &Some(all.clone()))
321+
.unwrap_or(executable.clone()),
322+
);
322323
}
323324
}
324325

@@ -338,9 +339,9 @@ impl PythonEnvironmentBuilder {
338339
} else {
339340
Some(all.clone())
340341
};
341-
let executable = self
342-
.executable
343-
.map(|executable| get_shortest_executable(&Some(all.clone())).unwrap_or(executable));
342+
let executable = self.executable.map(|executable| {
343+
get_shortest_executable(&self.category, &Some(all.clone())).unwrap_or(executable)
344+
});
344345

345346
PythonEnvironment {
346347
display_name: self.display_name,
@@ -358,6 +359,43 @@ impl PythonEnvironmentBuilder {
358359
}
359360
}
360361

362+
// Given a list of executables, return the one with the shortest path.
363+
// The shortest path is the most likely to be most user friendly.
364+
fn get_shortest_executable(
365+
category: &PythonEnvironmentCategory,
366+
exes: &Option<Vec<PathBuf>>,
367+
) -> Option<PathBuf> {
368+
// For windows store, the exe should always be the one in the WindowsApps folder.
369+
if *category == PythonEnvironmentCategory::WindowsStore {
370+
if let Some(exes) = exes {
371+
if let Some(exe) = exes.iter().find(|e| {
372+
e.to_string_lossy().contains("AppData")
373+
&& e.to_string_lossy().contains("Local")
374+
&& e.to_string_lossy().contains("Microsoft")
375+
&& e.to_string_lossy().contains("WindowsApps")
376+
}) {
377+
return Some(exe.clone());
378+
}
379+
}
380+
}
381+
382+
// Ensure the executable always points to the shorted path.
383+
if let Some(mut exes) = exes.clone() {
384+
exes.sort_by(|a, b| {
385+
a.to_str()
386+
.unwrap_or_default()
387+
.len()
388+
.cmp(&b.to_str().unwrap_or_default().len())
389+
});
390+
if exes.is_empty() {
391+
return None;
392+
}
393+
Some(exes[0].clone())
394+
} else {
395+
None
396+
}
397+
}
398+
361399
pub fn get_environment_key(env: &PythonEnvironment) -> Option<PathBuf> {
362400
if let Some(exe) = &env.executable {
363401
Some(exe.clone())

crates/pet-python-utils/src/env.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44
use log::{error, trace};
55
use pet_fs::path::norm_case;
66
use serde::Deserialize;
7-
use std::path::{Path, PathBuf};
7+
use std::{
8+
path::{Path, PathBuf},
9+
time::SystemTime,
10+
};
811

912
use crate::pyvenv_cfg::PyVenvCfg;
1013

@@ -90,6 +93,7 @@ impl ResolvedPythonEnv {
9093
pub fn from(executable: &Path) -> Option<Self> {
9194
// Spawn the python exe and get the version, sys.prefix and sys.executable.
9295
let executable = executable.to_str()?;
96+
let start = SystemTime::now();
9397
trace!("Executing Python: {} -c {}", executable, PYTHON_INFO_CMD);
9498
let result = std::process::Command::new(executable)
9599
.args(["-c", PYTHON_INFO_CMD])
@@ -98,8 +102,9 @@ impl ResolvedPythonEnv {
98102
Ok(output) => {
99103
let output = String::from_utf8(output.stdout).unwrap().trim().to_string();
100104
trace!(
101-
"Python Execution for {:?} produced an output {:?}",
105+
"Executed Python {:?} in {:?} & produced an output {:?}",
102106
executable,
107+
start.elapsed(),
103108
output
104109
);
105110
if let Some((_, output)) = output.split_once(PYTHON_INFO_JSON_SEPARATOR) {

crates/pet-python-utils/src/executable.rs

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -112,26 +112,6 @@ fn is_python_executable_name(exe: &Path) -> bool {
112112
}
113113
}
114114

115-
// Given a list of executables, return the one with the shortest path.
116-
// The shortest path is the most likely to be most user friendly.
117-
pub fn get_shortest_executable(exes: &Option<Vec<PathBuf>>) -> Option<PathBuf> {
118-
// Ensure the executable always points to the shorted path.
119-
if let Some(mut exes) = exes.clone() {
120-
exes.sort_by(|a, b| {
121-
a.to_str()
122-
.unwrap_or_default()
123-
.len()
124-
.cmp(&b.to_str().unwrap_or_default().len())
125-
});
126-
if exes.is_empty() {
127-
return None;
128-
}
129-
Some(exes[0].clone())
130-
} else {
131-
None
132-
}
133-
}
134-
135115
#[cfg(test)]
136116
mod tests {
137117
use super::*;

crates/pet-reporter/src/jsonrpc.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
use crate::{environment::Environment, manager::Manager};
55
use env_logger::Builder;
6-
use log::LevelFilter;
6+
use log::{trace, LevelFilter};
77
use pet_core::{manager::EnvManager, python_environment::PythonEnvironment, reporter::Reporter};
88
use pet_jsonrpc::send_message;
99
use serde::{Deserialize, Serialize};
@@ -12,10 +12,12 @@ pub struct JsonRpcReporter {}
1212

1313
impl Reporter for JsonRpcReporter {
1414
fn report_manager(&self, manager: &EnvManager) {
15+
trace!("Reporting Manager {:?}", manager);
1516
send_message("manager", Manager::from(manager).into())
1617
}
1718

1819
fn report_environment(&self, env: &PythonEnvironment) {
20+
trace!("Reporting Environment {:?}", env);
1921
send_message("environment", Environment::from(env).into())
2022
}
2123
}

crates/pet-windows-store/src/environments.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,15 @@ impl PotentialPython {
6363
} else {
6464
None
6565
})
66-
.version(Some(self.version.clone()))
66+
// We only have the partial version, no point returning bogus info.
67+
// .version(Some(self.version.clone()))
6768
.symlinks(Some(vec![
68-
parent.join(format!("python{:?}.exe", self.version)),
69+
parent.join(format!("python{}.exe", self.version)),
6970
path.join("python.exe"),
7071
path.join("python3.exe"),
71-
path.join(format!("python{:?}.exe", self.version)),
72+
path.join(format!("python{}.exe", self.version)),
7273
env_path.join("python.exe"),
73-
env_path.join(format!("python{:?}.exe", self.version)),
74+
env_path.join(format!("python{}.exe", self.version)),
7475
]))
7576
.build(),
7677
)

crates/pet/src/jsonrpc.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,11 +166,12 @@ pub fn handle_resolve(context: Arc<Context>, id: u32, params: Value) {
166166
&resolved,
167167
);
168168

169+
trace!("Resolved env {:?} as {:?}", executable, resolved);
169170
send_reply(id, Some(ResolveResult::new(&resolved, now.elapsed())));
170171
} else {
171172
error!(
172-
"Failed to resolve env, returning discovered env {:?}",
173-
executable
173+
"Failed to resolve env {:?}, returning discovered env {:?}",
174+
executable, result.discovered
174175
);
175176
send_reply(
176177
id,

crates/pet/src/resolve.rs

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ use std::{path::PathBuf, sync::Arc};
55

66
use log::{trace, warn};
77
use pet_core::{
8-
arch::Architecture, os_environment::EnvironmentApi, python_environment::PythonEnvironment,
8+
arch::Architecture,
9+
os_environment::EnvironmentApi,
10+
python_environment::{PythonEnvironment, PythonEnvironmentBuilder},
911
Locator,
1012
};
1113
use pet_env_var_path::get_search_paths_from_env_variables;
@@ -43,23 +45,33 @@ pub fn resolve_environment(
4345
info
4446
);
4547
let discovered = env.clone();
46-
let mut resolved = env.clone();
47-
let mut symlinks = resolved.symlinks.clone().unwrap_or_default();
48-
48+
let mut symlinks = env.symlinks.clone().unwrap_or_default();
4949
symlinks.push(info.executable.clone());
5050
symlinks.append(&mut info.symlink.clone().unwrap_or_default());
5151
symlinks.sort();
5252
symlinks.dedup();
5353

54-
resolved.symlinks = Some(symlinks);
55-
resolved.version = Some(info.version);
56-
resolved.prefix = Some(info.prefix);
57-
resolved.arch = Some(if info.is64_bit {
54+
let version = Some(info.version);
55+
let prefix = Some(info.prefix);
56+
let arch = Some(if info.is64_bit {
5857
Architecture::X64
5958
} else {
6059
Architecture::X86
6160
});
6261

62+
let resolved = PythonEnvironmentBuilder::new(env.category)
63+
.arch(arch)
64+
.display_name(env.display_name)
65+
.executable(Some(info.executable))
66+
.manager(env.manager)
67+
.name(env.name)
68+
.prefix(prefix)
69+
.project(env.project)
70+
.search_path(env.search_path)
71+
.symlinks(Some(symlinks))
72+
.version(version)
73+
.build();
74+
6375
Some(ResolvedEnvironment {
6476
discovered,
6577
resolved: Some(resolved),

0 commit comments

Comments
 (0)