mirror of
https://github.com/python/cpython.git
synced 2025-10-10 00:43:41 +00:00
bpo-35872 and bpo-35873: Clears __PYVENV_LAUNCHER__ variable (GH-11745)
After reading __PYVENV_LAUNCHER__ we now set sys._base_executable value for later use. Make the same changes for macOS to avoid extra platform checks.
This commit is contained in:
parent
2f6fae6e51
commit
a8474d025c
7 changed files with 33 additions and 23 deletions
|
@ -19,6 +19,13 @@ WINEXE = (sys.platform == 'win32' and getattr(sys, 'frozen', False))
|
||||||
WINSERVICE = sys.executable.lower().endswith("pythonservice.exe")
|
WINSERVICE = sys.executable.lower().endswith("pythonservice.exe")
|
||||||
|
|
||||||
|
|
||||||
|
def _path_eq(p1, p2):
|
||||||
|
return p1 == p2 or os.path.normcase(p1) == os.path.normcase(p2)
|
||||||
|
|
||||||
|
WINENV = (hasattr(sys, '_base_executable') and
|
||||||
|
not _path_eq(sys.executable, sys._base_executable))
|
||||||
|
|
||||||
|
|
||||||
def _close_handles(*handles):
|
def _close_handles(*handles):
|
||||||
for handle in handles:
|
for handle in handles:
|
||||||
_winapi.CloseHandle(handle)
|
_winapi.CloseHandle(handle)
|
||||||
|
@ -50,12 +57,23 @@ class Popen(object):
|
||||||
pipe_handle=rhandle)
|
pipe_handle=rhandle)
|
||||||
cmd = ' '.join('"%s"' % x for x in cmd)
|
cmd = ' '.join('"%s"' % x for x in cmd)
|
||||||
|
|
||||||
|
python_exe = spawn.get_executable()
|
||||||
|
|
||||||
|
# bpo-35797: When running in a venv, we bypass the redirect
|
||||||
|
# executor and launch our base Python.
|
||||||
|
if WINENV and _path_eq(python_exe, sys.executable):
|
||||||
|
python_exe = sys._base_executable
|
||||||
|
env = os.environ.copy()
|
||||||
|
env["__PYVENV_LAUNCHER__"] = sys.executable
|
||||||
|
else:
|
||||||
|
env = None
|
||||||
|
|
||||||
with open(wfd, 'wb', closefd=True) as to_child:
|
with open(wfd, 'wb', closefd=True) as to_child:
|
||||||
# start process
|
# start process
|
||||||
try:
|
try:
|
||||||
hp, ht, pid, tid = _winapi.CreateProcess(
|
hp, ht, pid, tid = _winapi.CreateProcess(
|
||||||
spawn.get_executable(), cmd,
|
python_exe, cmd,
|
||||||
None, None, False, 0, None, None, None)
|
env, None, False, 0, None, None, None)
|
||||||
_winapi.CloseHandle(ht)
|
_winapi.CloseHandle(ht)
|
||||||
except:
|
except:
|
||||||
_winapi.CloseHandle(rhandle)
|
_winapi.CloseHandle(rhandle)
|
||||||
|
|
|
@ -29,19 +29,12 @@ __all__ = ['_main', 'freeze_support', 'set_executable', 'get_executable',
|
||||||
if sys.platform != 'win32':
|
if sys.platform != 'win32':
|
||||||
WINEXE = False
|
WINEXE = False
|
||||||
WINSERVICE = False
|
WINSERVICE = False
|
||||||
_WINENV = False
|
|
||||||
else:
|
else:
|
||||||
WINEXE = getattr(sys, 'frozen', False)
|
WINEXE = getattr(sys, 'frozen', False)
|
||||||
WINSERVICE = sys.executable.lower().endswith("pythonservice.exe")
|
WINSERVICE = sys.executable.lower().endswith("pythonservice.exe")
|
||||||
_WINENV = '__PYVENV_LAUNCHER__' in os.environ
|
|
||||||
|
|
||||||
if WINSERVICE:
|
if WINSERVICE:
|
||||||
_python_exe = os.path.join(sys.exec_prefix, 'python.exe')
|
_python_exe = os.path.join(sys.exec_prefix, 'python.exe')
|
||||||
elif _WINENV:
|
|
||||||
# bpo-35797: When running in a venv, we need to bypass the redirect
|
|
||||||
# executor and launch our base Python.
|
|
||||||
import _winapi
|
|
||||||
_python_exe = _winapi.GetModuleFileName(0)
|
|
||||||
else:
|
else:
|
||||||
_python_exe = sys.executable
|
_python_exe = sys.executable
|
||||||
|
|
||||||
|
|
|
@ -457,7 +457,14 @@ def venv(known_paths):
|
||||||
|
|
||||||
env = os.environ
|
env = os.environ
|
||||||
if sys.platform == 'darwin' and '__PYVENV_LAUNCHER__' in env:
|
if sys.platform == 'darwin' and '__PYVENV_LAUNCHER__' in env:
|
||||||
executable = os.environ['__PYVENV_LAUNCHER__']
|
executable = sys._base_executable = os.environ['__PYVENV_LAUNCHER__']
|
||||||
|
elif sys.platform == 'win32' and '__PYVENV_LAUNCHER__' in env:
|
||||||
|
executable = sys.executable
|
||||||
|
import _winapi
|
||||||
|
sys._base_executable = _winapi.GetModuleFileName(0)
|
||||||
|
# bpo-35873: Clear the environment variable to avoid it being
|
||||||
|
# inherited by child processes.
|
||||||
|
del os.environ['__PYVENV_LAUNCHER__']
|
||||||
else:
|
else:
|
||||||
executable = sys.executable
|
executable = sys.executable
|
||||||
exe_dir, _ = os.path.split(os.path.abspath(executable))
|
exe_dir, _ = os.path.split(os.path.abspath(executable))
|
||||||
|
|
|
@ -52,10 +52,7 @@ class BaseTest(unittest.TestCase):
|
||||||
self.bindir = 'bin'
|
self.bindir = 'bin'
|
||||||
self.lib = ('lib', 'python%d.%d' % sys.version_info[:2])
|
self.lib = ('lib', 'python%d.%d' % sys.version_info[:2])
|
||||||
self.include = 'include'
|
self.include = 'include'
|
||||||
if sys.platform == 'darwin' and '__PYVENV_LAUNCHER__' in os.environ:
|
executable = getattr(sys, '_base_executable', sys.executable)
|
||||||
executable = os.environ['__PYVENV_LAUNCHER__']
|
|
||||||
else:
|
|
||||||
executable = sys.executable
|
|
||||||
self.exe = os.path.split(executable)[-1]
|
self.exe = os.path.split(executable)[-1]
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
|
@ -100,11 +97,7 @@ class BasicTest(BaseTest):
|
||||||
else:
|
else:
|
||||||
self.assertFalse(os.path.exists(p))
|
self.assertFalse(os.path.exists(p))
|
||||||
data = self.get_text_file_contents('pyvenv.cfg')
|
data = self.get_text_file_contents('pyvenv.cfg')
|
||||||
if sys.platform == 'darwin' and ('__PYVENV_LAUNCHER__'
|
executable = getattr(sys, '_base_executable', sys.executable)
|
||||||
in os.environ):
|
|
||||||
executable = os.environ['__PYVENV_LAUNCHER__']
|
|
||||||
else:
|
|
||||||
executable = sys.executable
|
|
||||||
path = os.path.dirname(executable)
|
path = os.path.dirname(executable)
|
||||||
self.assertIn('home = %s' % path, data)
|
self.assertIn('home = %s' % path, data)
|
||||||
fn = self.get_env_file(self.bindir, self.exe)
|
fn = self.get_env_file(self.bindir, self.exe)
|
||||||
|
|
|
@ -106,10 +106,7 @@ class EnvBuilder:
|
||||||
context.prompt = '(%s) ' % prompt
|
context.prompt = '(%s) ' % prompt
|
||||||
create_if_needed(env_dir)
|
create_if_needed(env_dir)
|
||||||
env = os.environ
|
env = os.environ
|
||||||
if sys.platform == 'darwin' and '__PYVENV_LAUNCHER__' in env:
|
executable = getattr(sys, '_base_executable', sys.executable)
|
||||||
executable = os.environ['__PYVENV_LAUNCHER__']
|
|
||||||
else:
|
|
||||||
executable = sys.executable
|
|
||||||
dirname, exename = os.path.split(os.path.abspath(executable))
|
dirname, exename = os.path.split(os.path.abspath(executable))
|
||||||
context.executable = executable
|
context.executable = executable
|
||||||
context.python_dir = dirname
|
context.python_dir = dirname
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Prevents venv paths being inherited by child processes
|
|
@ -0,0 +1 @@
|
||||||
|
Uses the base Python executable when invoking venv in a virtual environment
|
Loading…
Add table
Add a link
Reference in a new issue