Always copy executable on Windows 3+ (#1977)
This commit is contained in:
parent
ced984abfd
commit
43a5e0383b
3 changed files with 28 additions and 31 deletions
|
|
@ -42,18 +42,19 @@ class CPythonPosix(CPython, PosixSupports):
|
|||
class CPythonWindows(CPython, WindowsSupports):
|
||||
@classmethod
|
||||
def _executables(cls, interpreter):
|
||||
executables = cls._win_executables(Path(interpreter.system_executable), interpreter, RefWhen.ANY)
|
||||
for src, targets, must, when in executables:
|
||||
yield src, targets, must, when
|
||||
|
||||
@classmethod
|
||||
def _win_executables(cls, host, interpreter, when):
|
||||
must = RefMust.COPY if interpreter.version_info.major == 2 else RefMust.NA
|
||||
# symlink of the python executables does not work reliably, copy always instead
|
||||
# - https://bugs.python.org/issue42013
|
||||
# - venv
|
||||
host = cls.host_python(interpreter)
|
||||
for path in (host.parent / n for n in {"python.exe", host.name}):
|
||||
yield host, [path.name], must, when
|
||||
yield host, [path.name], RefMust.COPY, RefWhen.ANY
|
||||
# for more info on pythonw.exe see https://stackoverflow.com/a/30313091
|
||||
python_w = host.parent / "pythonw.exe"
|
||||
yield python_w, [python_w.name], must, when
|
||||
yield python_w, [python_w.name], RefMust.COPY, RefWhen.ANY
|
||||
|
||||
@classmethod
|
||||
def host_python(cls, interpreter):
|
||||
return Path(interpreter.system_executable)
|
||||
|
||||
|
||||
def is_mac_os_framework(interpreter):
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
import abc
|
||||
from itertools import chain
|
||||
from textwrap import dedent
|
||||
|
||||
from six import add_metaclass
|
||||
|
||||
from virtualenv.create.describe import Python3Supports
|
||||
from virtualenv.create.via_global_ref.builtin.ref import PathRefToDest, RefMust, RefWhen
|
||||
from virtualenv.create.via_global_ref.builtin.ref import PathRefToDest
|
||||
from virtualenv.create.via_global_ref.store import is_store_python
|
||||
from virtualenv.util.path import Path
|
||||
|
||||
|
|
@ -56,29 +55,21 @@ class CPython3Windows(CPythonWindows, CPython3):
|
|||
def sources(cls, interpreter):
|
||||
for src in super(CPython3Windows, cls).sources(interpreter):
|
||||
yield src
|
||||
if cls.venv_37p(interpreter):
|
||||
for dll in (i for i in Path(interpreter.system_executable).parent.iterdir() if i.suffix == ".dll"):
|
||||
yield PathRefToDest(dll, cls.to_bin, RefMust.SYMLINK, RefWhen.SYMLINK)
|
||||
else:
|
||||
if not cls.venv_37p(interpreter):
|
||||
for src in cls.include_dll_and_pyd(interpreter):
|
||||
yield src
|
||||
|
||||
@classmethod
|
||||
def _executables(cls, interpreter):
|
||||
system_exe = Path(interpreter.system_executable)
|
||||
if cls.venv_37p(interpreter):
|
||||
# starting with CPython 3.7 Windows ships with a venvlauncher.exe that avoids the need for dll/pyd copies
|
||||
launcher = Path(interpreter.system_stdlib) / "venv" / "scripts" / "nt" / "python.exe"
|
||||
executables = cls._win_executables(launcher, interpreter, RefWhen.COPY)
|
||||
executables = chain(executables, cls._win_executables(system_exe, interpreter, RefWhen.SYMLINK))
|
||||
else:
|
||||
executables = cls._win_executables(system_exe, interpreter, RefWhen.ANY)
|
||||
for src, targets, must, when in executables:
|
||||
yield src, targets, must, when
|
||||
|
||||
@staticmethod
|
||||
def venv_37p(interpreter):
|
||||
return interpreter.version_info.minor > 6
|
||||
return interpreter.version_info.minor >= 7
|
||||
|
||||
@classmethod
|
||||
def host_python(cls, interpreter):
|
||||
if cls.venv_37p(interpreter):
|
||||
# starting with CPython 3.7 Windows ships with a venvlauncher.exe that avoids the need for dll/pyd copies
|
||||
# it also means the wrapper must be copied to avoid bugs such as https://bugs.python.org/issue42013
|
||||
return Path(interpreter.system_stdlib) / "venv" / "scripts" / "nt" / "python.exe"
|
||||
return super(CPython3Windows, cls).host_python(interpreter)
|
||||
|
||||
@classmethod
|
||||
def include_dll_and_pyd(cls, interpreter):
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ from abc import ABCMeta
|
|||
|
||||
from six import add_metaclass
|
||||
|
||||
from virtualenv.create.via_global_ref.builtin.ref import ExePathRefToDest, RefMust
|
||||
from virtualenv.create.via_global_ref.builtin.ref import ExePathRefToDest, RefMust, RefWhen
|
||||
from virtualenv.util.path import ensure_dir
|
||||
|
||||
from ..api import ViaGlobalRefApi, ViaGlobalRefMeta
|
||||
|
|
@ -89,7 +89,12 @@ class ViaGlobalRefVirtualenvBuiltin(ViaGlobalRefApi, VirtualenvBuiltin):
|
|||
try:
|
||||
self.enable_system_site_package = False
|
||||
for src in self._sources:
|
||||
src.run(self, self.symlinks)
|
||||
if (
|
||||
src.when == RefWhen.ANY
|
||||
or (src.when == RefWhen.SYMLINK and self.symlinks is True)
|
||||
or (src.when == RefWhen.COPY and self.symlinks is False)
|
||||
):
|
||||
src.run(self, self.symlinks)
|
||||
finally:
|
||||
if true_system_site != self.enable_system_site_package:
|
||||
self.enable_system_site_package = true_system_site
|
||||
|
|
|
|||
Loading…
Reference in a new issue