bpo-37369: Fix initialization of sys members when launched via an app container (GH-14428)

sys._base_executable is now always defined on all platforms, and can be overridden through configuration.
Also adds test.support.PythonSymlink to encapsulate platform-specific logic for symlinking sys.executable
This commit is contained in:
Steve Dower 2019-06-29 10:34:11 -07:00 committed by GitHub
parent 80097e089b
commit 9048c49322
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 410 additions and 277 deletions

View file

@ -28,8 +28,8 @@ except ImportError:
# Platforms that set sys._base_executable can create venvs from within
# another venv, so no need to skip tests that require venv.create().
requireVenvCreate = unittest.skipUnless(
hasattr(sys, '_base_executable')
or sys.prefix == sys.base_prefix,
sys.prefix == sys.base_prefix
or sys._base_executable != sys.executable,
'cannot run venv.create from within a venv on this platform')
def check_output(cmd, encoding=None):
@ -57,8 +57,14 @@ class BaseTest(unittest.TestCase):
self.bindir = 'bin'
self.lib = ('lib', 'python%d.%d' % sys.version_info[:2])
self.include = 'include'
executable = getattr(sys, '_base_executable', sys.executable)
executable = sys._base_executable
self.exe = os.path.split(executable)[-1]
if (sys.platform == 'win32'
and os.path.lexists(executable)
and not os.path.exists(executable)):
self.cannot_link_exe = True
else:
self.cannot_link_exe = False
def tearDown(self):
rmtree(self.env_dir)
@ -102,7 +108,7 @@ class BasicTest(BaseTest):
else:
self.assertFalse(os.path.exists(p))
data = self.get_text_file_contents('pyvenv.cfg')
executable = getattr(sys, '_base_executable', sys.executable)
executable = sys._base_executable
path = os.path.dirname(executable)
self.assertIn('home = %s' % path, data)
fn = self.get_env_file(self.bindir, self.exe)
@ -158,10 +164,6 @@ class BasicTest(BaseTest):
"""
Test that the prefix values are as expected.
"""
#check our prefixes
self.assertEqual(sys.base_prefix, sys.prefix)
self.assertEqual(sys.base_exec_prefix, sys.exec_prefix)
# check a venv's prefixes
rmtree(self.env_dir)
self.run_with_capture(venv.create, self.env_dir)
@ -169,9 +171,9 @@ class BasicTest(BaseTest):
cmd = [envpy, '-c', None]
for prefix, expected in (
('prefix', self.env_dir),
('prefix', self.env_dir),
('base_prefix', sys.prefix),
('base_exec_prefix', sys.exec_prefix)):
('exec_prefix', self.env_dir),
('base_prefix', sys.base_prefix),
('base_exec_prefix', sys.base_exec_prefix)):
cmd[2] = 'import sys; print(sys.%s)' % prefix
out, err = check_output(cmd)
self.assertEqual(out.strip(), expected.encode())
@ -283,7 +285,12 @@ class BasicTest(BaseTest):
# symlinked to 'python3.3' in the env, even when symlinking in
# general isn't wanted.
if usl:
self.assertTrue(os.path.islink(fn))
if self.cannot_link_exe:
# Symlinking is skipped when our executable is already a
# special app symlink
self.assertFalse(os.path.islink(fn))
else:
self.assertTrue(os.path.islink(fn))
# If a venv is created from a source build and that venv is used to
# run the test, the pyvenv.cfg in the venv created in the test will