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
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions crates/pet-homebrew/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,6 @@ pet-core = { path = "../pet-core" }
log = "0.4.21"
regex = "1.10.4"
rayon = "1.11.0"

[dev-dependencies]
tempfile = "3.10"
44 changes: 44 additions & 0 deletions crates/pet-homebrew/src/environment_locations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,47 @@ pub fn get_homebrew_prefix_bin(env_vars: &EnvVariables) -> Vec<PathBuf> {

homebrew_prefixes
}

#[cfg(test)]
mod tests {
use super::*;
use std::fs;
use tempfile::tempdir;

#[test]
fn homebrew_prefix_bin_uses_existing_homebrew_prefix_env_var() {
let homebrew_prefix = tempdir().unwrap();
let homebrew_bin = homebrew_prefix.path().join("bin");
fs::create_dir_all(&homebrew_bin).unwrap();
let env_vars = EnvVariables {
home: None,
root: None,
path: None,
homebrew_prefix: Some(homebrew_prefix.path().to_string_lossy().to_string()),
known_global_search_locations: vec![],
};

let prefix_bins = get_homebrew_prefix_bin(&env_vars);

assert!(prefix_bins.contains(&homebrew_bin));
}

#[test]
fn homebrew_prefix_bin_ignores_missing_homebrew_prefix_env_var() {
let homebrew_prefix_parent = tempdir().unwrap();
let missing_homebrew_prefix = homebrew_prefix_parent.path().join("missing-prefix");
let env_vars = EnvVariables {
home: None,
root: None,
path: None,
homebrew_prefix: Some(missing_homebrew_prefix.to_string_lossy().to_string()),
known_global_search_locations: vec![],
};

let prefix_bins = get_homebrew_prefix_bin(&env_vars);

assert!(!prefix_bins
.iter()
.any(|path| path == &missing_homebrew_prefix.join("bin")));
}
}
112 changes: 112 additions & 0 deletions crates/pet-homebrew/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,3 +170,115 @@ impl Locator for Homebrew {
});
}
}

#[cfg(all(test, unix))]
mod tests {
use super::*;
use tempfile::tempdir;

struct TestEnvironment {
homebrew_prefix: Option<String>,
}

impl Environment for TestEnvironment {
fn get_user_home(&self) -> Option<PathBuf> {
None
}

fn get_root(&self) -> Option<PathBuf> {
None
}

fn get_env_var(&self, key: String) -> Option<String> {
if key == "HOMEBREW_PREFIX" {
self.homebrew_prefix.clone()
} else {
None
}
}

fn get_know_global_search_locations(&self) -> Vec<PathBuf> {
vec![]
}
}

#[test]
fn homebrew_locator_reports_kind_and_supported_category() {
let locator = Homebrew::from(&TestEnvironment {
homebrew_prefix: None,
});

assert_eq!(locator.get_kind(), LocatorKind::Homebrew);
assert_eq!(
locator.supported_categories(),
vec![PythonEnvironmentKind::Homebrew]
);
}

#[test]
fn try_from_identifies_linuxbrew_python_executable() {
let locator = Homebrew::from(&TestEnvironment {
homebrew_prefix: None,
});
let env = PythonEnv::new(
PathBuf::from("/home/linuxbrew/.linuxbrew/Cellar/python@3.12/3.12.4/bin/python3.12"),
None,
None,
);

let homebrew_env = locator.try_from(&env).unwrap();

assert_eq!(homebrew_env.kind, Some(PythonEnvironmentKind::Homebrew));
assert_eq!(
homebrew_env.executable,
Some(PathBuf::from("/home/linuxbrew/.linuxbrew/bin/python3.12"))
);
assert_eq!(homebrew_env.version, Some("3.12.4".to_string()));
assert_eq!(homebrew_env.prefix, None);
assert!(homebrew_env
.symlinks
.as_ref()
.unwrap()
.contains(&PathBuf::from(
"/home/linuxbrew/.linuxbrew/Cellar/python@3.12/3.12.4/bin/python3.12"
)));
}

#[test]
fn try_from_rejects_non_homebrew_python() {
let locator = Homebrew::from(&TestEnvironment {
homebrew_prefix: None,
});
let env = PythonEnv::new(PathBuf::from("/usr/bin/python3.12"), None, None);

assert!(locator.try_from(&env).is_none());
}

#[test]
fn try_from_rejects_virtualenv_and_conda_prefixes() {
let locator = Homebrew::from(&TestEnvironment {
homebrew_prefix: None,
});

let venv_root = tempdir().unwrap();
let venv_bin = venv_root.path().join("bin");
fs::create_dir_all(&venv_bin).unwrap();
fs::write(venv_bin.join("activate"), b"").unwrap();
let venv_executable = venv_bin.join("python3.12");
fs::write(&venv_executable, b"").unwrap();
let venv = PythonEnv::new(venv_executable, Some(venv_root.path().to_path_buf()), None);
assert!(locator.try_from(&venv).is_none());

let conda_root = tempdir().unwrap();
fs::create_dir_all(conda_root.path().join("conda-meta")).unwrap();
let conda_executable = conda_root.path().join("bin").join("python3.12");
fs::create_dir_all(conda_executable.parent().unwrap()).unwrap();
fs::write(&conda_executable, b"").unwrap();
let conda = PythonEnv::new(
conda_executable,
Some(conda_root.path().to_path_buf()),
None,
);
assert!(locator.try_from(&conda).is_none());
}
}
36 changes: 36 additions & 0 deletions crates/pet-homebrew/src/sym_links.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,3 +243,39 @@ pub fn get_known_symlinks_impl(
vec![]
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn homebrew_python_paths_are_recognized_across_supported_prefixes() {
assert!(is_homebrew_python(Path::new(
"/opt/homebrew/Cellar/python@3.12/3.12.4/bin/python3.12"
)));
assert!(is_homebrew_python(Path::new(
"/usr/local/Cellar/python@3.11/3.11.9/bin/python3.11"
)));
assert!(is_homebrew_python(Path::new(
"/home/linuxbrew/.linuxbrew/Cellar/python@3.12/3.12.4/bin/python3.12"
)));
assert!(!is_homebrew_python(Path::new("/usr/bin/python3.12")));
}

#[test]
fn known_symlink_templates_include_resolved_executable_for_linuxbrew() {
let resolved_exe =
PathBuf::from("/home/linuxbrew/.linuxbrew/Cellar/python@3.12/3.12.4/bin/python3.12");
let symlinks = get_known_symlinks_impl(&resolved_exe, &"3.12.4".to_string());

assert!(symlinks.contains(&resolved_exe));
}

#[test]
fn known_symlink_templates_return_empty_for_unrecognized_paths() {
assert!(
get_known_symlinks_impl(Path::new("/usr/bin/python3.12"), &"3.12.4".to_string())
.is_empty()
);
}
}
Loading