Skip to content

Commit

Permalink
Fix: executables creation in Windows PyPy <= 3.6
Browse files Browse the repository at this point in the history
Also passes unit tests in test_creator.py
  • Loading branch information
reksar authored and gaborbernat committed Jun 24, 2022
1 parent 43753c2 commit fad7d33
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 6 deletions.
3 changes: 2 additions & 1 deletion .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ source =
src
.tox/*/lib/python*/site-packages
.tox/pypy*/site-packages
.tox\*\Lib\site-packages\
.tox\*\Lib\site-packages
.tox\py\site-packages
*/src
*\src
Expand Down
8 changes: 7 additions & 1 deletion src/virtualenv/create/creator.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,13 @@ def get_env_debug_info(env_exe, debug_script, app_data, env):
# noinspection PyBroadException
try:
if code != 0:
result = literal_eval(out)
if out:
result = literal_eval(out)
else:
if code == 2 and "file" in err:
# Re-raise FileNotFoundError from `run_cmd()`
raise OSError(err)
raise Exception(err)
else:
result = json.loads(out)
if err:
Expand Down
9 changes: 7 additions & 2 deletions src/virtualenv/create/via_global_ref/builtin/pypy/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ def _executables(cls, interpreter):
must = RefMust.COPY if interpreter.version_info.major == 2 else RefMust.NA
yield host, targets, must, RefWhen.ANY

@classmethod
def executables(cls, interpreter):
for src in super(PyPy, cls).sources(interpreter):
yield src

@classmethod
def exe_names(cls, interpreter):
return {
Expand All @@ -34,8 +39,8 @@ def exe_names(cls, interpreter):

@classmethod
def sources(cls, interpreter):
for src in super(PyPy, cls).sources(interpreter):
yield src
for exe in cls.executables(interpreter):
yield exe
for host in cls._add_shared_libs(interpreter):
yield PathRefToDest(host, dest=lambda self, s: self.bin_dir / s.name)

Expand Down
6 changes: 6 additions & 0 deletions src/virtualenv/create/via_global_ref/builtin/pypy/pypy3.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,15 @@ def sources(cls, interpreter):
class Pypy3Windows(PyPy3, WindowsSupports):
"""PyPy 3 on Windows"""

@property
def less_v37(self):
return self.interpreter.version_info.minor < 7

@property
def stdlib(self):
"""PyPy3 respects sysconfig only for the host python, virtual envs is instead Lib/site-packages"""
if self.less_v37:
return self.dest / "site-packages"
return self.dest / "Lib" / "site-packages"

@property
Expand Down
13 changes: 13 additions & 0 deletions src/virtualenv/create/via_global_ref/venv.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from virtualenv.util.subprocess import run_cmd

from .api import ViaGlobalRefApi, ViaGlobalRefMeta
from .builtin.pypy.pypy3 import Pypy3Windows


class Venv(ViaGlobalRefApi):
Expand Down Expand Up @@ -41,6 +42,18 @@ def create(self):
for lib in self.libs:
ensure_dir(lib)
super(Venv, self).create()
self.executables_for_win_pypy_less_v37()

def executables_for_win_pypy_less_v37(self):
"""
PyPy <= 3.6 (v7.3.3) for Windows contains only pypy3.exe and pypy3w.exe
Venv does not handle non-existing exe sources, e.g. python.exe, so this
patch does it.
"""
creator = self.describe
if isinstance(creator, Pypy3Windows) and creator.less_v37:
for exe in creator.executables(self.interpreter):
exe.run(creator, self.symlinks)

def create_inline(self):
from venv import EnvBuilder
Expand Down
7 changes: 5 additions & 2 deletions src/virtualenv/util/subprocess/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,11 @@ def run_cmd(cmd):
)
out, err = process.communicate() # input disabled
code = process.returncode
except OSError as os_error:
code, out, err = os_error.errno, "", os_error.strerror
except OSError as error:
code, out, err = error.errno, "", error.strerror
if code == 2 and "file" in err:
# FileNotFoundError in Python >= 3.3
err = str(error)
return code, out, err


Expand Down

0 comments on commit fad7d33

Please sign in to comment.