From f671cb4dbb84e5e575757bdf9c053ee797863eae Mon Sep 17 00:00:00 2001 From: Elvis Pranskevichus Date: Sat, 7 Aug 2021 10:46:53 -0700 Subject: [PATCH] Use cibuildwheel to build wheels (#70) The cibuildwheel infra seems to be mature enough, so use it for the wheel-building step instead of the homegrown setup. This gives us 32-bit and ARM wheels for free. Fixes: #44 Fixes: #63 --- .github/workflows/build-manylinux-wheels.sh | 28 ------- .github/workflows/release.yml | 83 ++++++++------------- .github/workflows/tests.yml | 2 + .gitignore | 1 + tests/test_mypy.py | 45 +++++------ 5 files changed, 59 insertions(+), 100 deletions(-) delete mode 100755 .github/workflows/build-manylinux-wheels.sh diff --git a/.github/workflows/build-manylinux-wheels.sh b/.github/workflows/build-manylinux-wheels.sh deleted file mode 100755 index 0fdaf575..00000000 --- a/.github/workflows/build-manylinux-wheels.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash - -set -e -x - -PY_MAJOR=${PYTHON_VERSION%%.*} -PY_MINOR=${PYTHON_VERSION#*.} - -ML_PYTHON_VERSION="cp${PY_MAJOR}${PY_MINOR}-cp${PY_MAJOR}${PY_MINOR}" -if [ "${PY_MAJOR}" -lt "4" -a "${PY_MINOR}" -lt "8" ]; then - ML_PYTHON_VERSION+="m" -fi - -# Temporary workaround for https://github.com/actions/runner/issues/781 -export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib - -# Compile wheels -PYTHON="/opt/python/${ML_PYTHON_VERSION}/bin/python" -PIP="/opt/python/${ML_PYTHON_VERSION}/bin/pip" -"${PIP}" install --upgrade setuptools pip wheel -cd "${GITHUB_WORKSPACE}" -make clean -"${PYTHON}" setup.py bdist_wheel - -# Bundle external shared libraries into the wheels. -for whl in "${GITHUB_WORKSPACE}"/dist/*.whl; do - auditwheel repair $whl -w "${GITHUB_WORKSPACE}"/dist/ - rm "${GITHUB_WORKSPACE}"/dist/*-linux_*.whl -done diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7e2c51b8..fb948c26 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -35,7 +35,7 @@ jobs: mkdir -p dist/ echo "${VERSION}" > dist/VERSION - - uses: actions/upload-artifact@v1 + - uses: actions/upload-artifact@v2 with: name: dist path: dist/ @@ -50,34 +50,30 @@ jobs: fetch-depth: 50 submodules: true - - name: Set up Python 3.7 - uses: actions/setup-python@v2 - with: - python-version: 3.7 + - uses: actions/setup-python@v2 - name: Build source distribution run: | - pip install -U setuptools wheel pip + python -m pip install -U setuptools wheel pip python setup.py sdist - - uses: actions/upload-artifact@v1 + - uses: actions/upload-artifact@v2 with: name: dist - path: dist/ + path: dist/*.tar.* build-wheels: needs: validate-release-request runs-on: ${{ matrix.os }} strategy: matrix: - python-version: [3.5, 3.6, 3.7, 3.8, 3.9] - os: [ubuntu-16.04, macos-latest, windows-latest] - exclude: - # Python 3.5 is unable to properly - # find the recent VS tooling - # https://bugs.python.org/issue30389 - - os: windows-latest - python-version: 3.5 + os: [ubuntu-latest, macos-latest, windows-latest] + cibw_arch: [auto] + include: + - os: ubuntu-latest + cibw_arch: aarch64 + - os: macos-latest + cibw_arch: universal2 steps: - uses: actions/checkout@v2 @@ -85,45 +81,30 @@ jobs: fetch-depth: 50 submodules: true - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + - name: Set up QEMU + if: matrix.os == 'ubuntu-latest' && matrix.cibw_arch == 'aarch64' + uses: docker/setup-qemu-action@v1 with: - python-version: ${{ matrix.python-version }} - - - name: Install Python Deps - run: | - python -m pip install --upgrade setuptools pip wheel + platforms: arm64 - - name: Test - run: | - make debug && make test - - - name: Build Wheels (linux) - if: startsWith(matrix.os, 'ubuntu') - uses: docker://quay.io/pypa/manylinux1_x86_64 + - uses: pypa/cibuildwheel@v2.0.1 env: - PYTHON_VERSION: ${{ matrix.python-version }} - with: - entrypoint: /github/workspace/.github/workflows/build-manylinux-wheels.sh - - - name: Build Wheels (non-linux) - if: "!startsWith(matrix.os, 'ubuntu')" - run: | - make clean - python setup.py bdist_wheel - - - name: Test Wheels - shell: bash - if: | - !contains(github.event.pull_request.labels.*.name, 'skip wheel tests') - run: | - pip install --pre immutables -f "file:///${GITHUB_WORKSPACE}/dist" - make -C "${GITHUB_WORKSPACE}" testinstalled - - - uses: actions/upload-artifact@v1 + CIBW_BUILD_VERBOSITY: 1 + CIBW_BUILD: "cp36-* cp37-* cp38-* cp39-*" + CIBW_ARCHS: ${{ matrix.cibw_arch }} + CIBW_MANYLINUX_X86_64_IMAGE: quay.io/pypa/manylinux1_x86_64 + CIBW_MANYLINUX_I686_IMAGE: quay.io/pypa/manylinux1_i686 + CIBW_SKIP: "pp*" + CIBW_TEST_EXTRAS: "test" + CIBW_TEST_COMMAND: "cd .. && python {project}/tests/__init__.py" + CIBW_TEST_COMMAND_WINDOWS: "cd .. && python {project}\\tests\\__init__.py" + CIBW_TEST_SKIP: "*universal2:arm64" + CIBW_ENVIRONMENT: "IMMU_SKIP_MYPY_TESTS=1" + + - uses: actions/upload-artifact@v2 with: name: dist - path: dist/ + path: wheelhouse/*.whl publish: needs: [build-sdist, build-wheels] @@ -135,7 +116,7 @@ jobs: fetch-depth: 5 submodules: false - - uses: actions/download-artifact@v1 + - uses: actions/download-artifact@v2 with: name: dist path: dist/ diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index b3316203..ec9ae1df 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -43,6 +43,8 @@ jobs: - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v2 if: steps.release.outputs.version == 0 + env: + PIP_DISABLE_PIP_VERSION_CHECK: 1 with: python-version: ${{ matrix.python-version }} architecture: ${{ matrix.arch }} diff --git a/.gitignore b/.gitignore index 07d98256..e4415579 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,4 @@ __pycache__/ /.coverage /.mypy_cache /.venv* +/wheelhouse diff --git a/tests/test_mypy.py b/tests/test_mypy.py index 48c7f7f4..fcdc11c3 100644 --- a/tests/test_mypy.py +++ b/tests/test_mypy.py @@ -1,23 +1,26 @@ import os -import mypy.test.testcmdline -from mypy.test.helpers import normalize_error_messages - -# I'm upset. There's no other way to deal with the little 'defined here' -# notes that mypy emits when passing an unexpected keyword argument -# and at no other time. -def renormalize_error_messages(messages): - messages = [x for x in messages if not x.endswith(' defined here')] - return normalize_error_messages(messages) - - -mypy.test.testcmdline.normalize_error_messages = renormalize_error_messages - - -this_file_dir = os.path.dirname(os.path.realpath(__file__)) -test_data_prefix = os.path.join(this_file_dir, 'test-data') - - -class ImmuMypyTest(mypy.test.testcmdline.PythonCmdlineSuite): - data_prefix = test_data_prefix - files = ['check-immu.test'] +try: + import mypy.test.testcmdline + from mypy.test.helpers import normalize_error_messages +except (ImportError, AssertionError): + if os.environ.get('IMMU_SKIP_MYPY_TESTS'): + pass + else: + raise +else: + # I'm upset. There's no other way to deal with the little 'defined here' + # notes that mypy emits when passing an unexpected keyword argument + # and at no other time. + def renormalize_error_messages(messages): + messages = [x for x in messages if not x.endswith(' defined here')] + return normalize_error_messages(messages) + + mypy.test.testcmdline.normalize_error_messages = renormalize_error_messages + + this_file_dir = os.path.dirname(os.path.realpath(__file__)) + test_data_prefix = os.path.join(this_file_dir, 'test-data') + + class ImmuMypyTest(mypy.test.testcmdline.PythonCmdlineSuite): + data_prefix = test_data_prefix + files = ['check-immu.test']