@@ -45,8 +45,11 @@ pub fn find_executable(env_path: &Path) -> Option<PathBuf> {
4545
4646pub fn find_executables < T : AsRef < Path > > ( env_path : T ) -> Vec < PathBuf > {
4747 let mut env_path = env_path. as_ref ( ) . to_path_buf ( ) ;
48- // Never find exes in `.pyenv/shims/` folder, they are not valid exes
49- if env_path. ends_with ( ".pyenv/shims" ) {
48+ // Never find exes in pyenv shims folder, they are not valid exes.
49+ // Pyenv can be installed at custom locations (e.g., ~/.pl/pyenv via PYENV_ROOT),
50+ // not just ~/.pyenv, so we check for any path ending with "shims" that has a
51+ // parent directory containing "pyenv".
52+ if is_pyenv_shims_dir ( & env_path) {
5053 return vec ! [ ] ;
5154 }
5255 let mut python_executables = vec ! [ ] ;
@@ -120,6 +123,29 @@ fn is_python_executable_name(exe: &Path) -> bool {
120123 }
121124}
122125
126+ /// Checks if the given path is a pyenv shims directory.
127+ /// Pyenv shims are not valid Python executables - they are wrapper scripts that
128+ /// redirect to the actual Python installation based on pyenv configuration.
129+ /// Pyenv can be installed at custom locations via PYENV_ROOT (e.g., ~/.pl/pyenv),
130+ /// not just the default ~/.pyenv location.
131+ fn is_pyenv_shims_dir ( path : & Path ) -> bool {
132+ // Must end with "shims"
133+ if !path. ends_with ( "shims" ) {
134+ return false ;
135+ }
136+
137+ // Check if parent directory name contains "pyenv" (case-insensitive)
138+ // This handles: ~/.pyenv/shims, ~/.pl/pyenv/shims, /opt/pyenv/shims, etc.
139+ if let Some ( parent) = path. parent ( ) {
140+ if let Some ( parent_name) = parent. file_name ( ) {
141+ if let Some ( name_str) = parent_name. to_str ( ) {
142+ return name_str. to_lowercase ( ) . contains ( "pyenv" ) ;
143+ }
144+ }
145+ }
146+ false
147+ }
148+
123149pub fn should_search_for_environments_in_path < P : AsRef < Path > > ( path : & P ) -> bool {
124150 // Never search in the .git folder
125151 // Never search in the node_modules folder
@@ -242,4 +268,42 @@ mod tests {
242268 PathBuf :: from( "pythonw3.exe" ) . as_path( )
243269 ) ) ;
244270 }
271+
272+ #[ test]
273+ fn test_is_pyenv_shims_dir ( ) {
274+ // Standard pyenv location
275+ assert ! ( is_pyenv_shims_dir(
276+ PathBuf :: from( "/home/user/.pyenv/shims" ) . as_path( )
277+ ) ) ;
278+
279+ // Custom pyenv location (issue #238)
280+ assert ! ( is_pyenv_shims_dir(
281+ PathBuf :: from( "/home/user/.pl/pyenv/shims" ) . as_path( )
282+ ) ) ;
283+
284+ // Other custom locations
285+ assert ! ( is_pyenv_shims_dir(
286+ PathBuf :: from( "/opt/pyenv/shims" ) . as_path( )
287+ ) ) ;
288+ assert ! ( is_pyenv_shims_dir(
289+ PathBuf :: from( "/usr/local/pyenv/shims" ) . as_path( )
290+ ) ) ;
291+
292+ // pyenv-win style (parent contains "pyenv")
293+ assert ! ( is_pyenv_shims_dir(
294+ PathBuf :: from( "/home/user/.pyenv/pyenv-win/shims" ) . as_path( )
295+ ) ) ;
296+
297+ // Not pyenv shims (should return false)
298+ assert ! ( !is_pyenv_shims_dir(
299+ PathBuf :: from( "/home/user/.pyenv/versions/3.10.0/bin" ) . as_path( )
300+ ) ) ;
301+ assert ! ( !is_pyenv_shims_dir( PathBuf :: from( "/usr/bin" ) . as_path( ) ) ) ;
302+ assert ! ( !is_pyenv_shims_dir(
303+ PathBuf :: from( "/home/user/shims" ) . as_path( )
304+ ) ) ; // "shims" but parent is not pyenv
305+ assert ! ( !is_pyenv_shims_dir(
306+ PathBuf :: from( "/home/user/project/shims" ) . as_path( )
307+ ) ) ;
308+ }
245309}
0 commit comments