11use miette:: { miette, Context , IntoDiagnostic } ;
22use std:: env;
3+ use std:: env:: VarError ;
34use std:: fs;
45use std:: io:: { self , BufRead } ;
56use std:: os:: unix:: process:: CommandExt ;
@@ -64,7 +65,6 @@ fn find_python_executables(version_from_cfg: &str, exclude_dir: &Path) -> Option
6465 None
6566 }
6667 } )
67- //.filter_map(|path| path.canonicalize().ok())
6868 . filter ( |potential_executable| potential_executable. parent ( ) != Some ( exclude_dir) )
6969 . filter ( |potential_executable| compare_versions ( version_from_cfg, & potential_executable) )
7070 . collect ( ) ;
@@ -77,16 +77,32 @@ fn find_python_executables(version_from_cfg: &str, exclude_dir: &Path) -> Option
7777}
7878
7979fn main ( ) -> miette:: Result < ( ) > {
80- let current_exe = env:: current_exe ( ) . unwrap ( ) ;
80+ let venv_home_path = PathBuf :: from (
81+ env:: var ( "VIRTUAL_ENV" )
82+ . into_diagnostic ( )
83+ . wrap_err ( "[aspect] $VIRTUAL_ENV was unbound! A venv must be activated." )
84+ . unwrap ( ) ,
85+ ) ;
86+
87+ let venv_interpreter_path: PathBuf = env:: var ( "PYTHONEXECUTABLE" )
88+ . map ( |x| PathBuf :: from ( x) )
89+ . map_err ( |_| Ok :: < PathBuf , VarError > ( venv_home_path. join ( "bin/python" ) ) )
90+ . unwrap ( ) ;
91+
92+ let excluded_interpreters_dir = & venv_home_path. join ( "bin" ) ;
93+
8194 let args: Vec < _ > = env:: args ( ) . collect ( ) ;
8295
83- #[ cfg( feature = "debug" ) ]
84- eprintln ! ( "[aspect] Current executable path: {:?}" , current_exe) ;
96+ //#[cfg(feature = "debug")]
97+ eprintln ! (
98+ "[aspect] Current executable path: {:?}" ,
99+ & venv_interpreter_path
100+ ) ;
85101
86- let Some ( pyvenv_cfg_path) = find_pyvenv_cfg ( & current_exe ) else {
102+ let Some ( pyvenv_cfg_path) = find_pyvenv_cfg ( & venv_interpreter_path ) else {
87103 return Err ( miette ! ( "pyvenv.cfg not found one directory level up." ) ) ;
88104 } ;
89- #[ cfg( feature = "debug" ) ]
105+ // #[cfg(feature = "debug")]
90106 eprintln ! ( "[aspect] Found pyvenv.cfg at: {:?}" , & pyvenv_cfg_path) ;
91107
92108 let version_info_result = extract_pyvenv_version_info ( & pyvenv_cfg_path)
@@ -101,33 +117,32 @@ fn main() -> miette::Result<()> {
101117 return Err ( miette ! ( "version_info key not found in pyvenv.cfg." ) ) ;
102118 } ;
103119
104- #[ cfg( feature = "debug" ) ]
105- eprintln ! ( "[aspect] version_info from pyvenv.cfg: {}" , & version_info) ;
120+ // #[cfg(feature = "debug")]
121+ eprintln ! ( "[aspect] version_info from pyvenv.cfg: {:? }" , & version_info) ;
106122
107123 let Some ( target_python_version) = parse_version_info ( & version_info) else {
108124 return Err ( miette ! ( "Could not parse version_info as x.y." ) ) ;
109125 } ;
110126
111- #[ cfg( feature = "debug" ) ]
127+ // #[cfg(feature = "debug")]
112128 eprintln ! (
113129 "[aspect] Parsed target Python version (major.minor): {}" ,
114130 & target_python_version
115131 ) ;
116132
117- let exclude_dir = current_exe. parent ( ) . unwrap ( ) . canonicalize ( ) . unwrap ( ) ;
133+ //#[cfg(feature = "debug")]
134+ eprintln ! ( "[aspect] Ignoring dir {:?}" , & excluded_interpreters_dir) ;
118135
119- #[ cfg( feature = "debug" ) ]
120- eprintln ! ( "[aspect] Ignoring dir {:?}" , & exclude_dir) ;
121-
122- let Some ( python_executables) = find_python_executables ( & target_python_version, & exclude_dir)
136+ let Some ( python_executables) =
137+ find_python_executables ( & target_python_version, & excluded_interpreters_dir)
123138 else {
124139 return Err ( miette ! (
125140 "No suitable Python interpreter found in PATH matching version '{}'." ,
126141 & version_info,
127142 ) ) ;
128143 } ;
129144
130- #[ cfg( feature = "debug" ) ]
145+ // #[cfg(feature = "debug")]
131146 {
132147 eprintln ! ( "[aspect] Found potential Python interpreters in PATH with matching version:" ) ;
133148 for exe in & python_executables {
@@ -148,30 +163,27 @@ fn main() -> miette::Result<()> {
148163 }
149164 } ;
150165
151- let Some ( interpreter_path ) = python_executables. get ( index) else {
166+ let Some ( actual_interpreter_path ) = python_executables. get ( index) else {
152167 return Err ( miette ! (
153168 "Unable to find another interpreter at index {}" ,
154169 index
155170 ) ) ;
156171 } ;
157172
158- let exe_path = current_exe. to_string_lossy ( ) . into_owned ( ) ;
159173 let exec_args = & args[ 1 ..] ;
160174
161- #[ cfg( feature = "debug" ) ]
175+ // #[cfg(feature = "debug")]
162176 eprintln ! (
163177 "[aspect] Attempting to execute: {:?} with argv[0] as {:?} and args as {:?}" ,
164- interpreter_path , exe_path , exec_args,
178+ & actual_interpreter_path , & venv_interpreter_path , exec_args,
165179 ) ;
166180
167- let mut cmd = Command :: new ( & interpreter_path ) ;
181+ let mut cmd = Command :: new ( & actual_interpreter_path ) ;
168182 cmd. args ( exec_args) ;
169183
170184 // Lie about the value of argv0 to hoodwink the interpreter as to its
171185 // location on Linux-based platforms.
172- if cfg ! ( target_os = "linux" ) {
173- cmd. arg0 ( & exe_path) ;
174- }
186+ cmd. arg0 ( & venv_interpreter_path) ;
175187
176188 // On MacOS however, there are facilities for asking the C runtime/OS
177189 // what the real name of the interpreter executable is, and that value
@@ -181,7 +193,7 @@ fn main() -> miette::Result<()> {
181193 // https://github.com/python/cpython/blob/68e72cf3a80362d0a2d57ff0c9f02553c378e537/Modules/getpath.c#L778
182194 // https://docs.python.org/3/using/cmdline.html#envvar-PYTHONEXECUTABLE
183195 if cfg ! ( target_os = "macos" ) {
184- cmd. env ( "PYTHONEXECUTABLE" , & exe_path ) ;
196+ cmd. env ( "PYTHONEXECUTABLE" , & venv_interpreter_path ) ;
185197 }
186198
187199 // Re-export the counter so it'll go up
0 commit comments