fix subprocesses for windows + pyenv-win workarounds

This commit is contained in:
sklancher
2025-06-11 15:56:54 -05:00
parent 86bf3005a6
commit 6954ba9e88
2 changed files with 44 additions and 5 deletions
+3 -2
View File
@@ -147,7 +147,8 @@ def install_pyenv():
logger.error("pyenv install failed, exiting...")
return False
os.environ["PATH"] = f"{os.environ.get('PYENV_ROOT', os.path.expanduser('~/.pyenv'))}/bin:{os.environ['PATH']}"
if shutil.which("pyenv") is None:
which_pyenv = shutil.which("pyenv")
if which_pyenv is None:
logger.error("Could not find pyenv, exiting...")
return False
versions = click.prompt(
@@ -156,7 +157,7 @@ def install_pyenv():
default=supported_versions,
show_default=False,
)
if subprocess.run(["pyenv", "install", *map(str, versions)]).returncode != 0:
if subprocess.run([which_pyenv, "install", *map(str, versions)]).returncode != 0:
logger.error("Error installing Python versions, exiting...")
return False
return True
+41 -3
View File
@@ -2,8 +2,10 @@
import subprocess
import sys
import shlex
import py_compile
import platform
import os
import shutil
from pylingual.utils.version import PythonVersion
@@ -12,6 +14,9 @@ class CompileError(Exception):
success = False
class PyenvError(Exception):
pass
def compile_version(py_file, out_file, version):
py_file = str(py_file)
out_file = str(out_file)
@@ -22,8 +27,41 @@ def compile_version(py_file, out_file, version):
except py_compile.PyCompileError as e:
raise CompileError(str(e))
return
which_pyenv = shutil.which("pyenv")
version_win = None
if platform.system() == "Windows": # workaround for pyenv-win being bugged when passing versions like 3.x not 3.x.y
def try_get_version_patch(version_str) -> int | None:
try:
return int(version_str.split(".", 2)[2])
except IndexError:
return None
except ValueError:
return None
pyenv_versions_cmd = [which_pyenv, *"versions --bare".split()]
pyenv_versions_output = subprocess.run(pyenv_versions_cmd, shell=False, capture_output=True, text=True)
if pyenv_versions_output.stderr:
raise CompileError(pyenv_versions_output.stderr)
# get lastest pyenv version for the correct major.minor version
pyenv_version_strings = list(filter(lambda x: x.startswith(f"{version.as_str()}"), pyenv_versions_output.stdout.splitlines()))
if not any(x == version.as_str() for x in pyenv_version_strings):
pyenv_real_versions = list(
filter(lambda x: x is not None,
map(try_get_version_patch,
pyenv_version_strings
)
)
)
if len(pyenv_real_versions) == 0:
raise PyenvError(f"Could not find pyenv version for {version.as_str()}")
version_win = f"{version.as_str()}.{max(pyenv_real_versions)}"
compile_cmd = f"import py_compile, sys; assert sys.version_info[:2] == {version.as_tuple()!r}; py_compile.compile({py_file!r}, cfile={out_file!r})"
cmd = f"env PYENV_VERSION={version.as_str()} PYTHONWARNINGS=ignore pyenv exec python -c {shlex.quote(compile_cmd)}"
output = subprocess.run(cmd, shell=True, capture_output=True, text=True)
cmd = [which_pyenv, *"exec python -c".split(), compile_cmd]
output = subprocess.run(cmd, shell=False, capture_output=True, text=True, env={**os.environ, "PYENV_VERSION": version_win if version_win else version.as_str(), "PYTHONWARNINGS": "ignore"})
if output.stderr:
raise CompileError(output.stderr)