Adjust base Python lookup logic for Windows (#2121)

## Summary

When I install via the Windows Store, `interpreter.base_prefix` contains
a bunch of resolved information that leads to a broken environment.

Instead, we now use `sys._base_executable` on Windows by default,
falling back to `sys.base_prefix` if it doesn't exist. (There are some
issues with `sys.base_executable` that lead to complexity in
`virtualenv`, but they only affect POSIX.) Admittedly, I don't know when
`sys._base_executable` wouldn't exist. It exists in all the environments
I've tested.

Additionally, we use the system interpreter directly if we're outside of
a virtualenv.
This commit is contained in:
Charlie Marsh 2024-03-03 09:44:10 -08:00 committed by GitHub
parent d4f1973bdc
commit 46265b711b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 120 additions and 25 deletions

View file

@ -88,6 +88,7 @@ interpreter_info = {
"base_prefix": sys.base_prefix,
"base_exec_prefix": sys.base_exec_prefix,
"prefix": sys.prefix,
"base_executable": getattr(sys, "_base_executable", None),
"sys_executable": sys.executable,
"sysconfig_paths": sysconfig.get_paths(),
}

View file

@ -32,6 +32,7 @@ pub struct Interpreter {
prefix: PathBuf,
base_exec_prefix: PathBuf,
base_prefix: PathBuf,
base_executable: Option<PathBuf>,
sys_executable: PathBuf,
tags: OnceCell<Tags>,
}
@ -54,6 +55,7 @@ impl Interpreter {
prefix: info.prefix,
base_exec_prefix: info.base_exec_prefix,
base_prefix: info.base_prefix,
base_executable: info.base_executable,
sys_executable: info.sys_executable,
tags: OnceCell::new(),
})
@ -77,6 +79,7 @@ impl Interpreter {
prefix: PathBuf::from("/dev/null"),
base_exec_prefix: PathBuf::from("/dev/null"),
base_prefix: PathBuf::from("/dev/null"),
base_executable: None,
sys_executable: PathBuf::from("/dev/null"),
tags: OnceCell::new(),
}
@ -355,6 +358,12 @@ impl Interpreter {
&self.prefix
}
/// Return the `sys._base_executable` path for this Python interpreter. Some platforms do not
/// have this attribute, so it may be `None`.
pub fn base_executable(&self) -> Option<&Path> {
self.base_executable.as_deref()
}
/// Return the `sys.executable` path for this Python interpreter.
pub fn sys_executable(&self) -> &Path {
&self.sys_executable
@ -455,6 +464,7 @@ struct InterpreterInfo {
prefix: PathBuf,
base_exec_prefix: PathBuf,
base_prefix: PathBuf,
base_executable: Option<PathBuf>,
sys_executable: PathBuf,
}