Skip to content

Commit 96c0cff

Browse files
committed
Replace .env search with resolve_dot_env
1 parent cb6bfea commit 96c0cff

4 files changed

Lines changed: 134 additions & 5 deletions

File tree

crates/pet-fs/src/path.rs

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -730,4 +730,133 @@ mod tests {
730730
let _ = std::fs::remove_file(&symlink_path);
731731
let _ = std::fs::remove_file(&target_file);
732732
}
733+
734+
// ==================== resolve_dot_venv tests ====================
735+
736+
#[test]
737+
fn test_resolve_dot_venv_no_dot_venv() {
738+
// If .venv does not exist, return None
739+
let temp_dir = std::env::temp_dir();
740+
let test_dir = temp_dir.join("pet_test_no_dot_venv");
741+
let _ = std::fs::remove_dir_all(&test_dir);
742+
std::fs::create_dir_all(&test_dir).expect("Failed to create test dir");
743+
744+
assert_eq!(resolve_dot_venv(&test_dir), None);
745+
746+
let _ = std::fs::remove_dir_all(&test_dir);
747+
}
748+
749+
#[test]
750+
fn test_resolve_dot_venv_directory() {
751+
// If .venv is a directory, return its path
752+
let temp_dir = std::env::temp_dir();
753+
let test_dir = temp_dir.join("pet_test_dot_venv_dir");
754+
let dot_venv = test_dir.join(".venv");
755+
756+
let _ = std::fs::remove_dir_all(&test_dir);
757+
std::fs::create_dir_all(&dot_venv).expect("Failed to create .venv dir");
758+
759+
let result = resolve_dot_venv(&test_dir);
760+
assert_eq!(result, Some(dot_venv));
761+
762+
let _ = std::fs::remove_dir_all(&test_dir);
763+
}
764+
765+
#[test]
766+
fn test_resolve_dot_venv_file_absolute_path() {
767+
// If .venv is a file containing an absolute path to an existing directory, return it
768+
let temp_dir = std::env::temp_dir();
769+
let test_dir = temp_dir.join("pet_test_dot_venv_file_abs");
770+
let target_venv = temp_dir.join("pet_test_dot_venv_target_abs");
771+
772+
let _ = std::fs::remove_dir_all(&test_dir);
773+
let _ = std::fs::remove_dir_all(&target_venv);
774+
std::fs::create_dir_all(&test_dir).expect("Failed to create test dir");
775+
std::fs::create_dir_all(&target_venv).expect("Failed to create target venv dir");
776+
777+
let dot_venv_file = test_dir.join(".venv");
778+
std::fs::write(&dot_venv_file, target_venv.to_string_lossy().as_ref())
779+
.expect("Failed to write .venv file");
780+
781+
let result = resolve_dot_venv(&test_dir);
782+
assert_eq!(result, Some(target_venv.clone()));
783+
784+
let _ = std::fs::remove_dir_all(&test_dir);
785+
let _ = std::fs::remove_dir_all(&target_venv);
786+
}
787+
788+
#[test]
789+
fn test_resolve_dot_venv_file_relative_path() {
790+
// If .venv is a file containing a relative path, resolve it against the dir
791+
let temp_dir = std::env::temp_dir();
792+
let test_dir = temp_dir.join("pet_test_dot_venv_file_rel");
793+
let target_venv = test_dir.join("my_venv");
794+
795+
let _ = std::fs::remove_dir_all(&test_dir);
796+
std::fs::create_dir_all(&target_venv).expect("Failed to create target venv dir");
797+
798+
let dot_venv_file = test_dir.join(".venv");
799+
std::fs::write(&dot_venv_file, "my_venv").expect("Failed to write .venv file");
800+
801+
let result = resolve_dot_venv(&test_dir);
802+
assert_eq!(result, Some(target_venv.clone()));
803+
804+
let _ = std::fs::remove_dir_all(&test_dir);
805+
}
806+
807+
#[test]
808+
fn test_resolve_dot_venv_file_nonexistent_target() {
809+
// If .venv is a file pointing to a non-existent directory, return None
810+
let temp_dir = std::env::temp_dir();
811+
let test_dir = temp_dir.join("pet_test_dot_venv_file_missing");
812+
813+
let _ = std::fs::remove_dir_all(&test_dir);
814+
std::fs::create_dir_all(&test_dir).expect("Failed to create test dir");
815+
816+
let dot_venv_file = test_dir.join(".venv");
817+
std::fs::write(&dot_venv_file, "/this/path/does/not/exist")
818+
.expect("Failed to write .venv file");
819+
820+
assert_eq!(resolve_dot_venv(&test_dir), None);
821+
822+
let _ = std::fs::remove_dir_all(&test_dir);
823+
}
824+
825+
#[test]
826+
fn test_resolve_dot_venv_file_whitespace_trimmed() {
827+
// Whitespace around the path should be trimmed
828+
let temp_dir = std::env::temp_dir();
829+
let test_dir = temp_dir.join("pet_test_dot_venv_whitespace");
830+
let target_venv = test_dir.join("ws_venv");
831+
832+
let _ = std::fs::remove_dir_all(&test_dir);
833+
std::fs::create_dir_all(&target_venv).expect("Failed to create target venv dir");
834+
835+
let dot_venv_file = test_dir.join(".venv");
836+
std::fs::write(&dot_venv_file, " ws_venv \n").expect("Failed to write .venv file");
837+
838+
let result = resolve_dot_venv(&test_dir);
839+
assert_eq!(result, Some(target_venv.clone()));
840+
841+
let _ = std::fs::remove_dir_all(&test_dir);
842+
}
843+
844+
#[test]
845+
fn test_resolve_dot_venv_file_points_to_file_not_dir() {
846+
// If .venv file points to a path that exists but is a file (not a dir), return None
847+
let temp_dir = std::env::temp_dir();
848+
let test_dir = temp_dir.join("pet_test_dot_venv_target_is_file");
849+
let target_file = test_dir.join("not_a_dir");
850+
851+
let _ = std::fs::remove_dir_all(&test_dir);
852+
std::fs::create_dir_all(&test_dir).expect("Failed to create test dir");
853+
std::fs::write(&target_file, "I am a file").expect("Failed to create target file");
854+
855+
let dot_venv_file = test_dir.join(".venv");
856+
std::fs::write(&dot_venv_file, "not_a_dir").expect("Failed to write .venv file");
857+
858+
assert_eq!(resolve_dot_venv(&test_dir), None);
859+
860+
let _ = std::fs::remove_dir_all(&test_dir);
861+
}
733862
}

crates/pet-poetry/src/environment_locations.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ fn list_all_environments_from_project_config(
108108
// Order of preference is Project (local config) > EnvVariable > Global
109109
if should_use_local_venv_as_poetry_env(global, &local, env) {
110110
// If virtualenvs are in the project, then look for .venv
111-
let venv = path.join(".venv");
111+
let venv = resolve_dot_env(path);
112112
if venv.is_dir() {
113113
envs.push(venv);
114114
}

crates/pet-uv/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,7 @@ fn find_workspace_for_project(project_path: &Path) -> Option<PythonEnvironment>
422422
/// Builds a `PythonEnvironment` for a uv workspace root if it has a `.venv` with a valid
423423
/// uv-managed pyvenv.cfg.
424424
fn build_workspace_env(workspace_root: &Path) -> Option<PythonEnvironment> {
425-
let prefix = workspace_root.join(".venv");
425+
let prefix = resolve_dot_env(workspace_root);
426426
let pyvenv_cfg = prefix.join("pyvenv.cfg");
427427
if !pyvenv_cfg.exists() {
428428
trace!(
@@ -465,8 +465,8 @@ fn list_envs_in_directory(path: &Path) -> Vec<PythonEnvironment> {
465465
let Some(pyproject) = pyproject else {
466466
return envs;
467467
};
468-
let pyvenv_cfg = path.join(".venv/pyvenv.cfg");
469-
let prefix = path.join(".venv");
468+
let pyvenv_cfg = resolve_dot_env(path).join("pyvenv.cfg");
469+
let prefix = resolve_dot_env(path);
470470
let unix_executable = prefix.join("bin/python");
471471
let windows_executable = prefix.join("Scripts/python.exe");
472472
let executable = if unix_executable.exists() {

crates/pet/src/find.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ pub fn find_python_environments_in_workspace_folder_recursive(
277277
// Possible this is a virtual env
278278
workspace_folder.to_path_buf(),
279279
// Optimize for finding these first.
280-
workspace_folder.join(".venv"),
280+
resolve_dot_env(workspace_folder),
281281
workspace_folder.join(".conda"),
282282
workspace_folder.join(".virtualenv"),
283283
workspace_folder.join("venv"),

0 commit comments

Comments
 (0)