diff options
author | Steve Dower <steve.dower@python.org> | 2019-06-29 17:34:11 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-06-29 17:34:11 (GMT) |
commit | 9048c49322a5229ff99610aba35913ffa295ebb7 (patch) | |
tree | caad6f4a3b44e547208ac70cc1746c4df349ac8f /Lib/venv | |
parent | 80097e089ba22a42d804e65fbbcf35e5e49eed00 (diff) | |
download | cpython-9048c49322a5229ff99610aba35913ffa295ebb7.zip cpython-9048c49322a5229ff99610aba35913ffa295ebb7.tar.gz cpython-9048c49322a5229ff99610aba35913ffa295ebb7.tar.bz2 |
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
Diffstat (limited to 'Lib/venv')
-rw-r--r-- | Lib/venv/__init__.py | 93 |
1 files changed, 56 insertions, 37 deletions
diff --git a/Lib/venv/__init__.py b/Lib/venv/__init__.py index b64125f..4ab9cc6 100644 --- a/Lib/venv/__init__.py +++ b/Lib/venv/__init__.py @@ -112,7 +112,7 @@ class EnvBuilder: prompt = self.prompt if self.prompt is not None else context.env_name context.prompt = '(%s) ' % prompt create_if_needed(env_dir) - executable = getattr(sys, '_base_executable', sys.executable) + executable = sys._base_executable dirname, exename = os.path.split(os.path.abspath(executable)) context.executable = executable context.python_dir = dirname @@ -163,47 +163,66 @@ class EnvBuilder: if self.prompt is not None: f.write(f'prompt = {self.prompt!r}\n') - def symlink_or_copy(self, src, dst, relative_symlinks_ok=False): - """ - Try symlinking a file, and if that fails, fall back to copying. - """ - force_copy = not self.symlinks - if not force_copy: - try: - if not os.path.islink(dst): # can't link to itself! + if os.name != 'nt': + def symlink_or_copy(self, src, dst, relative_symlinks_ok=False): + """ + Try symlinking a file, and if that fails, fall back to copying. + """ + force_copy = not self.symlinks + if not force_copy: + try: + if not os.path.islink(dst): # can't link to itself! + if relative_symlinks_ok: + assert os.path.dirname(src) == os.path.dirname(dst) + os.symlink(os.path.basename(src), dst) + else: + os.symlink(src, dst) + except Exception: # may need to use a more specific exception + logger.warning('Unable to symlink %r to %r', src, dst) + force_copy = True + if force_copy: + shutil.copyfile(src, dst) + else: + def symlink_or_copy(self, src, dst, relative_symlinks_ok=False): + """ + Try symlinking a file, and if that fails, fall back to copying. + """ + bad_src = os.path.lexists(src) and not os.path.exists(src) + if self.symlinks and not bad_src and not os.path.islink(dst): + try: if relative_symlinks_ok: assert os.path.dirname(src) == os.path.dirname(dst) os.symlink(os.path.basename(src), dst) else: os.symlink(src, dst) - except Exception: # may need to use a more specific exception - logger.warning('Unable to symlink %r to %r', src, dst) - force_copy = True - if force_copy: - if os.name == 'nt': - # On Windows, we rewrite symlinks to our base python.exe into - # copies of venvlauncher.exe - basename, ext = os.path.splitext(os.path.basename(src)) - srcfn = os.path.join(os.path.dirname(__file__), - "scripts", - "nt", - basename + ext) - # Builds or venv's from builds need to remap source file - # locations, as we do not put them into Lib/venv/scripts - if sysconfig.is_python_build(True) or not os.path.isfile(srcfn): - if basename.endswith('_d'): - ext = '_d' + ext - basename = basename[:-2] - if basename == 'python': - basename = 'venvlauncher' - elif basename == 'pythonw': - basename = 'venvwlauncher' - src = os.path.join(os.path.dirname(src), basename + ext) - else: - src = srcfn - if not os.path.exists(src): - logger.warning('Unable to copy %r', src) return + except Exception: # may need to use a more specific exception + logger.warning('Unable to symlink %r to %r', src, dst) + + # On Windows, we rewrite symlinks to our base python.exe into + # copies of venvlauncher.exe + basename, ext = os.path.splitext(os.path.basename(src)) + srcfn = os.path.join(os.path.dirname(__file__), + "scripts", + "nt", + basename + ext) + # Builds or venv's from builds need to remap source file + # locations, as we do not put them into Lib/venv/scripts + if sysconfig.is_python_build(True) or not os.path.isfile(srcfn): + if basename.endswith('_d'): + ext = '_d' + ext + basename = basename[:-2] + if basename == 'python': + basename = 'venvlauncher' + elif basename == 'pythonw': + basename = 'venvwlauncher' + src = os.path.join(os.path.dirname(src), basename + ext) + else: + src = srcfn + if not os.path.exists(src): + if not bad_src: + logger.warning('Unable to copy %r', src) + return shutil.copyfile(src, dst) @@ -251,7 +270,7 @@ class EnvBuilder: for suffix in suffixes: src = os.path.join(dirname, suffix) - if os.path.exists(src): + if os.path.lexists(src): copier(src, os.path.join(binpath, suffix)) if sysconfig.is_python_build(True): |