From df5372511c5c350ede63403234fac8236913d651 Mon Sep 17 00:00:00 2001 From: native-api Date: Thu, 24 Sep 2026 07:23:52 +0300 Subject: [PATCH] python-build: create pypy* symlinks for PyPy (#3562) Source and some older versions builds do not create them --- plugins/python-build/bin/python-build | 37 ++++++++++++++++++------ plugins/python-build/test/pyenv_ext.bats | 9 +++--- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/plugins/python-build/bin/python-build b/plugins/python-build/bin/python-build index 34e6ab28..7a6dce8f 100755 --- a/plugins/python-build/bin/python-build +++ b/plugins/python-build/bin/python-build @@ -1002,18 +1002,24 @@ build_package_pyston() { build_package_copy # Pyston tarballs provide an executable with a version-specific naming scheme # and `pyston` and `pyston3` symlinks to it. - build_package_make_python_symlinks pyston + make_python_symlinks pyston } # Add missing `python', `pythonX' and `pythonX.Y' symlinks as per PEP 394. -build_package_make_python_symlinks() { - seeder="${1:?}" - local real_interpreter version_suffix - real_interpreter=$(resolve_link "${PREFIX_PATH}/bin/$seeder" || echo $seeder) +make_python_symlinks() { + local seeder_basename version_suffix real_interpreter + local -a interpreter_names + seeder_basename="${1:?}"; shift + (($#)) && interpreter_names=("$@") || interpreter_names=(python) + + local real_interpreter + real_interpreter=$(resolve_link "${PREFIX_PATH}/bin/$seeder_basename" || echo $seeder_basename) # Use syntax accepted in both Py2 and Py3. Even though current Py2 holdouts (e.g. PyPy) support e.g. print() - version_suffix=$("${PREFIX_PATH}/bin/$seeder" -c 'import sys; sys.stdout.write("%d.%d\n" % sys.version_info[:2])' 2>&4) - for name in python "python${version_suffix%.*}" "python${version_suffix}"; do - [[ -e "${PREFIX_PATH}/bin/$name" ]] || ln -fs "${real_interpreter}" "${PREFIX_PATH}/bin/$name" + version_suffix=$("${PREFIX_PATH}/bin/$seeder_basename" -c 'import sys; sys.stdout.write("%d.%d\n" % sys.version_info[:2])') + for interpreter_name in "${interpreter_names[@]}"; do + for name in "$interpreter_name" "$interpreter_name${version_suffix%.*}" "$interpreter_name${version_suffix}"; do + [[ -e "${PREFIX_PATH}/bin/$name" ]] || ln -fs "${real_interpreter}" "${PREFIX_PATH}/bin/$name" + done done } @@ -1122,8 +1128,21 @@ build_package_pypy() { ln -fs "../bin/${bin##*/}" "${PREFIX_PATH}/lib/${bin##*/}" fi done + + # PyPy source builds may create only a pypy* executable with a version-sepecific name + local seeder= seeder_candidate + for seeder_candidate in "${PREFIX_PATH}/bin/"pypy*; do + if [[ -f $seeder_candidate && -x $seeder_candidate ]]; then + seeder="${seeder_candidate##*/}" + break + fi + done shopt -u nullglob - build_package_make_python_symlinks "pypy" + [[ -n $seeder ]] || { + echo "python-build: Cannot find a valid PyPy executable in \`${PREFIX_PATH}/bin'" >&4 + exit 1 + } + make_python_symlinks "$seeder" pypy python } build_package_pypy_builder() { diff --git a/plugins/python-build/test/pyenv_ext.bats b/plugins/python-build/test/pyenv_ext.bats index 1a9c94bf..4d5b1871 100644 --- a/plugins/python-build/test/pyenv_ext.bats +++ b/plugins/python-build/test/pyenv_ext.bats @@ -264,14 +264,13 @@ OUT done } -@test "pypy: create python* symlinks" { +@test "pypy: create pypy* and python* symlinks" { mkdir -p "${BATS_TEST_TMPDIR}/pypy/bin" cd "${BATS_TEST_TMPDIR}/pypy" - executable bin/real_interpreter_name <