Skip to content

Commit a2ed341

Browse files
authored
Python can be in bin dir in windows as well (#208)
Fixes #190
1 parent 7cd5195 commit a2ed341

File tree

6 files changed

+61
-16
lines changed

6 files changed

+61
-16
lines changed

crates/pet-conda/src/manager.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ fn get_conda_executable(path: &Path) -> Option<PathBuf> {
1717
let relative_path_to_conda_exe = vec![
1818
PathBuf::from("Scripts").join("conda.exe"),
1919
PathBuf::from("Scripts").join("conda.bat"),
20+
PathBuf::from("bin").join("conda.exe"),
21+
PathBuf::from("bin").join("conda.bat"),
2022
];
2123
#[cfg(unix)]
2224
let relative_path_to_conda_exe = vec![PathBuf::from("bin").join("conda")];

crates/pet-core/src/pyvenv_cfg.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,17 @@ fn find(path: &Path) -> Option<PathBuf> {
6161
return Some(cfg);
6262
}
6363

64-
let bin = if cfg!(windows) { "Scripts" } else { "bin" };
65-
if path.ends_with(bin) {
64+
if cfg!(windows) {
65+
// Only windows installations have a `Scripts` directory.
66+
if path.ends_with("Scripts") {
67+
let cfg = path.parent()?.join(PYVENV_CONFIG_FILE);
68+
if cfg.exists() {
69+
return Some(cfg);
70+
}
71+
}
72+
}
73+
// Some windows installations have a `bin` directory. https://github.com/microsoft/vscode-python/issues/24792
74+
if path.ends_with("bin") {
6675
let cfg = path.parent()?.join(PYVENV_CONFIG_FILE);
6776
if cfg.exists() {
6877
return Some(cfg);

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

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ pub fn find_executable(env_path: &Path) -> Option<PathBuf> {
2121
[
2222
env_path.join("Scripts").join("python.exe"),
2323
env_path.join("Scripts").join("python3.exe"),
24+
env_path.join("bin").join("python.exe"),
25+
env_path.join("bin").join("python3.exe"),
2426
env_path.join("python.exe"),
2527
env_path.join("python3.exe"),
2628
]
@@ -41,13 +43,20 @@ pub fn find_executable(env_path: &Path) -> Option<PathBuf> {
4143
}
4244

4345
pub fn find_executables<T: AsRef<Path>>(env_path: T) -> Vec<PathBuf> {
46+
let mut env_path = env_path.as_ref().to_path_buf();
4447
// Never find exes in `.pyenv/shims/` folder, they are not valid exes
45-
if env_path.as_ref().ends_with(".pyenv/shims") {
48+
if env_path.ends_with(".pyenv/shims") {
4649
return vec![];
4750
}
4851
let mut python_executables = vec![];
49-
let bin = if cfg!(windows) { "Scripts" } else { "bin" };
50-
let mut env_path = env_path.as_ref().to_path_buf();
52+
if cfg!(windows) {
53+
// Only windows can have a Scripts folder
54+
let bin = "Scripts";
55+
if env_path.join(bin).exists() {
56+
env_path = env_path.join(bin);
57+
}
58+
}
59+
let bin = "bin"; // Windows can have bin as well, https://github.com/microsoft/vscode-python/issues/24792
5160
if env_path.join(bin).exists() {
5261
env_path = env_path.join(bin);
5362
}

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,14 @@ pub struct Headers {
1919
impl Headers {
2020
pub fn get_version(path: &Path) -> Option<String> {
2121
let mut path = path.to_path_buf();
22-
let bin = if cfg!(windows) { "Scripts" } else { "bin" };
22+
if cfg!(windows) {
23+
// Only Windows can have a Scripts folder
24+
let bin = "Scripts";
25+
if path.join(bin).exists() {
26+
path = path.join(bin);
27+
}
28+
}
29+
let bin = "bin"; // Windows can have bin as well, see https://github.com/microsoft/vscode-python/issues/24792
2330
if path.ends_with(bin) {
2431
path.pop();
2532
}

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

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,12 @@ pub fn from_creator_for_virtual_env(prefix: &Path) -> Option<String> {
2020
if let Some(version) = Headers::get_version(prefix) {
2121
return Some(version);
2222
}
23-
let bin = if cfg!(windows) { "Scripts" } else { "bin" };
24-
let executable = &prefix.join(bin).join("python");
23+
let mut bin = "bin";
24+
let mut executable = prefix.join(bin).join("python");
25+
if cfg!(windows) && !executable.exists() {
26+
bin = "Scripts";
27+
executable = prefix.join(bin).join("python.exe");
28+
}
2529

2630
// Determine who created this virtual environment, and get version of that environment.
2731
// Note, its unlikely conda envs were used to create virtual envs, thats a very bad idea (known to cause issues and not reccomended).
@@ -67,8 +71,14 @@ pub fn from_prefix(prefix: &Path) -> Option<String> {
6771
/// Using this information its possible to determine the version of the Python environment used to create the env.
6872
fn get_python_exe_used_to_create_venv<T: AsRef<Path>>(executable: T) -> Option<PathBuf> {
6973
let parent_dir = executable.as_ref().parent()?;
70-
let bin = if cfg!(windows) { "Scripts" } else { "bin" };
71-
if parent_dir.file_name().unwrap_or_default() != bin {
74+
if cfg!(windows) {
75+
if parent_dir.file_name().unwrap_or_default() != "bin"
76+
&& parent_dir.file_name().unwrap_or_default() != "Scripts"
77+
{
78+
warn!("Attempted to determine creator of virtual environment, but the env executable ({:?}) is not in the expected location.", executable.as_ref());
79+
return None;
80+
}
81+
} else if parent_dir.file_name().unwrap_or_default() != "bin" {
7282
warn!("Attempted to determine creator of virtual environment, but the env executable ({:?}) is not in the expected location.", executable.as_ref());
7383
return None;
7484
}
@@ -93,7 +103,11 @@ fn get_version_from_pyvenv_if_pyvenv_cfg_and_exe_created_same_time(
93103
return None;
94104
}
95105
let cfg_metadata = pyvenv_cfg.metadata().ok()?;
96-
let exe_metadata = prefix.join("Scripts").join("python.exe").metadata().ok()?;
106+
let mut bin = prefix.join("Scripts");
107+
if !bin.exists() {
108+
bin = prefix.join("bin");
109+
}
110+
let exe_metadata = bin.join("python.exe").metadata().ok()?;
97111
let cfg_modified = cfg_metadata
98112
.modified()
99113
.ok()?

crates/pet-virtualenv/src/lib.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,19 @@ pub fn is_virtualenv(env: &PythonEnv) -> bool {
3030
}
3131

3232
pub fn is_virtualenv_dir(path: &Path) -> bool {
33+
if cfg!(windows) {
34+
is_virtualenv_dir_impl(path, "Scripts") || is_virtualenv_dir_impl(path, "bin")
35+
} else {
36+
is_virtualenv_dir_impl(path, "bin")
37+
}
38+
}
39+
40+
fn is_virtualenv_dir_impl(path: &Path, bin: &str) -> bool {
3341
// Check if the executable is in a bin or Scripts directory.
3442
// Possible for some reason we do not have the prefix.
3543
let mut path = path.to_path_buf();
3644
if !path.ends_with("bin") && !path.ends_with("Scripts") {
37-
if cfg!(windows) {
38-
path = path.join("Scripts");
39-
} else {
40-
path = path.join("bin");
41-
}
45+
path = path.join(bin);
4246
}
4347

4448
// Never consider global locations to be virtualenvs

0 commit comments

Comments
 (0)