Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions crates/pet-conda/src/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ fn get_conda_executable(path: &Path) -> Option<PathBuf> {
let relative_path_to_conda_exe = vec![
PathBuf::from("Scripts").join("conda.exe"),
PathBuf::from("Scripts").join("conda.bat"),
PathBuf::from("bin").join("conda.exe"),
PathBuf::from("bin").join("conda.bat"),
];
#[cfg(unix)]
let relative_path_to_conda_exe = vec![PathBuf::from("bin").join("conda")];
Expand Down
13 changes: 11 additions & 2 deletions crates/pet-core/src/pyvenv_cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,17 @@ fn find(path: &Path) -> Option<PathBuf> {
return Some(cfg);
}

let bin = if cfg!(windows) { "Scripts" } else { "bin" };
if path.ends_with(bin) {
if cfg!(windows) {
// Only windows installations have a `Scripts` directory.
if path.ends_with("Scripts") {
let cfg = path.parent()?.join(PYVENV_CONFIG_FILE);
if cfg.exists() {
return Some(cfg);
}
}
}
// Some windows installations have a `bin` directory. https://github.com/microsoft/vscode-python/issues/24792
if path.ends_with("bin") {
let cfg = path.parent()?.join(PYVENV_CONFIG_FILE);
if cfg.exists() {
return Some(cfg);
Expand Down
15 changes: 12 additions & 3 deletions crates/pet-python-utils/src/executable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ pub fn find_executable(env_path: &Path) -> Option<PathBuf> {
[
env_path.join("Scripts").join("python.exe"),
env_path.join("Scripts").join("python3.exe"),
env_path.join("bin").join("python.exe"),
env_path.join("bin").join("python3.exe"),
env_path.join("python.exe"),
env_path.join("python3.exe"),
]
Expand All @@ -41,13 +43,20 @@ pub fn find_executable(env_path: &Path) -> Option<PathBuf> {
}

pub fn find_executables<T: AsRef<Path>>(env_path: T) -> Vec<PathBuf> {
let mut env_path = env_path.as_ref().to_path_buf();
// Never find exes in `.pyenv/shims/` folder, they are not valid exes
if env_path.as_ref().ends_with(".pyenv/shims") {
if env_path.ends_with(".pyenv/shims") {
return vec![];
}
let mut python_executables = vec![];
let bin = if cfg!(windows) { "Scripts" } else { "bin" };
let mut env_path = env_path.as_ref().to_path_buf();
if cfg!(windows) {
// Only windows can have a Scripts folder
let bin = "Scripts";
if env_path.join(bin).exists() {
env_path = env_path.join(bin);
}
}
let bin = "bin"; // Windows can have bin as well, https://github.com/microsoft/vscode-python/issues/24792
if env_path.join(bin).exists() {
env_path = env_path.join(bin);
}
Expand Down
9 changes: 8 additions & 1 deletion crates/pet-python-utils/src/headers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,14 @@ pub struct Headers {
impl Headers {
pub fn get_version(path: &Path) -> Option<String> {
let mut path = path.to_path_buf();
let bin = if cfg!(windows) { "Scripts" } else { "bin" };
if cfg!(windows) {
// Only Windows can have a Scripts folder
let bin = "Scripts";
if path.join(bin).exists() {
path = path.join(bin);
}
}
let bin = "bin"; // Windows can have bin as well, see https://github.com/microsoft/vscode-python/issues/24792
if path.ends_with(bin) {
path.pop();
}
Expand Down
24 changes: 19 additions & 5 deletions crates/pet-python-utils/src/version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,12 @@ pub fn from_creator_for_virtual_env(prefix: &Path) -> Option<String> {
if let Some(version) = Headers::get_version(prefix) {
return Some(version);
}
let bin = if cfg!(windows) { "Scripts" } else { "bin" };
let executable = &prefix.join(bin).join("python");
let mut bin = "bin";
let mut executable = prefix.join(bin).join("python");
if cfg!(windows) && !executable.exists() {
bin = "Scripts";
executable = prefix.join(bin).join("python.exe");
}

// Determine who created this virtual environment, and get version of that environment.
// Note, its unlikely conda envs were used to create virtual envs, thats a very bad idea (known to cause issues and not reccomended).
Expand Down Expand Up @@ -67,8 +71,14 @@ pub fn from_prefix(prefix: &Path) -> Option<String> {
/// Using this information its possible to determine the version of the Python environment used to create the env.
fn get_python_exe_used_to_create_venv<T: AsRef<Path>>(executable: T) -> Option<PathBuf> {
let parent_dir = executable.as_ref().parent()?;
let bin = if cfg!(windows) { "Scripts" } else { "bin" };
if parent_dir.file_name().unwrap_or_default() != bin {
if cfg!(windows) {
if parent_dir.file_name().unwrap_or_default() != "bin"
&& parent_dir.file_name().unwrap_or_default() != "Scripts"
{
warn!("Attempted to determine creator of virtual environment, but the env executable ({:?}) is not in the expected location.", executable.as_ref());
return None;
}
} else if parent_dir.file_name().unwrap_or_default() != "bin" {
warn!("Attempted to determine creator of virtual environment, but the env executable ({:?}) is not in the expected location.", executable.as_ref());
return None;
}
Expand All @@ -93,7 +103,11 @@ fn get_version_from_pyvenv_if_pyvenv_cfg_and_exe_created_same_time(
return None;
}
let cfg_metadata = pyvenv_cfg.metadata().ok()?;
let exe_metadata = prefix.join("Scripts").join("python.exe").metadata().ok()?;
let mut bin = prefix.join("Scripts");
if !bin.exists() {
bin = prefix.join("bin");
}
let exe_metadata = bin.join("python.exe").metadata().ok()?;
let cfg_modified = cfg_metadata
.modified()
.ok()?
Expand Down
14 changes: 9 additions & 5 deletions crates/pet-virtualenv/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,19 @@ pub fn is_virtualenv(env: &PythonEnv) -> bool {
}

pub fn is_virtualenv_dir(path: &Path) -> bool {
if cfg!(windows) {
is_virtualenv_dir_impl(path, "Scripts") || is_virtualenv_dir_impl(path, "bin")
} else {
is_virtualenv_dir_impl(path, "bin")
}
}

fn is_virtualenv_dir_impl(path: &Path, bin: &str) -> bool {
// Check if the executable is in a bin or Scripts directory.
// Possible for some reason we do not have the prefix.
let mut path = path.to_path_buf();
if !path.ends_with("bin") && !path.ends_with("Scripts") {
if cfg!(windows) {
path = path.join("Scripts");
} else {
path = path.join("bin");
}
path = path.join(bin);
}

// Never consider global locations to be virtualenvs
Expand Down
Loading