Compare commits

...
116 Commits
Author SHA1 Message Date
Joe Rickerby d12e54af41 Bump version: v1.6.4 2020-10-31 15:56:43 +00:00
Matthieu DarboisandJoe Rickerby 336c80b694 Use certifi provided certificates when downloading files (#455)
* Use certifi provided certificates when downloading files

* fix typo

* Add comment about certifi usage

Co-authored-by: Joe Rickerby <joerick@mac.com>

Co-authored-by: Joe Rickerby <joerick@mac.com>
2020-10-31 10:06:14 +01:00
Joe Rickerby 7dcd6826a4 Merge pull request #439 from dimitern/dimitern-xmlstarlet-example-readme
Add xmlstarlet to Working examples.
2020-10-30 22:20:35 +00:00
Joe Rickerby 1e16497776 Bump version: v1.6.3 2020-10-12 21:05:20 +01:00
Joe Rickerby 39ea08469c Add merged PRs shortcut 2020-10-12 21:00:46 +01:00
Joe Rickerby 441a98f054 Merge pull request #448 from Czaki/dependency_constraints_str
Add str representation to DependencyConstraints
2020-10-11 10:42:30 +01:00
Joe Rickerby 7664768b8e Merge pull request #449 from mayeut/macos-update-ssl-patch
Update openssl patch from 1.0.2u to 1.1.1h on macOS
2020-10-11 10:41:58 +01:00
mayeut b2c4f3d385 Update openssl patch from 1.0.2u to 1.1.1h on macOS
- Update openssl patch from 1.0.2u to 1.1.1h on macOS
- Remove python 3.5 workaround in install_certifi.py
2020-10-10 18:55:26 +02:00
8094b3f6db Update macOS SSL certificates (#447)
Update macOS SSL certificates using latest `certifi` certificate bundle.

Co-authored-by: Yannick Jadoul <yannick.jadoul@belgacom.net>
Co-authored-by: Matthieu Darbois <mayeut@users.noreply.github.com>
2020-10-10 18:24:15 +02:00
Grzegorz Bokota d781111941 add str representation to DependencyConstraints 2020-10-09 23:10:44 +02:00
Joe Rickerby 97dd4ee1c0 Bump version: v1.6.2 2020-10-09 13:23:04 +01:00
Joe Rickerby f6eaa9feec Merge pull request #444 from joerick/joerick-patch-1
Add Python 3.9 to build identifiers table in docs
2020-10-08 13:32:29 +01:00
Joe Rickerby acedefdda5 Add Python 3.9 to build identifiers table in docs
Just noticed this was missing from the docs, have added it :)
2020-10-08 08:54:58 +01:00
Dimiter Naydenov 3e7a665b11 Updated description 2020-10-07 19:26:32 +03:00
Henry SchreinerandMatthieu Darbois 9fbe8186f9 chore: Python 3.9.0 final, Python 3.7 constraints (#440)
* chore: update to 3.9.0 final

* chore: add python 3.7 constraints

* chore: missed one image due to travis-ci fail

Co-authored-by: Matthieu Darbois <mayeut@users.noreply.github.com>

Co-authored-by: Matthieu Darbois <mayeut@users.noreply.github.com>
2020-10-06 22:02:11 -04:00
Yannick Jadoul 015f382418 Merge pull request #430 from YannickJadoul/pypy-7.3.2
[READY] Updating PyPy to 7.3.2
2020-10-06 17:47:34 +02:00
Dimiter Naydenov 734377b5f5 Add xmlstarlet to Working examples.
Building binary wheels for Python 3.6+ and Linux, MacOS, and Windows.
The easiest way to install and use the tool on Windows (from Python), also builds a truly native MSVC win_amd64 binary (not MinGW64).
I couldn't find a good example of a usable CFFI cross-platform binary wheel build setup (esp. when the original C sources only build under MinGW32).
2020-10-04 20:45:46 +03:00
Yannick Jadoul 0154a8f992 Run less tests in macOS builds on Travis CI 2020-10-04 00:13:18 +02:00
Yannick Jadoul cd53552b4b Change examples to use macOS >= 10.14 2020-10-03 21:37:17 +02:00
Joe Rickerby 630653b786 add henryiii to maintainers 🎉 2020-10-03 11:18:29 +01:00
Yannick Jadoul 870bf3f740 Update Travis CI and CircleCI to use macOS 10.14 2020-09-27 13:44:48 +02:00
Yannick Jadoul 6ef2f92dfc Reverting to the official PyPy docker image 2020-09-26 22:46:40 +02:00
Yannick Jadoul b3a16d58cf PyPy 7.3.2 was released 2020-09-25 15:42:05 +02:00
Yannick Jadoul 7f95eb3d8f Update PyPy to 7.3.2rc2 2020-09-25 15:41:33 +02:00
Yannick Jadoul a7b69cc16d Remove workaround for AppVeyor bug on macOS (#318), as the AppVeyor issue is closed now 2020-09-25 15:41:33 +02:00
Yannick Jadoul 87dfa75dcb Revert "Allow failures on Appveyor macos"
This reverts commit f1c4ebbed0.
2020-09-25 15:41:33 +02:00
Yannick Jadoul 61c45248bd Temporarily fixing some tests of default docker images (now that pypywheels/manylinux2010-pypy_x86_64 temporarily moved to yannickjadoul/manylinux2010-pypy_x86_64) 2020-09-25 15:41:33 +02:00
Yannick Jadoul acd9300077 Update Linux versions as well, with 'yannickjadoul/manylinux2010-pypy_x86_64:7.3.2rc1' temporary docker image 2020-09-25 15:41:33 +02:00
Yannick Jadoul 37a6504351 Adding PyPy Python 3.7 to the tests 2020-09-25 15:41:33 +02:00
Yannick Jadoul 452631eb60 Updating PyPy to 7.3.2rc1 on macOS and Windows, and adding the Python 3.7 version 2020-09-25 15:41:33 +02:00
Joe Rickerby aacd0fe33c Bump version: v1.6.1 2020-09-20 17:36:35 +01:00
Joe Rickerby 26705eef1b Merge pull request #436 from YannickJadoul/update-docker-images-ppc64le
Update pinned_docker_images.cfg after the ppc64le manylinux2014 image is built again on Travis CI
2020-09-20 17:27:42 +01:00
Yannick Jadoul ff277fd345 Remove Python 3.9 on ppc64le warning from README 2020-09-20 15:53:37 +02:00
Yannick Jadoul 3d9fef458c Update pinned_docker_images.cfg after the ppc64le manylinux2014 image is built again on Travis CI 2020-09-20 15:51:10 +02:00
Joe Rickerby fac9b13307 Merge pull request #433 from mondeja/fix-travis-examples
Fix TravisCI deploy example link and TravisCI config example in README
2020-09-20 10:15:19 +01:00
Álvaro Mondéjar 31a4e3c86b Fix TravisCI deploy example link and TravisCI config example in README 2020-09-20 00:01:25 +02:00
Joe Rickerby bd0aca510c Add notes to some of the examples in README 2020-09-19 10:59:49 +01:00
Joe Rickerby 93b2ce39f0 Merge pull request #432 from tasn/patch-1
README: add etebase-py to the list of users
2020-09-18 15:49:15 +01:00
Tom Hacohen d696481714 README: add etebase-py to the list of users 2020-09-16 14:43:13 +03:00
Joe Rickerby 42b81ab47f Merge pull request #428 from adamchainz/patch-1
Add project_urls to setup.py
2020-09-09 18:45:38 +01:00
Joe Rickerby c013e0d0e6 Update README.md 2020-09-09 18:42:41 +01:00
Adam Johnson 2fd18793c1 Add project_urls to setup.py
These links make it easier to jump from PyPI to the respective page.
2020-09-09 09:17:42 +01:00
Joe Rickerby 200d4af89c Bump version: v1.6.0 2020-09-09 08:57:25 +01:00
Joe Rickerby 48d77c7edf Merge pull request #425 from joerick/update-constraints-2020-09-07T21-18-26
Update dependencies
2020-09-08 08:40:30 +01:00
Joe Rickerby 0b9a3e8afd Update dependencies 2020-09-07 22:18:40 +01:00
Joe Rickerby a2a8655c43 Merge pull request #419 from joerick/gitlab-ci
Add Gitlab CI
2020-09-07 22:16:42 +01:00
Joe Rickerby 4b5ac4ecbb Merge remote-tracking branch 'origin/master' into gitlab-ci 2020-09-07 20:25:14 +01:00
Joe Rickerby 8a434b1759 Merge pull request #382 from joerick/python3.9
Add python3.9 support
2020-09-07 20:10:56 +01:00
Yannick Jadoul 2a62198b47 Update docker images again 2020-09-06 23:56:21 +02:00
Yannick Jadoul 28de36ea6f Adapt README to fully support Python 3.9 2020-09-06 23:55:04 +02:00
Joe Rickerby c3caa5f26f Add maintainer tools docs 2020-09-06 16:58:13 +01:00
Joe Rickerby 6840c9cea1 Add docs for linux-only Gitlab CI 2020-09-02 19:53:03 +01:00
Joe Rickerby c67da48510 Remove Windows Gitlab support 2020-09-02 19:43:12 +01:00
Joe Rickerby 9a444b1ab8 Install vcpython27 while working around the dotnet3.5 install error 2020-09-01 22:45:46 +01:00
Joe Rickerby 10585d2882 Use Powershell syntax for changing PATH 2020-09-01 21:25:01 +01:00
Joe Rickerby 2fbaa36286 Use cmd syntax to change PATH 2020-08-31 21:02:19 +01:00
Joe Rickerby 4433ea4de1 Add missing cibuildwheel install line 2020-08-31 20:46:15 +01:00
Joe Rickerby 5c5d1ef10a Fix Gitlab Windows config 2020-08-31 20:44:25 +01:00
Joe Rickerby 734dea7526 Fix config path 2020-08-31 19:34:00 +01:00
Joe Rickerby 188eaa8a93 Add gitlab config 2020-08-31 19:32:45 +01:00
Joe Rickerby 8e0ee0a4ab Improve script output formatting 2020-08-31 18:59:32 +01:00
Joe Rickerby 84446ed1a9 Attempt a fix for the CircleCI minimal example 2020-08-31 18:52:20 +01:00
Joe Rickerby a4699f4cc8 Fix flake8 error 2020-08-30 12:12:06 +01:00
Joe Rickerby ac90f2b9ac Add CI example test script 2020-08-30 12:08:58 +01:00
Yannick Jadoul 3a984346dd Merge pull request #424 from YannickJadoul/docs-vc++-runtime
Add section to the docs' FAQ about VC++ runtimes and VCRUNTIME140_1.dll on VS2019
2020-08-29 20:17:12 +02:00
Yannick Jadoul b448271640 Fix typos 2020-08-28 17:09:49 +02:00
Yannick Jadoul e0dd32dea8 Extend explanation about versions of Python and versions of VC++ redistributable files 2020-08-28 16:16:14 +02:00
Yannick Jadoul fbb4e28b44 Add section to the docs' FAQ about VC++ runtimes and VCRUNTIME140_1.dll on VS2019 2020-08-28 01:52:04 +02:00
Yannick Jadoul aafdff7ec7 Merge pull request #420 from henryiii/fix/exfile
fix: Windows extra file
2020-08-16 23:03:18 +02:00
Yannick Jadoul e6e8cb79fc Merge pull request #422 from henryiii/ci/format
ci: format updates
2020-08-16 23:02:19 +02:00
Henry SchreinerandJoe Rickerby a0d67a7a90 ci: suggestion from @joerick
Co-authored-by: Joe Rickerby <joerick@mac.com>
2020-08-16 14:15:28 -04:00
Henry Schreiner fd2b5d3270 refactor: minor tweaks from @joerick 2020-08-16 14:05:39 -04:00
Henry Schreiner 416c6f3a3c fix: file method of requirement installs 2020-08-14 17:12:40 -04:00
Henry Schreiner 9df68df525 style: add a few more checks 2020-08-14 16:12:24 -04:00
Henry Schreiner 45074a9b3a fix: add extra space after ] 2020-08-14 15:57:42 -04:00
Henry Schreiner 448d6538d7 chore: run pre-commit autoupdate 2020-08-14 15:56:06 -04:00
Henry Schreiner 17c83ad78b ci: move formatting check to pre-commit + GitHub 2020-08-14 15:56:05 -04:00
Henry Schreiner 6d6d277ea5 fix: pre-commit check was broken 2020-08-14 15:49:56 -04:00
Joe Rickerby d36b2d35c6 fix PYTHON variable 2020-08-14 11:42:25 +01:00
Joe Rickerby efa1958023 Add a windows gitlab implementation 2020-08-14 09:51:30 +00:00
Yannick Jadoul a345008626 Update all, except ppc64le on manylinux2014, to Python 3.9 rc1 2020-08-13 17:28:09 +02:00
Joe Rickerby 43abc35259 Merge pull request #418 from joerick/add-troubleshoot-test
Add troubleshoot test
2020-08-13 15:19:26 +01:00
Joe Rickerby 2942c99ce4 docker tweaks 2020-08-13 13:58:14 +01:00
Joe Rickerby 3c577ab036 Add docker config 2020-08-13 13:49:52 +01:00
Joe Rickerby 8ce553b2ea Tweak config 2020-08-13 13:42:52 +01:00
Joe Rickerby 48c23b10d0 Move gitlab config to the right location 2020-08-13 13:36:48 +01:00
Joe Rickerby 442174157a Add a test Gitlab CI config 2020-08-13 12:15:53 +01:00
Joe Rickerby f19c606573 Fix comment 2020-08-13 11:50:17 +01:00
Joe Rickerby ac3523132d Add troubleshoot test 2020-08-13 11:46:39 +01:00
stfbncandYannick Jadoul a7ea9f42cb added fathon repository to README (#415)
* added fathon repository to README

* accidental error fixed

* Undo line break change to changelog in README

Co-authored-by: Yannick Jadoul <yannick.jadoul@belgacom.net>
2020-08-04 23:26:48 +02:00
Joe Rickerby 1059249f4d Update to Python 3.9.0b5 2020-08-03 17:45:27 +01:00
Joe Rickerby 516f4b9d7e Merge pull request #414 from joerick/pure-wheel-error
Raise an error when cibuildwheel produces a non-platform wheel
2020-07-24 20:53:29 +01:00
Joe Rickerby ebf56281ed Add pure wheel detection, and failing with an error in this case 2020-07-24 15:54:31 +01:00
Joe Rickerby 0896566743 Merge remote-tracking branch 'origin/master' into python3.9 2020-07-24 15:35:31 +01:00
Joe Rickerby fd92707823 Merge pull request #413 from Czaki/project_path_to_var
use variable instead of '/project' literal
2020-07-24 15:27:36 +01:00
Grzegorz Bokota cfec077f05 change project_path to container_project_path 2020-07-23 20:24:19 +02:00
Joe Rickerby 5c4767899d Bump version: v1.5.5 2020-07-22 18:57:47 +01:00
Grzegorz Bokota a15ccb6ef0 change project_path to PurePath 2020-07-22 17:26:25 +02:00
Grzegorz Bokota ae6d65e62e use variable instead on '/project' literal 2020-07-22 15:27:51 +02:00
Yannick Jadoul 3cd3a9dc77 Merge pull request #410 from YannickJadoul/fix-pwd-linux-docker
Fix cwd in Linux docker images
2020-07-22 14:41:16 +02:00
Yannick Jadoul 9e40094cfc Make timeout 2 hours on GitHub Actions and Azure Pipelines because of slow Windows jobs 2020-07-21 23:13:55 +02:00
Yannick Jadoul c91d669a90 Extend tests and add tests for CIBW_BEFORE_ALL 2020-07-21 20:12:28 +02:00
Yannick Jadoul f81c9474d6 Fix test_before_build test on Windows 2020-07-20 18:07:45 +02:00
Yannick Jadoul 2610f3220a Run Linux docker images with /project as cwd 2020-07-20 18:07:45 +02:00
Yannick Jadoul 29b0cdb08a Add cwd argument to DockerContainer 2020-07-20 18:07:45 +02:00
Yannick Jadoul 2b7da3fcbe Test whether CIBW_BEFORE_BUILD is executed from the right directory and confirm it is not 2020-07-20 18:07:45 +02:00
Joe Rickerby 726bcdf372 Merge pull request #411 from YannickJadoul/fix-docker-commandsubstitution
Fix command substitution in CIBW_ENVIRONMENT in Linux docker images
2020-07-20 16:38:30 +01:00
Yannick Jadoul 3142806f4b Capture output in DockerContainer.environment_executor to fix command substitutions in CIBW_ENVIRONMENT on Linux 2020-07-20 02:23:07 +02:00
Yannick Jadoul e28e43e7f9 Fix test_environment's checks on a command substitution in an environment 2020-07-20 02:02:50 +02:00
Yannick Jadoul 737ad6b650 Merge pull request #395 from mayeut/python3.9-s390x
Update dependencies to get python 3.9 support on s390x
2020-07-05 21:10:54 +02:00
mayeut 472eb898ed Update dependencies to get python 3.9 support on s390x 2020-07-05 11:02:18 +02:00
Yannick Jadoul 98db24f92c Merge pull request #377 from YannickJadoul/python3.9
Add Python 3.9 (beta 3) to builds
2020-06-22 12:18:08 +02:00
Yannick Jadoul 29b25a3ab6 Update manylinux docker image versions, again 2020-06-18 23:49:14 +02:00
Yannick Jadoul 5a6f35fe76 Skip Python 3.9 in test_docker_images.py until dockcross catches up 2020-06-18 23:14:59 +02:00
Yannick Jadoul 03ae918ec5 Update manylinux docker image versions 2020-06-18 00:23:41 +02:00
Yannick Jadoul 94dead9440 Add Python 3.9 (beta 3) to builds 2020-06-18 00:23:41 +02:00
54 changed files with 871 additions and 190 deletions
+1 -18
View File
@@ -1,25 +1,9 @@
version: 2
jobs:
flake8-mypy:
docker:
- image: circleci/python:3.6
steps:
- checkout
- run:
name: Install flake8 & mypy
command: sudo python -m pip install flake8 mypy
- run:
name: flake8
command: flake8
- run:
name: mypy
command: mypy
osx-python3.6:
macos:
xcode: "9.4.1"
xcode: 10.2.1
environment:
PYTHON: python3
steps:
@@ -54,6 +38,5 @@ workflows:
version: 2
all-tests:
jobs:
- flake8-mypy
- osx-python3.6
- linux-python3.6
+9
View File
@@ -7,6 +7,14 @@ on:
- 'docs/**'
jobs:
pre-commit:
name: Pre-commit checks (mypy, flake8, etc.)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
- uses: pre-commit/action@v2.0.0
test:
# skip branch builds on joerick/cibuildwheel, but always build `master` and pull requests
if: github.repository != 'joerick/cibuildwheel' || github.ref == 'refs/heads/master' || github.event_name == 'pull_request'
@@ -17,6 +25,7 @@ jobs:
matrix:
os: [ubuntu-18.04, windows-latest, macos-latest]
python_version: ['3.7']
timeout-minutes: 180
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
+15
View File
@@ -0,0 +1,15 @@
linux:
image: python:3.8
services:
- name: docker:dind
entrypoint: ["env", "-u", "DOCKER_HOST"]
command: ["dockerd-entrypoint.sh"]
variables:
DOCKER_HOST: tcp://docker:2375/
DOCKER_DRIVER: overlay2
# See https://github.com/docker-library/docker/pull/166
DOCKER_TLS_CERTDIR: ""
script:
- curl -sSL https://get.docker.com/ | sh
- python -m pip install -r requirements-dev.txt
- python ./bin/run_tests.py
+24 -20
View File
@@ -1,21 +1,25 @@
repos:
- repo: https://gitlab.com/pycqa/flake8
rev: 3.8.1
hooks:
- id: flake8
pass_filenames: true
# this seems to need to be here in addition to setup.cfg
exclude: cibuildwheel/resources/
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.3.0
hooks:
- id: check-yaml
- id: check-merge-conflict
- id: end-of-file-fixer
exclude: cibuildwheel/resources/pinned_docker_images.cfg
- repo: https://github.com/pre-commit/mirrors-mypy
rev: '' # Use the sha / tag you want to point at
hooks:
- id: mypy
files: cibuildwheel|test
exclude: cibuildwheel/resources
- repo: https://gitlab.com/pycqa/flake8
rev: 3.8.3
hooks:
- id: flake8
exclude: cibuildwheel/resources/
additional_dependencies: [flake8-bugbear]
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.2.0
hooks:
- id: check-case-conflict
- id: check-merge-conflict
- id: check-yaml
- id: end-of-file-fixer
exclude: cibuildwheel/resources/pinned_docker_images.cfg
- id: mixed-line-ending
- id: trailing-whitespace
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v0.782
hooks:
- id: mypy
files: cibuildwheel/|test/
pass_filenames: false
+5 -2
View File
@@ -28,7 +28,10 @@ jobs:
- name: macOS | x86_64 | Python 3.x
os: osx
env: PYTHON=python3
osx_image: xcode10.2
env:
- PYTHON=python3
- PYTEST_ADDOPTS='-k "unit_test or test_0_basic" --suppress-no-test-exit-code'
- name: Windows | x86_64 | Python 3.6
os: windows
@@ -52,6 +55,6 @@ jobs:
# must repeat the s390x job above exactly to match
- *linux_s390x_36
install: $PYTHON -m pip install -r requirements-dev.txt
install: $PYTHON -m pip install -r requirements-dev.txt pytest-custom-exit-code
script: $PYTHON ./bin/run_tests.py
+83 -15
View File
@@ -17,18 +17,19 @@ What does it do?
| | macOS x86_64 | Windows 64bit | Windows 32bit | manylinux x86_64 | manylinux i686 | manylinux aarch64 | manylinux ppc64le | manylinux s390x |
|---|---|---|---|---|---|---|---|---|
| CPython 2.7 | ✅ | ✅¹ | ✅¹ | ✅ | ✅ | | | |
| CPython 3.5 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅² |
| CPython 3.6 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅² |
| CPython 3.7 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅² |
| CPython 3.8 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅² |
| CPython 3.9³ | 🛠 | 🛠 | 🛠 | 🛠 | 🛠 | 🛠 | 🛠 | |
| PyPy 2.7 v7.3.0 | ✅ | | ✅ | ✅ | | | | |
| PyPy 3.6 v7.3.0 | ✅ | | ✅ | ✅ | | | | |
| CPython 2.7 | ✅ | ✅¹ | ✅¹ | ✅ | ✅ | | | |
| CPython 3.5 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅² | ✅² | ✅³ |
| CPython 3.6 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅² | ✅² | ✅³ |
| CPython 3.7 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅² | ✅² | ✅³ |
| CPython 3.8 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅² | ✅² | ✅³ |
| CPython 3.9 | | | | | | ✅² | ✅² | ✅³ |
| PyPy 2.7 v7.3.2 | ✅ | | ✅ | ✅ | | | | |
| PyPy 3.6 v7.3.2 | ✅ | | ✅ | ✅ | | | | |
| PyPy 3.7 (alpha) v7.3.2 | ✅ | | ✅ | ✅ | | | | |
<sup>¹ Not supported on Travis</sup><br>
<sup>² Beta support until Travis CI fixes <a href="https://travis-ci.community/t/no-space-left-on-device-for-system-z/5954/11">a bug</a></sup><br>
<sup>³ Python 3.9 is not yet ABI stable, so you shouldn't publish wheels with it yet. But if you want to check that your wheels build on Python 3.9, try our [`python3.9` branch](https://github.com/joerick/cibuildwheel/pull/382)!</sup>
<sup>² Only supported on Travis</sup><br>
<sup>³ Beta support until Travis CI fixes <a href="https://travis-ci.community/t/no-space-left-on-device-for-system-z/5954/11">a bug</a></sup><br>
- Builds manylinux, macOS and Windows wheels for CPython and PyPy using Azure Pipelines, Travis CI, AppVeyor, and CircleCI
- Bundles shared library dependencies on Linux and macOS through [auditwheel](https://github.com/pypa/auditwheel) and [delocate](https://github.com/matthew-brett/delocate)
@@ -37,7 +38,7 @@ What does it do?
Usage
-----
`cibuildwheel` currently works on **Travis CI**, **Azure Pipelines**, **AppVeyor** and **GitHub Actions** to build wheels for all three supported platforms (Linux, macOS, Windows). On **CircleCI** Linux and macOS wheels can be built.
`cibuildwheel` currently works on **Travis CI**, **Azure Pipelines**, **AppVeyor**, **GitHub Actions**, **CircleCI**, and **Gitlab CI**. Check the table below for supported platforms on each service:
| | Linux | macOS | Windows |
|-----------------|-------|-------|---------|
@@ -46,8 +47,9 @@ Usage
| AppVeyor | ✅ | ✅ | ✅ |
| GitHub Actions | ✅ | ✅ | ✅ |
| CircleCI | ✅ | ✅ | |
| Gitlab CI | ✅ | | |
`cibuildwheel` is not intended to run on your development machine. Because it uses system Python from Python.org it will try to install packages globally - not what you expect from a build tool! Instead, isolated CI services like Travis CI, CircleCI, Azure Pipelines and AppVeyor are ideal.
`cibuildwheel` is not intended to run on your development machine. Because it uses system Python from Python.org it will try to install packages globally - not what you expect from a build tool! Instead, isolated CI services like those mentioned above are ideal.
<!--intro-end-->
@@ -65,6 +67,8 @@ jobs:
- services: docker
# and a mac build
- os: osx
# PyPy 7.3.2 needs macOS >= 10.14
osx_image: xcode10.2
language: shell
# and a windows build
- os: windows
@@ -72,6 +76,8 @@ jobs:
before_install:
- choco install python --version 3.8.0
- export PATH="/c/Python38:/c/Python38/Scripts:$PATH"
# make sure it's on PATH as 'python3'
- ln -s /c/Python38/python.exe /c/Python38/python3.exe
env:
global:
@@ -79,7 +85,7 @@ env:
# Note: TWINE_PASSWORD is set to a PyPI API token in Travis settings
install:
- python3 -m pip install cibuildwheel==1.5.4
- python3 -m pip install cibuildwheel==1.6.4
script:
# build the wheels, put them into './wheelhouse'
@@ -121,7 +127,7 @@ Working examples
Here are some repos that use cibuildwheel.
- [pyinstrument_cext](https://github.com/joerick/pyinstrument_cext)
- [pyinstrument_cext](https://github.com/joerick/pyinstrument_cext) - A simple C extension, without external dependencies, built on Travis CI/Appveyor.
- [websockets](https://github.com/aaugustin/websockets)
- [Parselmouth](https://github.com/YannickJadoul/Parselmouth)
- [python-admesh](https://github.com/admesh/python-admesh)
@@ -137,8 +143,12 @@ Here are some repos that use cibuildwheel.
- [aiortc](https://github.com/aiortc/aiortc)
- [aioquic](https://github.com/aiortc/aioquic)
- [pikepdf](https://github.com/pikepdf/pikepdf)
- [fathon](https://github.com/stfbnc/fathon)
- [etebase-py](https://github.com/etesync/etebase-py) - Python bindings to a Rust library using `setuptools-rust`, and `sccache` for improved speed, built on Travis CI.
- [xmlstarlet](https://github.com/dimitern/xmlstarlet) - Python 3.6+ CFFI bindings with true MSVC build and GitHub Actions.
> Add your repo here! Send a PR.
>
> <sup>I'd like to include notes here to indicate why an example might be interesting to cibuildwheel users - the styles/technologies/techniques used in each. Please include that in future additions!</sup>
Legal note
----------
@@ -152,6 +162,63 @@ This is similar to static linking, so it might have some licence implications. C
Changelog
=========
### 1.6.4
_31 October 2020_
- 🐛 Fix crash on Appveyor during nuget install due to old system CA
certificates. We now use certifi's CA certs to download files. (#455)
### 1.6.3
_12 October 2020_
- 🐛 Fix missing SSL certificates on macOS (#447)
- 🛠 Update OpenSSL Python 3.5 patch to 1.1.1h on macOS (#449)
### 1.6.2
_9 October 2020_
- ✨ Python 3.9 updated to the final release version - v3.9.0 (#440)
- 🛠 Pypy updated to v7.3.2, adding alpha support for Python 3.7 (#430)
### 1.6.1
_20 September 2020_
- 🛠 Add PPC64LE manylinux image supporting Python 3.9. (#436)
- 📚 Add project URLs to PyPI listing (#428)
### 1.6.0
_9 September 2020_
- 🌟 Add Python 3.9 support! This initial support uses release candidate
builds. You can start publishing wheels for Python 3.9 now, ahead of
the official release. (#382)
Minor note - if you're building PPC64LE wheels, the manylinux image pinned
by this version is
[still on Python 3.9b3](https://github.com/pypa/manylinux/issues/758), not a
release candidate. We'd advise holding off on distributing 3.9 ppc64le wheels
until a subsequent version of cibuildwheel.
- 🌟 Add Gitlab CI support. Gitlab CI can now build Linux wheels, using
cibuildwheel. (#419)
- 🐛 Fix a bug that causes pyproject.toml dependencies to fail to install on
Windows (#420)
- 📚 Added some information about Windows VC++ runtimes and how they relate
to wheels.
### 1.5.5
_22 July 2020_
- 🐛 Fix a bug that would cause command substitutions in CIBW_ENVIRONMENT to
produce no output on Linux (#411)
- 🐛 Fix regression (introduced in 1.5.3) which caused BEFORE_BUILD and
BEFORE_ALL to be executed in the wrong directory (#410)
### 1.5.4
_19 June 2020_
@@ -496,6 +563,7 @@ Maintainers
- Joe Rickerby [@joerick](https://github.com/joerick)
- Yannick Jadoul [@YannickJadoul](https://github.com/YannickJadoul)
- Matthieu Darbois [@mayeut](https://github.com/mayeut)
- Henry Schreiner [@henryiii](https://github.com/henryiii)
Credits
-------
+1 -9
View File
@@ -1,7 +1,4 @@
environment:
# workaround an appveyor bug on macos
# see https://github.com/appveyor/ci/issues/3376#issuecomment-611314299
APPVEYOR_CONSOLE_DISABLE_PTY: true
matrix:
- APPVEYOR_BUILD_WORKER_IMAGE: Ubuntu
APPVEYOR_JOB_NAME: "python37-x64-ubuntu"
@@ -10,11 +7,6 @@ environment:
- APPVEYOR_BUILD_WORKER_IMAGE: macos-mojave
APPVEYOR_JOB_NAME: "python37-x64-macos-mojave"
# while pypy libffi dependency is failing the build, allow failures on macos
matrix:
allow_failures:
- APPVEYOR_BUILD_WORKER_IMAGE: macos-mojave
stack: python 3.7
build: off
@@ -24,7 +16,7 @@ init:
- ps: |
$BRANCH = if ($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH) { $env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH } else { $env:APPVEYOR_REPO_BRANCH }
if (-not ($BRANCH -eq 'master' -or $BRANCH.ToLower().StartsWith('appveyor-'))) {
$env:PYTEST_ADDOPTS='-k "unit_test or _basic" --suppress-no-test-exit-code'
$env:PYTEST_ADDOPTS='-k "unit_test or test_0_basic" --suppress-no-test-exit-code'
}
install: python -m pip install -r requirements-dev.txt pytest-custom-exit-code
+2
View File
@@ -21,6 +21,7 @@ jobs:
- job: windows_36
pool: {vmImage: 'vs2017-win2016'}
timeoutInMinutes: 180
steps:
- task: UsePythonVersion@0
inputs:
@@ -33,6 +34,7 @@ jobs:
- job: windows_38
pool: {vmImage: 'vs2017-win2016'}
timeoutInMinutes: 180
steps:
- task: UsePythonVersion@0
inputs:
+19
View File
@@ -7,6 +7,7 @@ import cibuildwheel
from packaging.version import Version, InvalidVersion
import subprocess
import glob
import urllib.parse
config = [
# file path, version find/replace format
@@ -87,6 +88,24 @@ def bump_version():
print('Files updated. If you want to update the changelog as part of this')
print('commit, do that now.')
print()
try:
commit_date_str = subprocess.run([
'git',
'show', '-s', '--pretty=format:%ci',
f'v{current_version}^{{commit}}'
], check=True, capture_output=True, encoding='utf8').stdout
commit_date_parts = commit_date_str.split(' ')
url = 'https://github.com/joerick/cibuildwheel/pulls?' + urllib.parse.urlencode({
'q': f'is:pr merged:>{commit_date_parts[0]}T{commit_date_parts[1]}{commit_date_parts[2]}',
})
print(f'PRs merged since last release:\n {url}')
print()
except subprocess.CalledProcessError as e:
print(e)
print('Failed to get previous version tag information.')
while input('Type "done" to continue: ').strip().lower() != 'done':
pass
+137
View File
@@ -0,0 +1,137 @@
#!/usr/bin/env python3
import os
from pathlib import Path
import shutil
from subprocess import run
import sys
import textwrap
import time
import click
from collections import namedtuple
from urllib.parse import quote
def shell(cmd, **kwargs):
return run([cmd], shell=True, **kwargs)
def git_repo_has_changes():
unstaged_changes = shell('git diff-index --quiet HEAD --').returncode != 0
staged_changes = shell('git diff-index --quiet --cached HEAD --').returncode != 0
return unstaged_changes or staged_changes
def generate_basic_project(path):
sys.path.insert(0, '')
from test.test_projects.c import new_c_project
project = new_c_project()
project.generate(path)
CIService = namedtuple('CIService', 'name src_config_path dst_config_path badge_md')
services = [
CIService(
name='appveyor',
src_config_path='examples/appveyor-minimal.yml',
dst_config_path='appveyor.yml',
badge_md='[![Build status](https://ci.appveyor.com/api/projects/status/wbsgxshp05tt1tif/branch/{branch}?svg=true)](https://ci.appveyor.com/project/joerick/cibuildwheel/branch/{branch})',
),
CIService(
name='azure-pipelines',
src_config_path='examples/azure-pipelines-minimal.yml',
dst_config_path='azure-pipelines.yml',
badge_md='[![Build Status](https://dev.azure.com/joerick0429/cibuildwheel/_apis/build/status/joerick.cibuildwheel?branchName={branch})](https://dev.azure.com/joerick0429/cibuildwheel/_build/latest?definitionId=2&branchName={branch})',
),
CIService(
name='circle-ci',
src_config_path='examples/circleci-minimal.yml',
dst_config_path='.circleci/config.yml',
badge_md='[![CircleCI](https://circleci.com/gh/joerick/cibuildwheel/tree/{branch_escaped}.svg?style=svg)](https://circleci.com/gh/joerick/cibuildwheel/tree/{branch})',
),
CIService(
name='github',
src_config_path='examples/github-minimal.yml',
dst_config_path='.github/workflows/example.yml',
badge_md='[![Build](https://github.com/joerick/cibuildwheel/workflows/Build/badge.svg?branch={branch})](https://github.com/joerick/cibuildwheel/actions)',
),
CIService(
name='travis-ci',
src_config_path='examples/travis-ci-minimal.yml',
dst_config_path='.travis.yml',
badge_md='[![Build Status](https://travis-ci.org/joerick/cibuildwheel.svg?branch={branch})](https://travis-ci.org/joerick/cibuildwheel)',
),
CIService(
name='gitlab',
src_config_path='examples/gitlab-minimal.yml',
dst_config_path='.gitlab-ci.yml',
badge_md='[![Gitlab](https://gitlab.com/joerick/cibuildwheel/badges/{branch}/pipeline.svg)](https://gitlab.com/joerick/cibuildwheel/-/commits/{branch})'
),
]
@click.command()
def run_example_ci_configs():
if git_repo_has_changes():
print('Your git repo has uncommitted changes. Commit or stash before continuing.')
exit(1)
previous_branch = shell('git rev-parse --abbrev-ref HEAD',
check=True,
capture_output=True,
encoding='utf8').stdout.strip()
timestamp = time.strftime('%Y-%m-%dT%H-%M-%S', time.gmtime())
branch_name = f'example-config-test---{previous_branch}-{timestamp}'
try:
shell(f'git checkout --orphan {branch_name}', check=True)
example_project = Path('example_root')
generate_basic_project(example_project)
for service in services:
src_config_file = Path(service.src_config_path)
dst_config_file = example_project / service.dst_config_path
dst_config_file.parent.mkdir(parents=True, exist_ok=True)
shutil.copyfile(src_config_file, dst_config_file)
run(['git', 'add', example_project], check=True)
run(['git', 'commit', '-m', textwrap.dedent(f'''
Test example minimal configs
Testing files: {[s.src_config_path for s in services]}
Generated from branch: {previous_branch}
Time: {timestamp}
''')], check=True)
shell(f'git subtree --prefix={example_project} push origin {branch_name}', check=True)
print('---')
print()
print('> **Examples test run**')
print('> ')
print(f'> Branch: [{branch_name}](https://github.com/joerick/cibuildwheel/tree/{branch_name})')
print('> ')
print('> | Service | Config | Status |')
print('> |---|---|---|')
for service in services:
badge = service.badge_md.format(branch=branch_name, branch_escaped=quote(branch_name, safe=''))
print(f'> | {service.name} | `{service.src_config_path}` | {badge} |')
print('> ')
print('> Generated by `bin/run_example_ci_config.py`')
print()
print('---')
finally:
# remove any local changes
shutil.rmtree(example_project, ignore_errors=True)
shell('git checkout -- .')
shell(f'git checkout {previous_branch}', check=True)
shell(f'git branch -D --force {branch_name}', check=True)
if __name__ == '__main__':
os.chdir(os.path.dirname(__file__))
os.chdir('..')
run_example_ci_configs(standalone_mode=True)
+1 -1
View File
@@ -19,7 +19,7 @@ subprocess.check_call([
'--upgrade',
'cibuildwheel/resources/constraints.in',
])
for python_version in ['27', '35', '36']:
for python_version in ['27', '35', '36', '37']:
subprocess.check_call([
f'./env{python_version}/bin/pip-compile',
'--allow-unsafe',
+1 -1
View File
@@ -1 +1 @@
__version__ = '1.5.4'
__version__ = '1.6.4'
+8 -4
View File
@@ -27,12 +27,14 @@ class DockerContainer:
bash_stdin: IO[bytes]
bash_stdout: IO[bytes]
def __init__(self, docker_image: str, simulate_32_bit=False):
def __init__(self, docker_image: str, simulate_32_bit: bool = False, cwd: Optional[Union[str, PathLike]] = None):
self.docker_image = docker_image
self.simulate_32_bit = simulate_32_bit
self.cwd = cwd
def __enter__(self) -> 'DockerContainer':
self.name = f'cibuildwheel-{uuid.uuid4()}'
cwd_args = ['-w', str(self.cwd)] if self.cwd else []
shell_args = ['linux32', '/bin/bash'] if self.simulate_32_bit else ['/bin/bash']
subprocess.run(
[
@@ -41,6 +43,7 @@ class DockerContainer:
'--name', self.name,
'-i',
'-v', '/:/host', # ignored on CircleCI
*cwd_args,
self.docker_image,
*shell_args
],
@@ -114,11 +117,12 @@ class DockerContainer:
return [PurePath(p) for p in path_strs]
def call(self, args: Sequence[Union[str, PathLike]], env: Dict[str, str] = {},
def call(self, args: Sequence[Union[str, PathLike]], env: Optional[Dict[str, str]] = None,
capture_output=False, cwd: Optional[Union[str, PathLike]] = None) -> str:
chdir = f'cd {cwd}' if cwd else ''
env_assignments = ' '.join(f'{shlex.quote(k)}={shlex.quote(v)}'
for k, v in env.items())
for k, v in env.items()) if env is not None else ''
command = ' '.join(shlex.quote(str(a)) for a in args)
end_of_message = str(uuid.uuid4())
@@ -182,7 +186,7 @@ class DockerContainer:
def environment_executor(self, command: List[str], environment: Dict[str, str]) -> str:
# used as an EnvironmentExecutor to evaluate commands and capture output
return self.call(command, env=environment)
return self.call(command, env=environment, capture_output=True)
def shell_quote(path: PurePath) -> str:
+24 -14
View File
@@ -7,7 +7,7 @@ from pathlib import Path, PurePath
from typing import List, NamedTuple, Union
from .docker_container import DockerContainer
from .util import (BuildOptions, BuildSelector,
from .util import (BuildOptions, BuildSelector, NonPlatformWheelError,
get_build_verbosity_extra_flags, prepare_command)
@@ -50,26 +50,32 @@ def get_python_configurations(build_selector: BuildSelector) -> List[PythonConfi
PythonConfiguration(version='3.6', identifier='cp36-manylinux_x86_64', path_str='/opt/python/cp36-cp36m'),
PythonConfiguration(version='3.7', identifier='cp37-manylinux_x86_64', path_str='/opt/python/cp37-cp37m'),
PythonConfiguration(version='3.8', identifier='cp38-manylinux_x86_64', path_str='/opt/python/cp38-cp38'),
PythonConfiguration(version='3.9', identifier='cp39-manylinux_x86_64', path_str='/opt/python/cp39-cp39'),
PythonConfiguration(version='2.7', identifier='cp27-manylinux_i686', path_str='/opt/python/cp27-cp27m'),
PythonConfiguration(version='2.7', identifier='cp27-manylinux_i686', path_str='/opt/python/cp27-cp27mu'),
PythonConfiguration(version='3.5', identifier='cp35-manylinux_i686', path_str='/opt/python/cp35-cp35m'),
PythonConfiguration(version='3.6', identifier='cp36-manylinux_i686', path_str='/opt/python/cp36-cp36m'),
PythonConfiguration(version='3.7', identifier='cp37-manylinux_i686', path_str='/opt/python/cp37-cp37m'),
PythonConfiguration(version='3.8', identifier='cp38-manylinux_i686', path_str='/opt/python/cp38-cp38'),
PythonConfiguration(version='3.9', identifier='cp39-manylinux_i686', path_str='/opt/python/cp39-cp39'),
PythonConfiguration(version='2.7', identifier='pp27-manylinux_x86_64', path_str='/opt/python/pp27-pypy_73'),
PythonConfiguration(version='3.6', identifier='pp36-manylinux_x86_64', path_str='/opt/python/pp36-pypy36_pp73'),
PythonConfiguration(version='3.7', identifier='pp37-manylinux_x86_64', path_str='/opt/python/pp37-pypy37_pp73'),
PythonConfiguration(version='3.5', identifier='cp35-manylinux_aarch64', path_str='/opt/python/cp35-cp35m'),
PythonConfiguration(version='3.6', identifier='cp36-manylinux_aarch64', path_str='/opt/python/cp36-cp36m'),
PythonConfiguration(version='3.7', identifier='cp37-manylinux_aarch64', path_str='/opt/python/cp37-cp37m'),
PythonConfiguration(version='3.8', identifier='cp38-manylinux_aarch64', path_str='/opt/python/cp38-cp38'),
PythonConfiguration(version='3.9', identifier='cp39-manylinux_aarch64', path_str='/opt/python/cp39-cp39'),
PythonConfiguration(version='3.5', identifier='cp35-manylinux_ppc64le', path_str='/opt/python/cp35-cp35m'),
PythonConfiguration(version='3.6', identifier='cp36-manylinux_ppc64le', path_str='/opt/python/cp36-cp36m'),
PythonConfiguration(version='3.7', identifier='cp37-manylinux_ppc64le', path_str='/opt/python/cp37-cp37m'),
PythonConfiguration(version='3.8', identifier='cp38-manylinux_ppc64le', path_str='/opt/python/cp38-cp38'),
PythonConfiguration(version='3.9', identifier='cp39-manylinux_ppc64le', path_str='/opt/python/cp39-cp39'),
PythonConfiguration(version='3.5', identifier='cp35-manylinux_s390x', path_str='/opt/python/cp35-cp35m'),
PythonConfiguration(version='3.6', identifier='cp36-manylinux_s390x', path_str='/opt/python/cp36-cp36m'),
PythonConfiguration(version='3.7', identifier='cp37-manylinux_s390x', path_str='/opt/python/cp37-cp37m'),
PythonConfiguration(version='3.8', identifier='cp38-manylinux_s390x', path_str='/opt/python/cp38-cp38'),
PythonConfiguration(version='3.9', identifier='cp39-manylinux_s390x', path_str='/opt/python/cp39-cp39'),
]
# skip builds as required
return [c for c in python_configurations if matches_platform(c.identifier) and build_selector(c.identifier)]
@@ -101,7 +107,8 @@ def build(options: BuildOptions) -> None:
if cwd != abs_package_dir and cwd not in abs_package_dir.parents:
raise Exception('package_dir must be inside the working directory')
container_package_dir = PurePath('/project') / abs_package_dir.relative_to(cwd)
container_project_path = PurePath('/project')
container_package_dir = container_project_path / abs_package_dir.relative_to(cwd)
container_output_dir = PurePath('/output')
for implementation, platform_tag, docker_image in platforms:
@@ -110,15 +117,15 @@ def build(options: BuildOptions) -> None:
continue
try:
with DockerContainer(docker_image, simulate_32_bit=platform_tag.endswith('i686')) as docker:
docker.copy_into(Path.cwd(), Path('/project'))
with DockerContainer(docker_image, simulate_32_bit=platform_tag.endswith('i686'), cwd=container_project_path) as docker:
docker.copy_into(Path.cwd(), container_project_path)
if options.before_all:
env = docker.get_environment()
env['PATH'] = f'/opt/python/cp38-cp38:{env["PATH"]}'
env = options.environment.as_dictionary(env, executor=docker.environment_executor)
before_all_prepared = prepare_command(options.before_all, project='/project', package=container_package_dir)
before_all_prepared = prepare_command(options.before_all, project=container_project_path, package=container_package_dir)
docker.call(['sh', '-c', before_all_prepared], env=env)
for config in platform_configs:
@@ -151,7 +158,7 @@ def build(options: BuildOptions) -> None:
exit(1)
if options.before_build:
before_build_prepared = prepare_command(options.before_build, project='/project', package=container_package_dir)
before_build_prepared = prepare_command(options.before_build, project=container_project_path, package=container_package_dir)
docker.call(['sh', '-c', before_build_prepared], env=env)
temp_dir = PurePath('/tmp/cibuildwheel')
@@ -173,11 +180,14 @@ def build(options: BuildOptions) -> None:
docker.call(['rm', '-rf', repaired_wheel_dir])
docker.call(['mkdir', '-p', repaired_wheel_dir])
if built_wheel.name.endswith('none-any.whl') or not options.repair_command:
docker.call(['mv', built_wheel, repaired_wheel_dir])
else:
if built_wheel.name.endswith('none-any.whl'):
raise NonPlatformWheelError()
if options.repair_command:
repair_command_prepared = prepare_command(options.repair_command, wheel=built_wheel, dest_dir=repaired_wheel_dir)
docker.call(['sh', '-c', repair_command_prepared], env=env)
else:
docker.call(['mv', built_wheel, repaired_wheel_dir])
repaired_wheels = docker.glob(repaired_wheel_dir, '*.whl')
@@ -193,7 +203,7 @@ def build(options: BuildOptions) -> None:
virtualenv_env['PATH'] = f"{venv_dir / 'bin'}:{virtualenv_env['PATH']}"
if options.before_test:
before_test_prepared = prepare_command(options.before_test, project='/project', package=container_package_dir)
before_test_prepared = prepare_command(options.before_test, project=container_project_path, package=container_package_dir)
docker.call(['sh', '-c', before_test_prepared], env=virtualenv_env)
# Install the wheel we just built
@@ -210,7 +220,7 @@ def build(options: BuildOptions) -> None:
docker.call(['pip', 'install', *options.test_requires], env=virtualenv_env)
# Run the tests from a different directory
test_command_prepared = prepare_command(options.test_command, project='/project', package=container_package_dir)
test_command_prepared = prepare_command(options.test_command, project=container_project_path, package=container_package_dir)
docker.call(['sh', '-c', test_command_prepared], cwd='/root', env=virtualenv_env)
# clean up test environment
@@ -229,8 +239,8 @@ def build(options: BuildOptions) -> None:
def troubleshoot(package_dir: Path, error: Exception) -> None:
if (isinstance(error, subprocess.CalledProcessError) and 'exec' in error.cmd):
# the bash script failed
if (isinstance(error, subprocess.CalledProcessError) and error.cmd[0:2] == ['pip', 'wheel']):
# the 'pip wheel' step failed.
print('Checking for common errors...')
so_files = list(package_dir.glob('**/*.so'))
@@ -243,7 +253,7 @@ def troubleshoot(package_dir: Path, error: Exception) -> None:
If you're using Cython and have previously done an in-place build,
remove those build files (*.so and *.c) before starting cibuildwheel.
'''))
'''), file=sys.stderr)
print(' Files detected:')
print('\n'.join([f' {f}' for f in so_files]))
+20 -11
View File
@@ -9,9 +9,9 @@ from pathlib import Path
from typing import Dict, List, NamedTuple, Optional, Sequence, Union
from .environment import ParsedEnvironment
from .util import (BuildOptions, BuildSelector, download,
from .util import (BuildOptions, BuildSelector, NonPlatformWheelError, download,
get_build_verbosity_extra_flags, get_pip_script,
prepare_command)
prepare_command, install_certifi_script)
def call(args: Union[str, Sequence[Union[str, PathLike]]], env: Optional[Dict[str, str]] = None, cwd: Optional[str] = None, shell: bool = False) -> int:
@@ -38,9 +38,11 @@ def get_python_configurations(build_selector: BuildSelector) -> List[PythonConfi
PythonConfiguration(version='3.6', identifier='cp36-macosx_x86_64', url='https://www.python.org/ftp/python/3.6.8/python-3.6.8-macosx10.9.pkg'),
PythonConfiguration(version='3.7', identifier='cp37-macosx_x86_64', url='https://www.python.org/ftp/python/3.7.8/python-3.7.8-macosx10.9.pkg'),
PythonConfiguration(version='3.8', identifier='cp38-macosx_x86_64', url='https://www.python.org/ftp/python/3.8.4/python-3.8.4-macosx10.9.pkg'),
PythonConfiguration(version='3.9', identifier='cp39-macosx_x86_64', url='https://www.python.org/ftp/python/3.9.0/python-3.9.0-macosx10.9.pkg'),
# PyPy
PythonConfiguration(version='2.7', identifier='pp27-macosx_x86_64', url='https://downloads.python.org/pypy/pypy2.7-v7.3.1-osx64.tar.bz2'),
PythonConfiguration(version='3.6', identifier='pp36-macosx_x86_64', url='https://downloads.python.org/pypy/pypy3.6-v7.3.1-osx64.tar.bz2'),
PythonConfiguration(version='2.7', identifier='pp27-macosx_x86_64', url='https://downloads.python.org/pypy/pypy2.7-v7.3.2-osx64.tar.bz2'),
PythonConfiguration(version='3.6', identifier='pp36-macosx_x86_64', url='https://downloads.python.org/pypy/pypy3.6-v7.3.2-osx64.tar.bz2'),
PythonConfiguration(version='3.7', identifier='pp37-macosx_x86_64', url='https://downloads.python.org/pypy/pypy3.7-v7.3.2-osx64.tar.bz2'),
]
# skip builds as required
@@ -70,6 +72,9 @@ def install_cpython(version: str, url: str) -> Path:
# if this version of python isn't installed, get it from python.org and install
python_package_identifier = f'org.python.Python.PythonFramework-{version}'
python_executable = 'python3' if version[0] == '3' else 'python'
installation_bin_path = Path(f'/Library/Frameworks/Python.framework/Versions/{version}/bin')
if python_package_identifier not in installed_system_packages:
# download the pkg
download(url, Path('/tmp/Python.pkg'))
@@ -77,12 +82,12 @@ def install_cpython(version: str, url: str) -> Path:
call(['sudo', 'installer', '-pkg', '/tmp/Python.pkg', '-target', '/'])
# patch open ssl
if version == '3.5':
open_ssl_patch_url = f'https://github.com/mayeut/patch-macos-python-openssl/releases/download/v1.0.2u/patch-macos-python-{version}-openssl-v1.0.2u.tar.gz'
open_ssl_patch_url = f'https://github.com/mayeut/patch-macos-python-openssl/releases/download/v1.1.1h/patch-macos-python-{version}-openssl-v1.1.1h.tar.gz'
download(open_ssl_patch_url, Path('/tmp/python-patch.tar.gz'))
call(['sudo', 'tar', '-C', f'/Library/Frameworks/Python.framework/Versions/{version}/', '-xmf', '/tmp/python-patch.tar.gz'])
installation_bin_path = Path(f'/Library/Frameworks/Python.framework/Versions/{version}/bin')
python_executable = 'python3' if version[0] == '3' else 'python'
call(["sudo", str(installation_bin_path/python_executable), str(install_certifi_script)])
pip_executable = 'pip3' if version[0] == '3' else 'pip'
make_symlinks(installation_bin_path, python_executable, pip_executable)
@@ -215,12 +220,16 @@ def build(options: BuildOptions) -> None:
if repaired_wheel_dir.exists():
shutil.rmtree(repaired_wheel_dir)
repaired_wheel_dir.mkdir(parents=True)
if built_wheel.name.endswith('none-any.whl') or not options.repair_command:
# pure Python wheel or empty repair command
shutil.move(str(built_wheel), repaired_wheel_dir)
else:
if built_wheel.name.endswith('none-any.whl'):
raise NonPlatformWheelError()
if options.repair_command:
repair_command_prepared = prepare_command(options.repair_command, wheel=built_wheel, dest_dir=repaired_wheel_dir)
call(repair_command_prepared, env=env, shell=True)
else:
shutil.move(str(built_wheel), repaired_wheel_dir)
repaired_wheel = next(repaired_wheel_dir.glob('*.whl'))
if options.test_command:
+10 -10
View File
@@ -6,21 +6,21 @@
#
appdirs==1.4.4 # via virtualenv
configparser==4.0.2 # via importlib-metadata
contextlib2==0.6.0.post1 # via importlib-metadata, importlib-resources, virtualenv
delocate==0.8.0 # via -r cibuildwheel/resources/constraints.in
distlib==0.3.0 # via virtualenv
contextlib2==0.6.0.post1 # via importlib-metadata, importlib-resources
delocate==0.8.2 # via -r cibuildwheel/resources/constraints.in
distlib==0.3.1 # via virtualenv
filelock==3.0.12 # via virtualenv
importlib-metadata==1.6.0 # via importlib-resources, virtualenv
importlib-resources==1.5.0 # via virtualenv
importlib-metadata==2.0.0 # via virtualenv
importlib-resources==3.0.0 # via virtualenv
pathlib2==2.3.5 # via importlib-metadata, importlib-resources, virtualenv
scandir==1.10.0 # via pathlib2
singledispatch==3.4.0.3 # via importlib-resources
six==1.15.0 # via pathlib2, virtualenv
typing==3.7.4.1 # via importlib-resources
virtualenv==20.0.21 # via -r cibuildwheel/resources/constraints.in
wheel==0.34.2 # via -r cibuildwheel/resources/constraints.in, delocate
typing==3.7.4.3 # via importlib-resources
virtualenv==20.0.33 # via -r cibuildwheel/resources/constraints.in
wheel==0.35.1 # via -r cibuildwheel/resources/constraints.in, delocate
zipp==1.2.0 # via importlib-metadata, importlib-resources
# The following packages are considered to be unsafe in a requirements file:
pip==20.1.1 # via -r cibuildwheel/resources/constraints.in
setuptools==44.1.0 # via -r cibuildwheel/resources/constraints.in
pip==20.2.3 # via -r cibuildwheel/resources/constraints.in
setuptools==44.1.1 # via -r cibuildwheel/resources/constraints.in
@@ -5,16 +5,16 @@
# bin/update_constraints.py
#
appdirs==1.4.4 # via virtualenv
delocate==0.8.0 # via -r cibuildwheel/resources/constraints.in
distlib==0.3.0 # via virtualenv
delocate==0.8.2 # via -r cibuildwheel/resources/constraints.in
distlib==0.3.1 # via virtualenv
filelock==3.0.12 # via virtualenv
importlib-metadata==1.6.0 # via importlib-resources, virtualenv
importlib-resources==1.5.0 # via virtualenv
importlib-metadata==2.0.0 # via virtualenv
importlib-resources==3.0.0 # via virtualenv
six==1.15.0 # via virtualenv
virtualenv==20.0.21 # via -r cibuildwheel/resources/constraints.in
wheel==0.34.2 # via -r cibuildwheel/resources/constraints.in, delocate
virtualenv==20.0.33 # via -r cibuildwheel/resources/constraints.in
wheel==0.35.1 # via -r cibuildwheel/resources/constraints.in, delocate
zipp==1.2.0 # via importlib-metadata, importlib-resources
# The following packages are considered to be unsafe in a requirements file:
pip==20.1.1 # via -r cibuildwheel/resources/constraints.in
setuptools==46.4.0 # via -r cibuildwheel/resources/constraints.in
pip==20.2.3 # via -r cibuildwheel/resources/constraints.in
setuptools==50.3.0 # via -r cibuildwheel/resources/constraints.in
@@ -5,16 +5,16 @@
# bin/update_constraints.py
#
appdirs==1.4.4 # via virtualenv
delocate==0.8.0 # via -r cibuildwheel/resources/constraints.in
distlib==0.3.0 # via virtualenv
delocate==0.8.2 # via -r cibuildwheel/resources/constraints.in
distlib==0.3.1 # via virtualenv
filelock==3.0.12 # via virtualenv
importlib-metadata==1.6.0 # via importlib-resources, virtualenv
importlib-resources==1.5.0 # via virtualenv
importlib-metadata==2.0.0 # via virtualenv
importlib-resources==3.0.0 # via virtualenv
six==1.15.0 # via virtualenv
virtualenv==20.0.21 # via -r cibuildwheel/resources/constraints.in
wheel==0.34.2 # via -r cibuildwheel/resources/constraints.in, delocate
zipp==3.1.0 # via importlib-metadata, importlib-resources
virtualenv==20.0.33 # via -r cibuildwheel/resources/constraints.in
wheel==0.35.1 # via -r cibuildwheel/resources/constraints.in, delocate
zipp==3.3.0 # via importlib-metadata, importlib-resources
# The following packages are considered to be unsafe in a requirements file:
pip==20.1.1 # via -r cibuildwheel/resources/constraints.in
setuptools==46.4.0 # via -r cibuildwheel/resources/constraints.in
pip==20.2.3 # via -r cibuildwheel/resources/constraints.in
setuptools==50.3.0 # via -r cibuildwheel/resources/constraints.in
@@ -0,0 +1,19 @@
#
# This file is autogenerated by pip-compile
# To update, run:
#
# bin/update_constraints.py
#
appdirs==1.4.4 # via virtualenv
delocate==0.8.2 # via -r cibuildwheel/resources/constraints.in
distlib==0.3.1 # via virtualenv
filelock==3.0.12 # via virtualenv
importlib-metadata==2.0.0 # via virtualenv
six==1.15.0 # via virtualenv
virtualenv==20.0.33 # via -r cibuildwheel/resources/constraints.in
wheel==0.35.1 # via -r cibuildwheel/resources/constraints.in, delocate
zipp==3.3.0 # via importlib-metadata
# The following packages are considered to be unsafe in a requirements file:
pip==20.2.3 # via -r cibuildwheel/resources/constraints.in
setuptools==50.3.0 # via -r cibuildwheel/resources/constraints.in
+6 -8
View File
@@ -5,15 +5,13 @@
# bin/update_constraints.py
#
appdirs==1.4.4 # via virtualenv
delocate==0.8.0 # via -r cibuildwheel/resources/constraints.in
distlib==0.3.0 # via virtualenv
delocate==0.8.2 # via -r cibuildwheel/resources/constraints.in
distlib==0.3.1 # via virtualenv
filelock==3.0.12 # via virtualenv
importlib-metadata==1.6.0 # via virtualenv
six==1.15.0 # via virtualenv
virtualenv==20.0.21 # via -r cibuildwheel/resources/constraints.in
wheel==0.34.2 # via -r cibuildwheel/resources/constraints.in, delocate
zipp==3.1.0 # via importlib-metadata
virtualenv==20.0.33 # via -r cibuildwheel/resources/constraints.in
wheel==0.35.1 # via -r cibuildwheel/resources/constraints.in, delocate
# The following packages are considered to be unsafe in a requirements file:
pip==20.1.1 # via -r cibuildwheel/resources/constraints.in
setuptools==46.4.0 # via -r cibuildwheel/resources/constraints.in
pip==20.2.3 # via -r cibuildwheel/resources/constraints.in
setuptools==50.3.0 # via -r cibuildwheel/resources/constraints.in
+50
View File
@@ -0,0 +1,50 @@
# Based on: https://github.com/python/cpython/blob/master/Mac/BuildScript/resources/install_certificates.command
# install_certifi.py
#
# sample script to install or update a set of default Root Certificates
# for the ssl module. Uses the certificates provided by the certifi package:
# https://pypi.org/project/certifi/
import os
import os.path
import ssl
import stat
import subprocess
import sys
STAT_0o775 = (stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR
| stat.S_IRGRP | stat.S_IWGRP | stat.S_IXGRP
| stat.S_IROTH | stat.S_IXOTH)
if sys.version_info[0] == 2:
FileNotFoundError = OSError
def main():
openssl_dir, openssl_cafile = os.path.split(
ssl.get_default_verify_paths().openssl_cafile)
print(" -- pip install --upgrade certifi")
subprocess.check_call([sys.executable,
"-E", "-s", "-m", "pip", "install", "--upgrade", "certifi"])
import certifi
# change working directory to the default SSL directory
os.chdir(openssl_dir)
relpath_to_certifi_cafile = os.path.relpath(certifi.where())
print(" -- removing any existing file or link")
try:
os.remove(openssl_cafile)
except FileNotFoundError:
pass
print(" -- creating symlink to certifi certificate bundle")
os.symlink(relpath_to_certifi_cafile, openssl_cafile)
print(" -- setting permissions")
os.chmod(openssl_cafile, STAT_0o775)
print(" -- update complete")
if __name__ == '__main__':
main()
+10 -11
View File
@@ -1,22 +1,21 @@
[x86_64]
manylinux1 = quay.io/pypa/manylinux1_x86_64:2020-05-25-b56702d
manylinux2010 = quay.io/pypa/manylinux2010_x86_64:2020-05-20-c7bbd11
manylinux2014 = quay.io/pypa/manylinux2014_x86_64:2020-05-17-2f8ac3b
manylinux1 = quay.io/pypa/manylinux1_x86_64:2020-10-06-c4a4a7c
manylinux2010 = quay.io/pypa/manylinux2010_x86_64:2020-10-06-786a931
manylinux2014 = quay.io/pypa/manylinux2014_x86_64:2020-10-06-b2ca7a1
[i686]
manylinux1 = quay.io/pypa/manylinux1_i686:2020-05-25-b56702d
manylinux2010 = quay.io/pypa/manylinux2010_i686:2020-05-20-c7bbd11
manylinux2014 = quay.io/pypa/manylinux2014_i686:2020-05-17-2f8ac3b
manylinux1 = quay.io/pypa/manylinux1_i686:2020-10-06-c4a4a7c
manylinux2010 = quay.io/pypa/manylinux2010_i686:2020-10-06-786a931
manylinux2014 = quay.io/pypa/manylinux2014_i686:2020-10-06-b2ca7a1
[pypy_x86_64]
manylinux2010 = pypywheels/manylinux2010-pypy_x86_64:2020-04-25-eb2cdff
manylinux2010 = pypywheels/manylinux2010-pypy_x86_64:2020-09-26-8f210b5
[aarch64]
manylinux2014 = quay.io/pypa/manylinux2014_aarch64:2020-05-17-2f8ac3b
manylinux2014 = quay.io/pypa/manylinux2014_aarch64:2020-10-06-b2ca7a1
[ppc64le]
manylinux2014 = quay.io/pypa/manylinux2014_ppc64le:2020-05-17-2f8ac3b
manylinux2014 = quay.io/pypa/manylinux2014_ppc64le:2020-10-06-b2ca7a1
[s390x]
manylinux2014 = quay.io/pypa/manylinux2014_s390x:2020-05-17-2f8ac3b
manylinux2014 = quay.io/pypa/manylinux2014_s390x:2020-10-06-b2ca7a1
+27 -1
View File
@@ -1,5 +1,8 @@
import os
import textwrap
import certifi
import urllib.request
import ssl
from fnmatch import fnmatch
from pathlib import Path
from time import sleep
@@ -65,10 +68,14 @@ def download(url: str, dest: Path) -> None:
if not dest_dir.exists():
dest_dir.mkdir(parents=True)
# we've had issues when relying on the host OS' CA certificates on Windows,
# so we use certifi (this sounds odd but requests also does this by default)
cafile = os.environ.get('SSL_CERT_FILE', certifi.where())
context = ssl.create_default_context(cafile=cafile)
repeat_num = 3
for i in range(repeat_num):
try:
response = urllib.request.urlopen(url)
response = urllib.request.urlopen(url, context=context)
except Exception:
if i == repeat_num - 1:
raise
@@ -106,6 +113,9 @@ class DependencyConstraints:
else:
return self.base_file_path
def __str__(self):
return f"File '{self.base_file_path}'"
class BuildOptions(NamedTuple):
package_dir: Path
@@ -126,3 +136,19 @@ class BuildOptions(NamedTuple):
resources_dir = Path(__file__).resolve().parent / 'resources'
get_pip_script = resources_dir / 'get-pip.py'
install_certifi_script = resources_dir / "install_certifi.py"
class NonPlatformWheelError(Exception):
def __init__(self) -> None:
message = textwrap.dedent('''
cibuildwheel: Build failed because a pure Python wheel was generated.
If you intend to build a pure-Python wheel, you don't need cibuildwheel - use
`pip wheel -w DEST_DIR .` instead.
If you expected a platform wheel, check your project configuration, or run
cibuildwheel with CIBW_BUILD_VERBOSITY=1 to view build logs.
''')
super().__init__(message)
+21 -8
View File
@@ -10,7 +10,7 @@ from zipfile import ZipFile
import toml
from .environment import ParsedEnvironment
from .util import (BuildOptions, BuildSelector, download,
from .util import (BuildOptions, BuildSelector, NonPlatformWheelError, download,
get_build_verbosity_extra_flags, get_pip_script,
prepare_command)
@@ -58,9 +58,12 @@ def get_python_configurations(build_selector: BuildSelector) -> List[PythonConfi
PythonConfiguration(version='3.7.8', arch='64', identifier='cp37-win_amd64', url=None),
PythonConfiguration(version='3.8.4', arch='32', identifier='cp38-win32', url=None),
PythonConfiguration(version='3.8.4', arch='64', identifier='cp38-win_amd64', url=None),
PythonConfiguration(version='3.9.0', arch='32', identifier='cp39-win32', url=None),
PythonConfiguration(version='3.9.0', arch='64', identifier='cp39-win_amd64', url=None),
# PyPy
PythonConfiguration(version='2.7', arch='32', identifier='pp27-win32', url='https://downloads.python.org/pypy/pypy2.7-v7.3.1-win32.zip'),
PythonConfiguration(version='3.6', arch='32', identifier='pp36-win32', url='https://downloads.python.org/pypy/pypy3.6-v7.3.1-win32.zip'),
PythonConfiguration(version='2.7', arch='32', identifier='pp27-win32', url='https://downloads.python.org/pypy/pypy2.7-v7.3.2-win32.zip'),
PythonConfiguration(version='3.6', arch='32', identifier='pp36-win32', url='https://downloads.python.org/pypy/pypy3.6-v7.3.2-win32.zip'),
PythonConfiguration(version='3.7', arch='32', identifier='pp37-win32', url='https://downloads.python.org/pypy/pypy3.7-v7.3.2-win32.zip'),
]
if IS_RUNNING_ON_TRAVIS:
@@ -177,8 +180,14 @@ def pep_518_cp35_workaround(package_dir: Path, env: Dict[str, str]) -> None:
if 'build-system' in data
else []
)
if requirements:
shell(['pip', 'install'] + requirements, env=env)
with tempfile.TemporaryDirectory() as d:
reqfile = Path(d) / "requirements.txt"
with reqfile.open("w") as f:
for r in requirements:
print(r, file=f)
call(['pip', 'install', '-r', reqfile], env=env)
def build(options: BuildOptions) -> None:
@@ -236,12 +245,16 @@ def build(options: BuildOptions) -> None:
if repaired_wheel_dir.exists():
shutil.rmtree(repaired_wheel_dir)
repaired_wheel_dir.mkdir(parents=True)
if built_wheel.name.endswith('none-any.whl') or not options.repair_command:
# pure Python wheel or empty repair command
shutil.move(str(built_wheel), repaired_wheel_dir)
else:
if built_wheel.name.endswith('none-any.whl'):
raise NonPlatformWheelError()
if options.repair_command:
repair_command_prepared = prepare_command(options.repair_command, wheel=built_wheel, dest_dir=repaired_wheel_dir)
shell(repair_command_prepared, env=env)
else:
shutil.move(str(built_wheel), repaired_wheel_dir)
repaired_wheel = next(repaired_wheel_dir.glob('*.whl'))
if options.test_command:
+76
View File
@@ -28,3 +28,79 @@ cibuildwheel doesn't really do anything itself - it's always deferring to other
We're not responsible for errors in those tools, for fixing errors/crashes there. But cibuildwheel's job is providing users with an 'integrated' user experience across those tools. We provide an abstraction. The user says 'build me some wheels', not 'open the docker container, build a wheel with pip, fix up the symbols with auditwheel' etc. However, errors have a habit of breaking abstractions. And this is where users get confused, because the mechanism of cibuildwheel is laid bare, and they must understand a little bit how it works to debug.
So, if we can, I'd like to improve the experience on errors as well. In [this](https://github.com/joerick/cibuildwheel/issues/139) case, it takes a bit of knowledge to understand that the linux builds are happening in a totally different OS via docker, that the linked symbols won't match, that auditwheel will fail because of this. A problem with how the tools fit together, instead of the tools themselves.
Maintainer notes
----------------
## Testing minimal configs
cibuildwheel's _minimal_ example configs can be tested on a simple project on cibuildwheel's existing CI. These should be run whenever the minimal configs change.
To test minimal configs, make sure you have a clean git repo, then run the script:
```bash
bin/run_example_ci_configs.py
```
The script will create an isolated 'orphan' commit containing all the minimal config CI files, and a simple C extension project, and push that to a branch on the `origin` repo. The project's CI is already set up to run on branch push, so will begin testing.
The script then outputs a Markdown table that can be copy/pasted into a PR to monitor and record the test.
## Preparing environments
The dependency update script in the next section requires multiple python versions installed. One way to do this is to use `pyenv`:
```bash
pyenv install 2.7.18
pyenv install 3.5.9
pyenv install 3.6.11
pyenv install 3.7.8
# Optionally add 3.8 and make it the local version;
# otherwise assuming 3.8+ already is your current python version
```
Then, you need to make the required virtual environments:
```bash
$(pyenv prefix 2.7.18)/bin/python -m pip install virtualenv
$(pyenv prefix 2.7.18)/bin/python -m virtualenv env27
$(pyenv prefix 3.5.9)/bin/python -m venv env35
$(pyenv prefix 3.6.11)/bin/python -m venv env36
$(pyenv prefix 3.7.8)/bin/python -m venv env37
```
<!-- Note for fish users: use zsh/bash for these lines for now, there's not a nice one-line fish replacement -->
And, you need to install the requirements into each environment:
```bash
for f in env*/bin/pip; do $f install pip-tools; done
```
## Making a release
Before making a release, ensure pinned dependencies are up-to-date. Run the script:
```bash
bin/make_dependency_update_pr.py
```
If updates are needed, this will push a PR with those updates for the CI to test. Once green, merge this PR.
Then, increment the project version number using:
```bash
bin/bump_version.py
```
You'll be prompted to enter the new version number. Update the changelog when prompted. The script will create a 'bump version' commit and version tag.
Finally, cut the release and upload to PyPI/Github.
```bash
rm -rf dist
python setup.py sdist bdist_wheel
twine upload dist/*
git push && git push --tags
```
+2 -2
View File
@@ -9,14 +9,14 @@ After you've built your wheels, you'll probably want to deliver them to PyPI.
On your development machine, do the following...
```bash
# Clear out your 'dist' folder.
# Clear out your 'dist' folder.
rm -rf dist
# Make a source distribution
python setup.py sdist
# 🏃🏻
# Go and download your wheel files from wherever you put them. e.g. your CI
# provider can be configured to store them for you. Put them all into the
# provider can be configured to store them for you. Put them all into the
# 'dist' folder.
# Upload using 'twine' (you may need to 'pip install twine')
+1 -1
View File
@@ -59,7 +59,7 @@ h1, h2, h3, h4, h5, h6 {
background-color: #eff1f3;
font-size: 85%;
font-weight: bold;
border-top-left-radius: 3px;
border-top-right-radius: 3px;
+20
View File
@@ -61,3 +61,23 @@ python3 -m cibuildwheel --output-dir wheelhouse
python3 -m pip install twine
python3 -m twine upload wheelhouse/*.whl
```
### 'ImportError: DLL load failed: The specific module could not be found' error on Windows
Visual Studio and MSVC link the compiled binary wheels to the Microsoft Visual C++ Runtime. Normally, these are included with Python, but when compiling with a newer version of Visual Studio, it is possible users will run into problems on systems that do not have these runtime libraries installed. The solution is to ask users to download the corresponding Visual C++ Redistributable from the [Microsoft website](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads) and install it. Since a Python installation normally includes these VC++ Redistributable files for [the version of the MSVC compiler used to compile Python](https://wiki.python.org/moin/WindowsCompilers), this is typically only a problem when compiling a Python 2.7 C extension with a newer compiler, e.g. to support a modern C++ standard (see [the section on modern C++ standards for Python 2.7](cpp_standards.md#windows-and-python-27) for more details).
Additionally, Visual Studio 2019 started linking to an even newer DLL, `VCRUNTIME140_1.dll`, besides the `VCRUNTIME140.dll` that is included with recent Python versions (starting from Python 3.5; see [here](https://wiki.python.org/moin/WindowsCompilers) for more details on the corresponding Visual Studio & MSVC versions used to compile the different Python versions). To avoid this extra dependency on `VCRUNTIME140_1.dll`, the [`/d2FH4-` flag](https://devblogs.microsoft.com/cppblog/making-cpp-exception-handling-smaller-x64/) can be added to the MSVC invocations (check out [this issue](https://github.com/joerick/cibuildwheel/issues/423) for details and references).
To add the `/d2FH4-` flag to a standard `setup.py` using `setuptools`, the `extra_compile_args` option can be used:
```python
ext_modules=[
Extension(
'c_module',
sources=['extension.c'],
extra_compile_args=['/d2FH4-'] if sys.platform == 'win32' else []
)
],
```
To investigate the dependencies of a C extension (i.e., the `.pyd` file, a DLL in disguise) on Windows, [Dependency Walker](http://www.dependencywalker.com/) is a great tool.
+2 -2
View File
@@ -2,9 +2,9 @@
title: Home
---
{%
{%
includemarkdown "../README.md"
start="<!--intro-start-->"
start="<!--intro-start-->"
end="<!--intro-end-->"
%}
+6 -3
View File
@@ -86,13 +86,16 @@ When setting the options, you can use shell-style globbing syntax (as per [`fnma
| Python 3.6 | cp36-macosx_x86_64 | cp36-manylinux_x86_64 | cp36-manylinux_i686 | cp36-win_amd64 | cp36-win32 | cp36-manylinux_aarch64 | cp36-manylinux_ppc64le | cp36-manylinux_s390x |
| Python 3.7 | cp37-macosx_x86_64 | cp37-manylinux_x86_64 | cp37-manylinux_i686 | cp37-win_amd64 | cp37-win32 | cp37-manylinux_aarch64 | cp37-manylinux_ppc64le | cp37-manylinux_s390x |
| Python 3.8 | cp38-macosx_x86_64 | cp38-manylinux_x86_64 | cp38-manylinux_i686 | cp38-win_amd64 | cp38-win32 | cp38-manylinux_aarch64 | cp38-manylinux_ppc64le | cp38-manylinux_s390x |
| PyPy 2.7 v7.3.0 | pp27-macosx_x86_64 | pp27-manylinux_x86_64 | | | pp27-win32 | | | |
| PyPy 3.6 v7.3.0 | pp36-macosx_x86_64 | pp36-manylinux_x86_64 | | | pp36-win32 | | | |
| Python 3.9 | cp39-macosx_x86_64 | cp39-manylinux_x86_64 | cp39-manylinux_i686 | cp39-win_amd64 | cp39-win32 | cp39-manylinux_aarch64 | cp39-manylinux_ppc64le | cp39-manylinux_s390x |
| PyPy 2.7 v7.3.2 | pp27-macosx_x86_64 | pp27-manylinux_x86_64 | | | pp27-win32 | | | |
| PyPy 3.6 v7.3.2 | pp36-macosx_x86_64 | pp36-manylinux_x86_64 | | | pp36-win32 | | | |
| PyPy 3.7 (alpha) v7.3.2 | pp37-macosx_x86_64 | pp37-manylinux_x86_64 | | | pp37-win32 | | | |
The list of supported and currently selected build identifiers can also be retrieved by passing the `--print-build-identifiers` flag to `cibuildwheel`.
The format is `python_tag-platform_tag`, with tags similar to those in [PEP 425](https://www.python.org/dev/peps/pep-0425/#details).
For CPython, the minimally supported macOS version is 10.9; for PyPy 2.7 and PyPy 3.6, respectively macOS 10.7 and 10.13 or higher is required.
For CPython, the minimally supported macOS version is 10.9; for PyPy 2.7 and PyPy 3.6/3.7, respectively macOS 10.7 and 10.13 or higher is required.
#### Examples
+14 -1
View File
@@ -48,7 +48,7 @@ Commit this file, enable building of your repo on Travis CI, and push.
Then setup a deployment method by following the [Travis CI deployment docs](https://docs.travis-ci.com/user/deployment/), or see [Delivering to PyPI](deliver-to-pypi.md). For more info on `.travis.yml`, check out the [docs](https://docs.travis-ci.com/).
[`examples/travis-deploy.yml`](https://github.com/joerick/cibuildwheel/blob/master/examples/travis-deploy.yml) extends this minimal example with a demonstration of how to automatically upload the built wheels to PyPI.
[`examples/travis-ci-deploy.yml`](https://github.com/joerick/cibuildwheel/blob/master/examples/travis-ci-deploy.yml) extends this minimal example with a demonstration of how to automatically upload the built wheels to PyPI.
# CircleCI [linux/mac] {: #circleci}
@@ -66,6 +66,19 @@ Commit this file, enable building of your repo on CircleCI, and push.
CircleCI will store the built wheels for you - you can access them from the project console. Check out the CircleCI [docs](https://circleci.com/docs/2.0/configuration-reference/#section=configuration) for more info on this config file.
# Gitlab CI [linux] {: #gitlab-ci}
To build Linux wheels on Gitlab CI, create a `.gitlab-ci.yml` file in your repo,
> .gitlab-ci.yml
```yaml
{% include "../examples/gitlab-minimal.yml" %}
```
Commit this file, and push to Gitlab. The pipeline should start automatically.
Gitlab will store the built wheels for you - you can access them from the Pipelines view. Check out the Gitlab [docs](https://docs.gitlab.com/ee/ci/yaml/) for more info on this config file.
# AppVeyor [linux/mac/windows] {: #appveyor}
To build Linux, Mac, and Windows wheels on AppVeyor, create an `appveyor.yml` file in your repo.
+1 -1
View File
@@ -12,7 +12,7 @@ stack: python 3.7
init:
- cmd: set PATH=C:\Python37;C:\Python37\Scripts;%PATH%
install: python -m pip install cibuildwheel==1.5.4
install: python -m pip install cibuildwheel==1.6.4
build_script: python -m cibuildwheel --output-dir wheelhouse
+3 -3
View File
@@ -5,7 +5,7 @@ jobs:
- task: UsePythonVersion@0
- bash: |
python3 -m pip install --upgrade pip
pip3 install cibuildwheel==1.5.4
pip3 install cibuildwheel==1.6.4
cibuildwheel --output-dir wheelhouse .
- task: PublishBuildArtifacts@1
inputs: {pathtoPublish: 'wheelhouse'}
@@ -16,7 +16,7 @@ jobs:
- task: UsePythonVersion@0
- bash: |
python3 -m pip install --upgrade pip
pip3 install cibuildwheel==1.5.4
pip3 install cibuildwheel==1.6.4
cibuildwheel --output-dir wheelhouse .
- task: PublishBuildArtifacts@1
inputs: {pathtoPublish: 'wheelhouse'}
@@ -29,7 +29,7 @@ jobs:
displayName: Install Visual C++ for Python 2.7
- bash: |
python -m pip install --upgrade pip
pip install cibuildwheel==1.5.4
pip install cibuildwheel==1.6.4
cibuildwheel --output-dir wheelhouse .
- task: PublishBuildArtifacts@1
inputs: {pathtoPublish: 'wheelhouse'}
+4 -3
View File
@@ -11,7 +11,7 @@ jobs:
- run:
name: Build the Linux wheels.
command: |
pip3 install --user cibuildwheel==1.5.4
pip3 install --user cibuildwheel==1.6.4
cibuildwheel --output-dir wheelhouse
- store_artifacts:
path: wheelhouse/
@@ -19,13 +19,14 @@ jobs:
osx-wheels:
working_directory: ~/osx-wheels
macos:
xcode: "10.0.0"
# PyPy 7.3.2 needs macOS >= 10.14
xcode: 10.2.1
steps:
- checkout
- run:
name: Build the OS X wheels.
command: |
pip3 install --user cibuildwheel==1.5.4
pip3 install cibuildwheel==1.6.4
cibuildwheel --output-dir wheelhouse
- store_artifacts:
path: wheelhouse/
+1 -1
View File
@@ -28,7 +28,7 @@ jobs:
- name: Install cibuildwheel
run: |
python -m pip install cibuildwheel==1.5.4
python -m pip install cibuildwheel==1.6.4
- name: Install Visual C++ for Python 2.7
if: runner.os == 'Windows'
+1 -1
View File
@@ -20,7 +20,7 @@ jobs:
- name: Install cibuildwheel
run: |
python -m pip install cibuildwheel==1.5.4
python -m pip install cibuildwheel==1.6.4
- name: Install Visual C++ for Python 2.7
if: runner.os == 'Windows'
+19
View File
@@ -0,0 +1,19 @@
linux:
image: python:3.8
# make a docker daemon available for cibuildwheel to use
services:
- name: docker:dind
entrypoint: ["env", "-u", "DOCKER_HOST"]
command: ["dockerd-entrypoint.sh"]
variables:
DOCKER_HOST: tcp://docker:2375/
DOCKER_DRIVER: overlay2
# See https://github.com/docker-library/docker/pull/166
DOCKER_TLS_CERTDIR: ""
script:
- curl -sSL https://get.docker.com/ | sh
- python -m pip install cibuildwheel
- cibuildwheel --output-dir wheelhouse
artifacts:
paths:
- wheelhouse/
+3 -1
View File
@@ -9,6 +9,8 @@ jobs:
- services: docker
# and a mac build
- os: osx
# PyPy 7.3.2 needs macOS >= 10.14
osx_image: xcode10.2
language: shell
# and a windows build
- os: windows
@@ -25,7 +27,7 @@ env:
# Note: TWINE_PASSWORD is set to a PyPI API token in Travis settings
install:
- python3 -m pip install cibuildwheel==1.5.4
- python3 -m pip install cibuildwheel==1.6.4
script:
# build the wheels, put them into './wheelhouse'
+3 -1
View File
@@ -15,6 +15,8 @@ jobs:
arch: s390x
# and a mac build
- os: osx
# PyPy 7.3.2 needs macOS >= 10.14
osx_image: xcode10.2
language: shell
# and a windows build
- os: windows
@@ -26,7 +28,7 @@ jobs:
- ln -s /c/Python38/python.exe /c/Python38/python3.exe
install:
- python3 -m pip install cibuildwheel==1.5.4
- python3 -m pip install cibuildwheel==1.6.4
script:
# build the wheels, put them into './wheelhouse'
+5 -3
View File
@@ -55,7 +55,7 @@ jobs:
- stage: deploy
name: Build and deploy Linux wheels
services: docker
install: python3 -m pip install cibuildwheel==1.5.4
install: python3 -m pip install cibuildwheel==1.6.4
script: python3 -m cibuildwheel --output-dir wheelhouse
after_success: |
python3 -m pip install twine
@@ -64,8 +64,10 @@ jobs:
- stage: deploy
name: Build and deploy macOS wheels
os: osx
# PyPy 7.3.2 needs macOS >= 10.14
osx_image: xcode10.2
language: shell
install: python3 -m pip install cibuildwheel==1.5.4
install: python3 -m pip install cibuildwheel==1.6.4
script: python3 -m cibuildwheel --output-dir wheelhouse
after_success: |
python3 -m pip install twine
@@ -75,7 +77,7 @@ jobs:
name: Build and deploy Windows wheels
os: windows
language: shell
install: python3 -m pip install cibuildwheel==1.5.4
install: python3 -m pip install cibuildwheel==1.6.4
script: python3 -m cibuildwheel --output-dir wheelhouse
after_success: |
python3 -m pip install twine
+2 -1
View File
@@ -1,5 +1,6 @@
[flake8]
ignore = E501,W503,E741,E226
ignore = E501,W503,E741,E226,B950
select = C,E,F,W,B,B9
application-import-names = cibuildwheel
exclude =
cibuildwheel/resources/,
+6 -2
View File
@@ -11,14 +11,18 @@ long_description = (this_directory / 'README.md').read_text(encoding='utf-8')
setup(
name='cibuildwheel',
version='1.5.4',
install_requires=['bashlex!=0.13', 'toml'],
version='1.6.4',
install_requires=['bashlex!=0.13', 'toml', 'certifi'],
description="Build Python wheels on CI with minimal configuration.",
long_description=long_description,
long_description_content_type='text/markdown',
author="Joe Rickerby",
author_email='joerick@mac.com',
url='https://github.com/joerick/cibuildwheel',
project_urls={
'Changelog': 'https://github.com/joerick/cibuildwheel#changelog',
'Documentation': 'https://cibuildwheel.readthedocs.io/',
},
packages=['cibuildwheel', ],
license="BSD",
zip_safe=False,
+28 -3
View File
@@ -1,4 +1,5 @@
import os
import pytest
import subprocess
import textwrap
from . import utils
@@ -21,7 +22,7 @@ def test(tmp_path):
project_dir = tmp_path / 'project'
project_with_before_build_asserts.generate(project_dir)
with open(os.path.join(project_dir, "text_info.txt"), mode='w') as ff:
with (project_dir / 'text_info.txt').open(mode='w') as ff:
print("dummy text", file=ff)
# build the wheels
@@ -33,6 +34,30 @@ def test(tmp_path):
})
# also check that we got the right wheels
os.remove(os.path.join(project_dir, "text_info.txt"))
(project_dir / 'text_info.txt').unlink()
expected_wheels = utils.expected_wheels('spam', '0.1.0')
assert set(actual_wheels) == set(expected_wheels)
def test_failing_command(tmp_path):
project_dir = tmp_path / 'project'
test_projects.new_c_project().generate(project_dir)
with pytest.raises(subprocess.CalledProcessError):
utils.cibuildwheel_run(project_dir, add_env={
'CIBW_BEFORE_ALL': 'false',
'CIBW_BEFORE_ALL_WINDOWS': 'exit /b 1',
})
def test_cwd(tmp_path):
project_dir = tmp_path / 'project'
test_projects.new_c_project().generate(project_dir)
actual_wheels = utils.cibuildwheel_run(project_dir, add_env={
'CIBW_BEFORE_ALL': f'''python -c "import os; assert os.getcwd() == {str(project_dir)!r}"''',
'CIBW_BEFORE_ALL_LINUX': '''python -c "import os; assert os.getcwd() == '/project'"''',
})
expected_wheels = utils.expected_wheels('spam', '0.1.0')
assert set(actual_wheels) == set(expected_wheels)
+31 -2
View File
@@ -1,3 +1,5 @@
import pytest
import subprocess
import textwrap
from . import utils
@@ -32,14 +34,41 @@ def test(tmp_path):
project_dir = tmp_path / 'project'
project_with_before_build_asserts.generate(project_dir)
before_build = ('''python -c "import sys; open('{output_dir}pythonversion.txt', 'w').write(sys.version)" && '''
'''python -c "import sys; open('{output_dir}pythonexecutable.txt', 'w').write(sys.executable)"''')
# build the wheels
actual_wheels = utils.cibuildwheel_run(project_dir, add_env={
# write python version information to a temporary file, this is
# checked in setup.py
'CIBW_BEFORE_BUILD': '''python -c "import sys; open('/tmp/pythonversion.txt', 'w').write(sys.version)" && python -c "import sys; open('/tmp/pythonexecutable.txt', 'w').write(sys.executable)"''',
'CIBW_BEFORE_BUILD_WINDOWS': '''python -c "import sys; open('c:\\pythonversion.txt', 'w').write(sys.version)" && python -c "import sys; open('c:\\pythonexecutable.txt', 'w').write(sys.executable)"''',
'CIBW_BEFORE_BUILD': before_build.format(output_dir='/tmp/'),
'CIBW_BEFORE_BUILD_WINDOWS': before_build.format(output_dir=r'c:\\'),
})
# also check that we got the right wheels
expected_wheels = utils.expected_wheels('spam', '0.1.0')
assert set(actual_wheels) == set(expected_wheels)
def test_failing_command(tmp_path):
project_dir = tmp_path / 'project'
test_projects.new_c_project().generate(project_dir)
with pytest.raises(subprocess.CalledProcessError):
utils.cibuildwheel_run(project_dir, add_env={
'CIBW_BEFORE_BUILD': 'false',
'CIBW_BEFORE_BUILD_WINDOWS': 'exit /b 1',
})
def test_cwd(tmp_path):
project_dir = tmp_path / 'project'
test_projects.new_c_project().generate(project_dir)
actual_wheels = utils.cibuildwheel_run(project_dir, add_env={
'CIBW_BEFORE_BUILD': f'''python -c "import os; assert os.getcwd() == {str(project_dir)!r}"''',
'CIBW_BEFORE_BUILD_LINUX': '''python -c "import os; assert os.getcwd() == '/project'"''',
})
expected_wheels = utils.expected_wheels('spam', '0.1.0')
assert set(actual_wheels) == set(expected_wheels)
+3
View File
@@ -66,6 +66,9 @@ def test_pinned_versions(tmp_path, python_version):
elif python_version == '3.6':
constraint_filename = 'constraints-python36.txt'
build_pattern = '[cp]p36-*'
elif python_version == '3.7':
constraint_filename = 'constraints-python37.txt'
build_pattern = '[cp]p37-*'
else:
constraint_filename = 'constraints.txt'
build_pattern = '[cp]p38-*'
+2 -2
View File
@@ -32,10 +32,10 @@ def test(tmp_path):
actual_wheels = utils.cibuildwheel_run(project_dir, add_env={
'CIBW_MANYLINUX_X86_64_IMAGE': 'dockcross/manylinux2010-x64',
'CIBW_MANYLINUX_I686_IMAGE': 'dockcross/manylinux2010-x86',
'CIBW_SKIP': 'pp*',
'CIBW_SKIP': 'pp* cp39-*',
})
# also check that we got the right wheels built
expected_wheels = [w for w in utils.expected_wheels('spam', '0.1.0')
if '-pp' not in w]
if '-pp' not in w and '-cp39-' not in w]
assert set(actual_wheels) == set(expected_wheels)
+3
View File
@@ -13,12 +13,15 @@ project_with_environment_asserts = test_projects.new_c_project(
# explode if environment isn't correct, as set in CIBW_ENVIRONMENT
CIBW_TEST_VAR = os.environ.get("CIBW_TEST_VAR")
CIBW_TEST_VAR_2 = os.environ.get("CIBW_TEST_VAR_2")
CIBW_TEST_VAR_3 = os.environ.get("CIBW_TEST_VAR_3")
PATH = os.environ.get("PATH")
if CIBW_TEST_VAR != "a b c":
raise Exception('CIBW_TEST_VAR should equal "a b c". It was "%s"' % CIBW_TEST_VAR)
if CIBW_TEST_VAR_2 != "1":
raise Exception('CIBW_TEST_VAR_2 should equal "1". It was "%s"' % CIBW_TEST_VAR_2)
if CIBW_TEST_VAR_3 != "test string 3":
raise Exception('CIBW_TEST_VAR_3 should equal "test string 3". It was "%s"' % CIBW_TEST_VAR_3)
if "/opt/cibw_test_path" not in PATH:
raise Exception('PATH should contain "/opt/cibw_test_path". It was "%s"' % PATH)
if "$PATH" in PATH:
+9
View File
@@ -1,6 +1,7 @@
import textwrap
from . import test_projects
from . import utils
import os
basic_project = test_projects.new_c_project(
setup_py_add=textwrap.dedent(
@@ -27,6 +28,7 @@ basic_project.files[
[build-system]
requires = [
"setuptools >= 42",
"setuptools_scm[toml]>=4.1.2",
"wheel",
"requests==2.22.0; python_version<'3.6'",
"requests==2.23.0; python_version>='3.6'"
@@ -47,3 +49,10 @@ def test_pep518(tmp_path):
# check that the expected wheels are produced
expected_wheels = utils.expected_wheels("spam", "0.1.0")
assert set(actual_wheels) == set(expected_wheels)
# These checks ensure an extra file is not created when using custom
# workaround; see https://github.com/joerick/cibuildwheel/issues/421
assert not (project_dir / "42").exists()
assert not (project_dir / "4.1.2").exists()
assert len(os.listdir(project_dir)) == len(basic_project.files)
+36
View File
@@ -0,0 +1,36 @@
import subprocess
import pytest
from test import test_projects
from . import utils
pure_python_project = test_projects.TestProject()
pure_python_project.files['setup.py'] = '''
from setuptools import Extension, setup
setup(
name="spam",
py_modules=['spam'],
version="0.1.0",
)
'''
pure_python_project.files['spam.py'] = '''
def a_function():
pass
'''
def test(tmp_path, capfd):
# this test checks that if a pure wheel is generated, the build should
# fail.
project_dir = tmp_path / 'project'
pure_python_project.generate(project_dir)
with pytest.raises(subprocess.CalledProcessError):
actual_wheels = utils.cibuildwheel_run(project_dir)
print('produced wheels:', actual_wheels)
captured = capfd.readouterr()
print('out', captured.out)
print('err', captured.err)
assert "Build failed because a pure Python wheel was generated" in captured.err
+4 -5
View File
@@ -13,11 +13,10 @@ project_with_ssl_tests = test_projects.new_c_project(
else:
from urllib.request import urlopen
if sys.version_info[0:2] == (3, 3):
data = urlopen("https://www.nist.gov")
else:
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
data = urlopen("https://www.nist.gov", context=context)
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
data = urlopen("https://www.nist.gov", context=context)
data = urlopen("https://raw.githubusercontent.com/joerick/cibuildwheel/master/CI.md", context=context)
data = urlopen("https://raw.githubusercontent.com/joerick/cibuildwheel/master/CI.md")
''')
)
+28
View File
@@ -0,0 +1,28 @@
import subprocess
import pytest
from .test_projects import TestProject
from . import utils
so_file_project = TestProject()
so_file_project.files['libnothing.so'] = ''
so_file_project.files['setup.py'] = '''
raise Exception('this build will fail')
'''
def test_failed_project_with_so_files(tmp_path, capfd):
if utils.platform != 'linux':
pytest.skip('this test is only relevant to the linux build')
project_dir = tmp_path / 'project'
so_file_project.generate(project_dir)
with pytest.raises(subprocess.CalledProcessError):
utils.cibuildwheel_run(project_dir)
captured = capfd.readouterr()
print('out', captured.out)
print('err', captured.err)
assert "NOTE: Shared object (.so) files found in this project." in captured.err
+2 -2
View File
@@ -91,10 +91,10 @@ def expected_wheels(package_name, package_version, manylinux_versions=None,
else:
manylinux_versions = ['manylinux2014']
python_abi_tags = ['cp35-cp35m', 'cp36-cp36m', 'cp37-cp37m', 'cp38-cp38']
python_abi_tags = ['cp35-cp35m', 'cp36-cp36m', 'cp37-cp37m', 'cp38-cp38', 'cp39-cp39']
if pm.machine() in ['x86_64', 'AMD64', 'x86']:
python_abi_tags += ['cp27-cp27m', 'pp27-pypy_73', 'pp36-pypy36_pp73']
python_abi_tags += ['cp27-cp27m', 'pp27-pypy_73', 'pp36-pypy36_pp73', 'pp37-pypy37_pp73']
if platform == 'linux':
python_abi_tags.append('cp27-cp27mu') # python 2.7 has 2 different ABI on manylinux
+15
View File
@@ -8,6 +8,7 @@ from pathlib import Path, PurePath
import pytest
from cibuildwheel.docker_container import DockerContainer
from cibuildwheel.environment import EnvironmentAssignment
# for these tests we use manylinux2014 images, because they're available on
# multi architectures and include python3.8
@@ -40,6 +41,13 @@ def test_environment():
assert container.call(['sh', '-c', 'echo $TEST_VAR'], env={'TEST_VAR': '1'}, capture_output=True) == '1\n'
@pytest.mark.docker
def test_cwd():
with DockerContainer(DEFAULT_IMAGE, cwd='/cibuildwheel/working_directory') as container:
assert container.call(['pwd'], capture_output=True) == '/cibuildwheel/working_directory\n'
assert container.call(['pwd'], capture_output=True, cwd='/opt') == '/opt\n'
@pytest.mark.docker
def test_container_removed():
with DockerContainer(DEFAULT_IMAGE) as container:
@@ -145,3 +153,10 @@ def test_dir_operations(tmp_path: Path):
container.copy_out(dst_dir, new_test_dir)
assert test_binary_data == (new_test_dir / 'test.dat').read_bytes()
@pytest.mark.docker
def test_environment_executor():
with DockerContainer(DEFAULT_IMAGE) as container:
assignment = EnvironmentAssignment("TEST=$(echo 42)")
assert assignment.evaluated_value({}, container.environment_executor) == "42"
+31
View File
@@ -0,0 +1,31 @@
import certifi
import pytest
import ssl
from cibuildwheel.util import download
DOWNLOAD_URL = 'https://raw.githubusercontent.com/joerick/cibuildwheel/v1.6.3/requirements-dev.txt'
def test_download(monkeypatch, tmp_path):
monkeypatch.delenv('SSL_CERT_FILE', raising=False)
dest = tmp_path / 'file.txt'
download(DOWNLOAD_URL, dest)
assert len(dest.read_bytes()) == 134
def test_download_good_ssl_cert_file(monkeypatch, tmp_path):
monkeypatch.setenv('SSL_CERT_FILE', certifi.where())
dest = tmp_path / 'file.txt'
download(DOWNLOAD_URL, dest)
assert len(dest.read_bytes()) == 134
def test_download_bad_ssl_cert_file(monkeypatch, tmp_path):
bad_cafile = tmp_path / 'ca.pem'
bad_cafile.write_text('bad certificates')
monkeypatch.setenv('SSL_CERT_FILE', str(bad_cafile))
dest = tmp_path / 'file.txt'
with pytest.raises(ssl.SSLError):
download(DOWNLOAD_URL, dest)