@@ -90,34 +90,64 @@ struct PythonEnvironment {
9090
9191impl PythonEnvironment {
9292 fn new ( project_path : & Path , venv_path : Option < & str > ) -> Option < Self > {
93+ eprintln ! (
94+ "[PythonEnvironment::new] Start search. Project: '{}', Explicit venv_path: {:?}" ,
95+ project_path. display( ) , venv_path
96+ ) ;
97+
9398 if let Some ( path) = venv_path {
99+ eprintln ! ( "[PythonEnvironment::new] Checking explicit venv_path: '{}'" , path) ;
94100 let prefix = PathBuf :: from ( path) ;
101+ // Call from_venv_prefix for the explicit path
102+ let explicit_env = Self :: from_venv_prefix ( & prefix) ;
95103 // If explicit path is provided and valid, use it.
96104 // If it's invalid, we *don't* fall through according to current logic.
97105 // Let's refine this: if explicit path is given but invalid, maybe we should error or log?
98106 // For now, stick to the current implementation: if from_venv_prefix returns Some, we use it.
99- if let Some ( env) = Self :: from_venv_prefix ( & prefix) {
107+ if let Some ( env) = explicit_env {
108+ eprintln ! (
109+ "[PythonEnvironment::new] Found environment via explicit path: '{}'" ,
110+ path
111+ ) ;
100112 return Some ( env) ;
101113 } else {
102114 // Explicit path provided but invalid. Should we stop here?
103115 // The current code implicitly continues to VIRTUAL_ENV check.
104116 // Let's keep the current behavior for now, but it's worth noting.
105117 eprintln ! (
106- "Warning: Explicit venv_path '{}' provided but seems invalid . Continuing search." ,
118+ "[PythonEnvironment::new] Explicit venv_path '{}' is invalid or incomplete . Continuing search.. ." ,
107119 path
108120 ) ;
109121 }
122+ } else {
123+ eprintln ! ( "[PythonEnvironment::new] No explicit venv_path provided." ) ;
110124 }
111125
112126 if let Ok ( virtual_env) = env:: var ( "VIRTUAL_ENV" ) {
113127 if !virtual_env. is_empty ( ) {
128+ eprintln ! ( "[PythonEnvironment::new] Checking VIRTUAL_ENV: '{}'" , virtual_env) ;
114129 let prefix = PathBuf :: from ( virtual_env) ;
130+ // Call from_venv_prefix for the VIRTUAL_ENV path
115131 if let Some ( env) = Self :: from_venv_prefix ( & prefix) {
132+ eprintln ! (
133+ "[PythonEnvironment::new] Found environment via VIRTUAL_ENV: '{}'" ,
134+ prefix. display( )
135+ ) ;
116136 return Some ( env) ;
137+ } else {
138+ eprintln ! (
139+ "[PythonEnvironment::new] VIRTUAL_ENV path '{}' is invalid or incomplete. Continuing search..." ,
140+ prefix. display( )
141+ ) ;
117142 }
143+ } else {
144+ eprintln ! ( "[PythonEnvironment::new] VIRTUAL_ENV variable is set but empty." ) ;
118145 }
146+ } else {
147+ eprintln ! ( "[PythonEnvironment::new] VIRTUAL_ENV variable not found." ) ;
119148 }
120149
150+ eprintln ! ( "[PythonEnvironment::new] Checking common venv directories within project: '{}'" , project_path. display( ) ) ;
121151 for venv_dir in & [ ".venv" , "venv" , "env" , ".env" ] {
122152 let potential_venv = project_path. join ( venv_dir) ;
123153 if potential_venv. is_dir ( ) {
@@ -126,11 +156,23 @@ impl PythonEnvironment {
126156 }
127157 }
128158 }
129-
130- Self :: from_system_python ( )
159+ eprintln ! ( "[PythonEnvironment::new] No valid environment found in common project directories." ) ;
160+
161+ eprintln ! ( "[PythonEnvironment::new] Falling back to system Python search..." ) ;
162+ let system_env = Self :: from_system_python ( ) ;
163+ if system_env. is_some ( ) {
164+ eprintln ! ( "[PythonEnvironment::new] Found system Python." ) ;
165+ } else {
166+ eprintln ! ( "[PythonEnvironment::new] Could not find system Python via 'which python'." ) ;
167+ }
168+ system_env // Return the result of the system python search
131169 }
132170
133171 fn from_venv_prefix ( prefix : & Path ) -> Option < Self > {
172+ eprintln ! (
173+ "[from_venv_prefix] Checking potential venv prefix: '{}'" ,
174+ prefix. display( )
175+ ) ;
134176 #[ cfg( not( windows) ) ]
135177 let python_path = prefix. join ( "bin" ) . join ( "python" ) ;
136178 #[ cfg( not( windows) ) ]
@@ -141,20 +183,38 @@ impl PythonEnvironment {
141183 #[ cfg( windows) ]
142184 let bin_dir = prefix. join ( "Scripts" ) ;
143185
186+ let prefix_is_dir = prefix. is_dir ( ) ;
187+ let python_exists = python_path. exists ( ) ;
188+
189+ eprintln ! (
190+ "[from_venv_prefix] Checking prefix directory '{}': Exists = {}" ,
191+ prefix. display( ) , prefix_is_dir
192+ ) ;
193+ eprintln ! (
194+ "[from_venv_prefix] Checking Python binary '{}': Exists = {}" ,
195+ python_path. display( ) , python_exists
196+ ) ;
197+
144198 // Check if the *prefix* and the *binary* exist.
145199 // Checking prefix helps avoid issues if only bin/python exists somehow.
146- if !prefix. is_dir ( ) || !python_path. exists ( ) {
200+ if !prefix_is_dir || !python_exists {
201+ eprintln ! ( "[from_venv_prefix] Basic requirements not met (prefix dir or python binary missing). Returning None." ) ;
147202 return None ;
148203 }
149204
150205 let mut sys_path = Vec :: new ( ) ;
151206 sys_path. push ( bin_dir) ; // Add bin/ or Scripts/
152207
153208 if let Some ( site_packages) = Self :: find_site_packages ( prefix) {
209+ // Check existence inside the if let, as find_site_packages might return a path that doesn't exist
154210 if site_packages. is_dir ( ) {
211+ eprintln ! ( "[from_venv_prefix] Confirmed site-packages directory '{}' exists. Adding to sys_path." , site_packages. display( ) ) ;
155212 sys_path. push ( site_packages) ;
213+ } else {
214+ eprintln ! ( "[from_venv_prefix] Warning: Found site-packages path '{}' but it's not a directory." , site_packages. display( ) ) ;
156215 }
157216 }
217+ eprintln ! ( "[from_venv_prefix] Successfully created environment for prefix '{}'" , prefix. display( ) ) ;
158218
159219 Some ( Self {
160220 python_path : python_path. clone ( ) ,
@@ -324,29 +384,56 @@ mod tests {
324384 fn test_explicit_venv_path_invalid_falls_through_to_virtual_env ( ) {
325385 let project_dir = tempdir ( ) . unwrap ( ) ;
326386 let venv_dir = tempdir ( ) . unwrap ( ) ;
387+ // Keep None here for consistency with original test logic
327388 let venv_prefix = create_mock_venv ( venv_dir. path ( ) , None ) ;
389+ let venv_prefix_str = venv_prefix. to_str ( ) . expect ( "Failed to convert venv_prefix path to string" ) ;
390+
391+ // --- Add checks immediately after creating the mock venv ---
392+ #[ cfg( not( windows) ) ]
393+ {
394+ let expected_bin = venv_prefix. join ( "bin" ) ;
395+ let expected_py = expected_bin. join ( "python" ) ;
396+ let expected_sp = venv_prefix. join ( "lib" ) . join ( "python3.9" ) . join ( "site-packages" ) ; // Matches default in create_mock_venv
397+ assert ! ( expected_py. exists( ) , "Mock python binary should exist at '{}'" , expected_py. display( ) ) ;
398+ assert ! ( expected_sp. is_dir( ) , "Mock site-packages dir should exist at '{}'" , expected_sp. display( ) ) ;
399+ }
400+ #[ cfg( windows) ]
401+ {
402+ let expected_scripts = venv_prefix. join ( "Scripts" ) ;
403+ let expected_py = expected_scripts. join ( "python.exe" ) ;
404+ let expected_sp = venv_prefix. join ( "Lib" ) . join ( "site-packages" ) ;
405+ assert ! ( expected_py. exists( ) , "Mock python binary should exist at '{}'" , expected_py. display( ) ) ;
406+ assert ! ( expected_sp. is_dir( ) , "Mock site-packages dir should exist at '{}'" , expected_sp. display( ) ) ;
407+ }
408+ // --- End added checks ---
328409
329410 // Set VIRTUAL_ENV to the valid path
330- let _guard = VirtualEnvGuard :: set ( "VIRTUAL_ENV" , venv_prefix . to_str ( ) . unwrap ( ) ) ;
411+ let _guard = VirtualEnvGuard :: set ( "VIRTUAL_ENV" , venv_prefix_str ) ;
331412
332413 // Provide an invalid explicit path (points to a non-existent directory)
333414 let invalid_path = project_dir. path ( ) . join ( "non_existent_venv" ) ;
334415 let invalid_path_str = invalid_path. to_str ( ) . unwrap ( ) ;
335416 // Ensure the invalid path doesn't accidentally exist
336417 assert ! ( !invalid_path. exists( ) , "Invalid path '{}' should not exist before test" , invalid_path. display( ) ) ;
337418
338- // --- Add a small delay before calling the function under test ---
339- eprintln ! ( "--- Adding small delay before PythonEnvironment::new call ---" ) ;
340- std:: thread:: sleep ( std:: time:: Duration :: from_millis ( 50 ) ) ; // 50ms delay
341- eprintln ! ( "--- Delay finished. Starting PythonEnvironment::new call for the test ---" ) ;
342- // --- End added delay ---
343-
344419 eprintln ! ( "--- Starting PythonEnvironment::new call for the test ---" ) ;
345420 // Call the function under test
346421 let env_result = PythonEnvironment :: new ( project_dir. path ( ) , Some ( invalid_path_str) ) ;
347422 eprintln ! ( "--- Finished PythonEnvironment::new call for the test ---" ) ;
348423
349- let env = env_result. expect ( "Should fall through to VIRTUAL_ENV" ) ;
424+ // Check the result with more detailed error message if it's None
425+ let env = env_result. unwrap_or_else ( || {
426+ // This path indicates `new` returned None, meaning the VIRTUAL_ENV check likely failed.
427+ panic ! (
428+ "PythonEnvironment::new returned None unexpectedly. \
429+ It should have fallen back to VIRTUAL_ENV ('{}'). \
430+ Project: '{}', Invalid Explicit Path: '{}'. \
431+ Check logs above for details on why from_venv_prefix might have failed for the VIRTUAL_ENV path.",
432+ venv_prefix_str,
433+ project_dir. path( ) . display( ) ,
434+ invalid_path_str
435+ ) ;
436+ } ) ;
350437
351438 // Should have found the one from VIRTUAL_ENV
352439 assert_eq ! (
@@ -362,10 +449,17 @@ mod tests {
362449 env. python_path, expected_python_path,
363450 "Python path should match the one in VIRTUAL_ENV bin dir"
364451 ) ;
452+ let expected_bin_dir = venv_prefix. join ( "bin" ) ;
365453 assert ! (
366- env. sys_path. contains( & venv_prefix . join ( "bin" ) ) ,
454+ env. sys_path. contains( & expected_bin_dir ) ,
367455 "Sys path should contain VIRTUAL_ENV bin dir"
368456 ) ;
457+ // Check against the default version used by create_mock_venv when None is passed
458+ let expected_site_packages = venv_prefix. join ( "lib" ) . join ( "python3.9" ) . join ( "site-packages" ) ;
459+ assert ! (
460+ env. sys_path. contains( & expected_site_packages) ,
461+ "Sys path should contain VIRTUAL_ENV site-packages dir ('{}')" , expected_site_packages. display( )
462+ ) ;
369463 }
370464
371465 #[ cfg( windows) ]
@@ -375,10 +469,16 @@ mod tests {
375469 env. python_path, expected_python_path,
376470 "Python path should match the one in VIRTUAL_ENV Scripts dir"
377471 ) ;
472+ let expected_scripts_dir = venv_prefix. join ( "Scripts" ) ;
378473 assert ! (
379- env. sys_path. contains( & venv_prefix . join ( "Scripts" ) ) ,
474+ env. sys_path. contains( & expected_scripts_dir ) ,
380475 "Sys path should contain VIRTUAL_ENV Scripts dir"
381476 ) ;
477+ let expected_site_packages = venv_prefix. join ( "Lib" ) . join ( "site-packages" ) ;
478+ assert ! (
479+ env. sys_path. contains( & expected_site_packages) ,
480+ "Sys path should contain VIRTUAL_ENV site-packages dir ('{}')" , expected_site_packages. display( )
481+ ) ;
382482 }
383483 }
384484
0 commit comments