Skip to content

Commit

Permalink
Try alternate filenames for system_executable
Browse files Browse the repository at this point in the history
The value of `sys._base_executable` may not be a real file due to
changes made in CPython 3.11. The value is derived from the current
executable name and the "home" key from pyvenv.cfg.

On POSIX systems, virtual environments deploy "python" for use within
the venv however CPython's `make install` and a number of distributions
do not provide a system "python" in part because of PEP 394.

Virtualenv exposes this via `PythonInfo.system_executable` and can
encounter issues when attempting to execute a non-existent file.

Attempt to fallback to "python<MAJOR>" and "python<MAJOR>.<MINOR>" if
"python" does not exist.

Signed-off-by: Vincent Fazio <vfazio@xes-inc.com>
  • Loading branch information
vfazio committed Nov 7, 2022
1 parent 1e90b97 commit 36c7ed5
Showing 1 changed file with 14 additions and 0 deletions.
14 changes: 14 additions & 0 deletions src/virtualenv/discovery/py_info.py
Expand Up @@ -138,6 +138,20 @@ def _fast_get_system_executable(self):
base_executable = getattr(sys, "_base_executable", None) # some platforms may set this to help us
if base_executable is not None: # use the saved system executable if present
if sys.executable != base_executable: # we know we're in a virtual environment, cannot be us
# Do light validation for non-Windows virtual environments
# Some installs/distributions do not provide a version-less "python" binary (PEP 394).
# Try to fallback to an alternative based on version number
# This should still be relatively fast since it's just a couple of `stat` calls
if self.os != "nt" and (self.version_info.major, self.version_info.minor) >= (3, 11):
if not os.path.exists(base_executable):
major, minor = self.version_info.major, self.version_info.minor
base_dir = os.path.dirname(base_executable)
for candidate in [
os.path.join(base_dir, f"python{v}") for v in (major, f"{major}.{minor}")
]:
if os.path.exists(candidate):
base_executable = candidate
break
return base_executable
return None # in this case we just can't tell easily without poking around FS and calling them, bail
# if we're not in a virtual environment, this is already a system python, so return the original executable
Expand Down

0 comments on commit 36c7ed5

Please sign in to comment.