From 2018c23555f7d1f3ba7b668dcceca9f8ef48122f Mon Sep 17 00:00:00 2001 From: ckl Date: Fri, 11 Jun 2021 16:39:02 -0700 Subject: [PATCH] Use pyenv to manage multiple Python versions. PiperOrigin-RevId: 378973310 (cherry picked from commit 6b1ddd948be1e36f46f1d91c7ee6c13058049a57) --- python/setup.py | 5 ++ python/tools/distribution/create_release.sh | 73 +++++++++++++++++---- 2 files changed, 67 insertions(+), 11 deletions(-) diff --git a/python/setup.py b/python/setup.py index 994923522e..e27d7e6c28 100644 --- a/python/setup.py +++ b/python/setup.py @@ -194,6 +194,11 @@ def bazel_build(self, ext): if not os.path.exists(self.build_temp): os.makedirs(self.build_temp) + # Ensure no artifacts from previous builds are reused (i.e. from builds + # using a different Python version). + bazel_clean_argv = [bazel, 'clean', '--expunge'] + self.spawn(bazel_clean_argv) + bazel_argv = [ bazel, 'build', ext.bazel_target, '--compilation_mode=' + ('dbg' if self.debug else 'opt'), diff --git a/python/tools/distribution/create_release.sh b/python/tools/distribution/create_release.sh index 80a7cca7c0..bad62e975d 100755 --- a/python/tools/distribution/create_release.sh +++ b/python/tools/distribution/create_release.sh @@ -14,7 +14,6 @@ # limitations under the License. ################################################################################ - # This script creates the release artifacts of Tink Python which includes a # source distribution and binary wheels for Linux and macOS. All Python tests # are exectued for each binary wheel and the source distribution. @@ -29,7 +28,11 @@ PYTHON_VERSIONS+=("3.8") readonly PYTHON_VERSIONS readonly PLATFORM="$(uname | tr '[:upper:]' '[:lower:]')" + readonly TINK_SRC_PATH="${PWD}/.." +readonly TINK_VERSION="$(grep ^TINK "${TINK_SRC_PATH}/tink_version.bzl" \ + | awk '{gsub(/"/, "", $3); print $3}')" + readonly IMAGE_NAME="quay.io/pypa/manylinux2014_x86_64" readonly IMAGE_DIGEST="sha256:d4604fe14cb0d691031f202ee7daf240e6d463297b060e2de60994d82a8f22ac" readonly IMAGE="${IMAGE_NAME}@${IMAGE_DIGEST}" @@ -37,6 +40,11 @@ readonly IMAGE="${IMAGE_NAME}@${IMAGE_DIGEST}" build_linux() { echo "### Building Linux binary wheels ###" + if [[ -n "${KOKORO_ROOT}" ]] ; then + eval "$(pyenv init -)" + pyenv versions + fi + mkdir -p release # Use signatures for getting images from registry (see @@ -47,20 +55,27 @@ build_linux() { docker run --volume "${TINK_SRC_PATH}:/tmp/tink" --workdir /tmp/tink/python \ "${IMAGE}" /tmp/tink/python/tools/distribution/build_linux_binary_wheels.sh - # Test binary wheels. + ## Test binary wheels. docker run --volume "${TINK_SRC_PATH}:/tmp/tink" --workdir /tmp/tink/python \ "${IMAGE}" /tmp/tink/python/tools/distribution/test_linux_binary_wheels.sh - # Build source wheels. - pip3 install wheel + echo "### Building Linux source distribution ###" + local sorted=( $( echo "${PYTHON_VERSIONS[@]}" \ + | xargs -n1 | sort -V | xargs ) ) + local latest="${sorted[${#sorted[@]}-1]}" + enable_py_version "${latest}" + + # Build source distribution. export TINK_PYTHON_SETUPTOOLS_OVERRIDE_BASE_PATH="${TINK_SRC_PATH}" - # TODO(ckl): Is sudo necessary? - sudo python3 setup.py sdist - cp dist/*.tar.gz release/ + python3 setup.py sdist + local sdist_filename="tink-${TINK_VERSION}.tar.gz" + set_owner_within_tar "dist/${sdist_filename}" + cp "dist/${sdist_filename}" release/ - # Test install from source wheel + # Test install from source distribution. + python3 --version pip3 list - pip3 install release/*.tar.gz + pip3 install -v "release/${sdist_filename}" pip3 list find tink/ -not -path "*cc/pybind*" -type f -name "*_test.py" -print0 \ | xargs -0 -n1 python3 @@ -69,16 +84,52 @@ build_linux() { build_macos() { echo "### Building macOS binary wheels ###" + mkdir -p release + for v in "${PYTHON_VERSIONS[@]}"; do + enable_py_version "${v}" + # Build binary wheel. - local pip_command="pip${v}" - ${pip_command} wheel . + pip3 wheel -w release . # Test binary wheel. # TODO(ckl): Implement test. done } +enable_py_version() { + # A partial version number (e.g. "3.9"). + local partial_version="$1" + + # The latest installed Python version that matches the partial version number + # (e.g. "3.9.5"). + local version="$(pyenv versions --bare | grep "${partial_version}" | tail -1)" + + # Set current Python version via environment variable. + pyenv shell "${version}" + + # Update environment. + pip3 install --upgrade pip + pip3 install --upgrade setuptools + pip3 install --upgrade wheel +} + +# setuptools does not replicate the distutils feature of explicitly setting +# user/group ownership on the files within the source distribution archive. +# +# This function is an easy workaround that doesn't require monkey-patching +# setuptools. This behavior is desired to produce deterministic release +# artifacts. +set_owner_within_tar() { + local tar_file="$1" + local tmp_dir="$(mktemp -d tink-py-tar-XXXXXX)" + tar -C "${tmp_dir}" -xzf "${tar_file}" + local tink_dir="$(basename $(ls -d ${tmp_dir}/tink*))" + tar -C "${tmp_dir}" -czf "${tar_file}" \ + --owner=root --group=root "${tink_dir}" + rm -r "${tmp_dir}" +} + main() { if [[ "${PLATFORM}" == 'linux' ]]; then build_linux