@@ -231,6 +231,8 @@ impl fmt::Display for PythonEnvironment {
231231mod tests {
232232 use super :: * ;
233233 use std:: fs;
234+ #[ cfg( unix) ]
235+ use std:: os:: unix:: fs:: PermissionsExt ; // Needed for setting execute permission
234236 use tempfile:: tempdir;
235237
236238 mod env_discovery {
@@ -289,6 +291,29 @@ mod tests {
289291 }
290292 }
291293
294+ // Guard struct to temporarily modify the PATH environment variable
295+ struct PathGuard {
296+ original_path : Option < String > ,
297+ }
298+
299+ impl PathGuard {
300+ fn set ( new_path_val : & str ) -> Self {
301+ let original_path = env:: var ( "PATH" ) . ok ( ) ;
302+ env:: set_var ( "PATH" , new_path_val) ;
303+ Self { original_path }
304+ }
305+ }
306+
307+ impl Drop for PathGuard {
308+ fn drop ( & mut self ) {
309+ // Restore original PATH, or remove if it wasn't set initially
310+ match self . original_path . as_deref ( ) {
311+ Some ( val) => env:: set_var ( "PATH" , val) ,
312+ None => env:: remove_var ( "PATH" ) ,
313+ }
314+ }
315+ }
316+
292317 #[ test]
293318 fn test_explicit_venv_path_found ( ) {
294319 let project_dir = tempdir ( ) . unwrap ( ) ;
@@ -417,31 +442,83 @@ mod tests {
417442 }
418443
419444 #[ test]
420- #[ ignore = "Relies on system python being available and having standard layout" ]
445+ // #[ignore = "Relies on system python being available and having standard layout"] // No longer ignored!
421446 fn test_system_python_fallback ( ) {
422- let project_dir = tempdir ( ) . unwrap ( ) ;
447+ let project_dir = tempdir ( ) . unwrap ( ) ; // Dummy project dir, not used for discovery here.
423448
424449 // Set VIRTUAL_ENV to something known to be invalid to ensure it's ignored.
425450 let invalid_virtual_env_path =
426451 project_dir. path ( ) . join ( "non_existent_venv_sys_fallback" ) ;
427452 let _guard =
428453 VirtualEnvGuard :: set ( "VIRTUAL_ENV" , invalid_virtual_env_path. to_str ( ) . unwrap ( ) ) ;
454+
455+ // --- Set up mock system python ---
456+ let mock_sys_python_dir = tempdir ( ) . unwrap ( ) ;
457+ let mock_sys_python_prefix = mock_sys_python_dir. path ( ) ;
458+
459+ #[ cfg( unix) ]
460+ let ( bin_subdir, python_exe, site_packages_rel_path) = (
461+ "bin" ,
462+ "python" ,
463+ Path :: new ( "lib" ) . join ( "python3.9" ) . join ( "site-packages" ) ,
464+ ) ;
465+ #[ cfg( windows) ]
466+ let ( bin_subdir, python_exe, site_packages_rel_path) = (
467+ "Scripts" ,
468+ "python.exe" ,
469+ Path :: new ( "Lib" ) . join ( "site-packages" ) ,
470+ ) ;
471+
472+ let bin_dir = mock_sys_python_prefix. join ( bin_subdir) ;
473+ fs:: create_dir_all ( & bin_dir) . unwrap ( ) ;
474+ let python_path = bin_dir. join ( python_exe) ;
475+ fs:: write ( & python_path, "" ) . unwrap ( ) ; // Create dummy executable
476+
477+ // Ensure the dummy executable has execute permissions (required by `which` on Unix)
478+ #[ cfg( unix) ]
479+ {
480+ let mut perms = fs:: metadata ( & python_path) . unwrap ( ) . permissions ( ) ;
481+ perms. set_mode ( 0o755 ) ; // rwxr-xr-x
482+ fs:: set_permissions ( & python_path, perms) . unwrap ( ) ;
483+ }
484+
485+ let site_packages_path = mock_sys_python_prefix. join ( site_packages_rel_path) ;
486+ fs:: create_dir_all ( & site_packages_path) . unwrap ( ) ;
487+
488+ // --- Manipulate PATH ---
489+ // Completely overwrite PATH to only include the mock bin directory
490+ let canonical_bin_dir =
491+ bin_dir. canonicalize ( ) . expect ( "Failed to canonicalize mock bin dir" ) ;
492+ let new_path = canonical_bin_dir. to_str ( ) . unwrap ( ) . to_string ( ) ;
493+ let _path_guard = PathGuard :: set ( & new_path) ;
494+
429495 // We don't create any venvs in project_dir
430496
431497 // This test assumes `which python` works and points to a standard layout
432498 let system_env = PythonEnvironment :: new ( project_dir. path ( ) , None ) ;
433499
434500 assert ! (
435501 system_env. is_some( ) ,
436- "Should fall back to system python if available "
502+ "Should fall back to the mock system python "
437503 ) ;
438504
439505 if let Some ( env) = system_env {
440- // Basic checks - exact paths depend heavily on the test environment
441- assert ! ( env. python_path. exists( ) ) ;
442- assert ! ( env. sys_prefix. exists( ) ) ;
443- assert ! ( !env. sys_path. is_empty( ) ) ;
444- assert ! ( env. sys_path[ 0 ] . exists( ) ) ; // Should contain the bin/Scripts dir
506+ assert_eq ! ( env. python_path, python_path, "Python path should match mock" ) ;
507+ assert_eq ! (
508+ env. sys_prefix,
509+ mock_sys_python_prefix,
510+ "Sys prefix should match mock prefix"
511+ ) ;
512+ assert ! (
513+ env. sys_path. contains( & bin_dir) ,
514+ "Sys path should contain mock bin dir"
515+ ) ;
516+ assert ! (
517+ env. sys_path. contains( & site_packages_path) ,
518+ "Sys path should contain mock site-packages"
519+ ) ;
520+ } else {
521+ panic ! ( "Expected to find environment, but got None" ) ; // Should not happen if assert above passed
445522 }
446523 }
447524
0 commit comments