Compare commits

...
267 Commits
Author SHA1 Message Date
Joe Rickerby eed12cf4c9 Bump version: v1.7.3 2021-01-01 13:21:29 +00:00
Joe Rickerby da91d7944d Fix docs version number 2021-01-01 13:06:47 +00:00
probot-auto-merge[bot] 965ced1984 Merge pull request #505 from joerick/update-dependencies-pr
[Bot] Update dependencies
2020-12-31 19:26:48 +00:00
henryiii a015f3425c Update dependencies 2020-12-31 16:52:34 +00:00
Grzegorz BokotaandYannick Jadoul 99203a83f9 fix: patching pypy venv (#502)
Potentially revert / remove on release of PyPy 7.3.4.

* patching linux and macos

* try test

* add patch files for pypy2.7

* fix installing

* Combine patch files into one

* Simplify further, and add test to remind ourselves to remove the PyPy patch

* ignore fail of patch on linux

make new test failing only on linux

* fix test

* add timeout

* fix patch on linux

* change `-N` to `--force`

Co-authored-by: Yannick Jadoul <yannick.jadoul@belgacom.net>
2020-12-31 11:50:19 -05:00
Joe Rickerby 1029a1a123 Merge pull request #503 from joerick/update-dependencies-pr
[Bot] Update dependencies
2020-12-31 14:36:13 +00:00
mayeut 143febd9fa Update dependencies 2020-12-28 06:10:06 +00:00
Henry Schreiner 4e17c275ef fix: adding pyproject.toml 2020-12-27 22:26:31 -05:00
Henry Schreiner 93a095d3de docs: include action form of cibuildwheel 2020-12-27 22:26:31 -05:00
Henry Schreiner 723b5e5128 feat: add support for composite-actions 2020-12-27 22:26:31 -05:00
Henry Schreiner 02f3849738 chore: update projects based on Discussion #485 (#498) 2020-12-27 22:22:34 -05:00
e43b105d28 [Bot] Update dependencies (#495)
* Update dependencies

* chore: bump Python 3.8.6 -> 3.8.7

Co-authored-by: mayeut <mayeut@users.noreply.github.com>
Co-authored-by: Henry Schreiner <henryschreineriii@gmail.com>
2020-12-24 10:00:12 -05:00
Matthieu Darbois 14a6a77f48 Run update workflow weekly (#497) 2020-12-23 23:38:45 +01:00
Matthieu DarboisandJoe Rickerby 40ddede41b Add a workflow to update dependencies (#490)
* Add a workflow to update dependencies

* Use '--no-docker' to run dependency update using local pythons

Default method is to use docker

* Only run the dependency update workflow manually

PR are only created for master

* Create constraints for all python versions

* Use manylinux2010_x86_64:latest to update dependencies

Co-authored-by: Joe Rickerby <joerick@mac.com>
2020-12-21 19:51:27 +01:00
Joe Rickerby ed8a9533c5 Bump version: v1.7.2 2020-12-21 13:20:45 +00:00
Joe Rickerby e439544a1d Fix directive name 2020-12-21 13:15:33 +00:00
Joe Rickerby 4d0db00d79 Merge pull request #493 from joerick/docs-fix
Docs fixes
2020-12-21 13:10:23 +00:00
Joe Rickerby b4fe1aa257 Update mkdocs-include-markdown-plugin 2020-12-21 11:43:27 +00:00
Joe Rickerby 194818ecf7 Fix directive name 2020-12-21 11:40:32 +00:00
Joe Rickerby fb2c6e2e89 Remove symlink hack 2020-12-21 11:40:22 +00:00
Matthieu Darbois 8dff764b23 Merge pull request #489 from henryiii/update-constraints-2020-12-20T14-28-50
Update dependencies
2020-12-21 08:39:28 +01:00
Henry Schreiner b020f9d3e5 chore: bump Python patch versions 2020-12-20 10:48:16 -05:00
Henry Schreiner 095c094420 Update dependencies 2020-12-20 09:29:55 -05:00
Henry SchreinerandJoe Rickerby d83daa3958 docs: use GitHub example in readme (#479)
* docs: use GitHub example in readme

* Apply suggestions from code review

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

* Copy/style tweaks

Co-authored-by: Joe Rickerby <joerick@mac.com>
2020-12-14 19:10:30 -05:00
Joe Rickerby 4f4dae27fb Merge pull request #474 from henryiii/docs/stars
docs: table and add stars
2020-12-13 16:53:37 +00:00
Joe Rickerby c76ee0b39b Add symlink to fix image references in the working-examples page
Hopefully https://github.com/mondeja/mkdocs-include-markdown-plugin/issues/1
will provider a cleaner fix, but for now this works :)
2020-12-12 18:30:55 +00:00
Joe Rickerby c217d5963d Add working examples and changelog docs pages 2020-12-12 18:29:46 +00:00
Joe Rickerby 84a4b0518f Add our own versions of the icons, generated from script 2020-12-12 14:47:14 +00:00
Joe Rickerby dbb65f94bd Run script to update readme 2020-12-12 12:42:43 +00:00
Joe Rickerby 2e165c3e7a Add back the options section 2020-12-12 12:40:04 +00:00
Joe Rickerby 4ac5feb6bb Add note about generated content, update paths 2020-12-12 12:38:01 +00:00
Joe Rickerby 6974680571 Move projects.yml to docs/data 2020-12-12 12:28:20 +00:00
Joe Rickerby 5dd2f56eab Remove the book emoji, seems a little distracting 2020-12-12 12:19:04 +00:00
Joe Rickerby 78b6f86305 Add notes to the popular projects 2020-12-12 12:18:24 +00:00
Joe Rickerby 677e51d137 Use spaces in project names to allow line breaks and keep column narrow 2020-12-12 12:15:47 +00:00
Henry Schreiner f9a5ec84d9 Update bin/projects.yml 2020-12-08 21:53:16 -05:00
Henry SchreinerandMatthieu Darbois 044a5dab37 docs: pybase64 moved
Co-authored-by: Matthieu Darbois <mayeut@users.noreply.github.com>
2020-12-08 17:57:04 -05:00
Joe Rickerby 00a217d4a6 Merge pull request #478 from joerick/henryiii-patch-1
docs: minor wording change for multibuild
2020-12-08 19:01:15 +00:00
Henry Schreiner 318e768292 docs: minor wording change for multibuild 2020-12-07 20:16:29 -05:00
Henry Schreiner 9bfd0f7956 fix: drop stars, fix a few more projects 2020-12-07 09:31:08 -05:00
Álvaro Mondéjar eae34832ec Separate 'mkdocs_include_markdown_plugin' from project (#475) 2020-12-06 16:55:04 +01:00
Henry Schreiner 3ac943b754 chore: run bin/projects.py 2020-12-04 16:52:08 -05:00
Henry Schreiner b3bb527584 feat: PyGithub and direct writing 2020-12-04 16:43:01 -05:00
Henry Schreiner c166426b50 chore: update repos to add CI and plat, more 2020-12-04 15:46:22 -05:00
Henry Schreiner bf011b51f9 feat: CI info 2020-12-04 14:51:17 -05:00
Henry Schreiner abbe91cf86 feat: generator 2020-12-04 12:09:22 -05:00
Henry Schreiner d1ba5b8419 docs: sort by stars 2020-12-03 17:34:14 -05:00
Henry Schreiner 64a093756c docs: repo table with stars 2020-12-03 17:16:51 -05:00
Joe Rickerby 49077c2a36 Bump version: v1.7.1 2020-12-03 18:02:15 +00:00
Matthew Treinish e94274db07 Bump pinned default manylinux2010 image version (#472)
The current pinned version of the manylinux2010 docker image has an
issue where it is trying to use EoL yum repositories
(see pypa/manylinux#836 for more details). The repository path has been
updated on the latest image. This commit bumps the manylinux2010 docker
image version to use the latest version to get this fix.
2020-12-03 17:59:29 +01:00
Joe Rickerby 3c77465100 Merge pull request #471 from nedbat/patch-1
Add coverage.py to the repos list
2020-12-01 08:56:00 +00:00
Ned Batchelder 0f459d378c Add coverage.py to the repos list
I wish I could say I was doing something interesting with cibuildwheel, but the thing I love about it is that it just worked right out of the box! Thanks so much for building it!!
2020-11-29 07:01:47 -05:00
Joe Rickerby 0fb2ead6fb Bump version: v1.7.0 2020-11-26 23:29:34 +00:00
Joe Rickerby dcf703c67e Show the PR link before asking for new version number 2020-11-26 23:26:17 +00:00
Joe Rickerby edbbdb6861 Merge pull request #467 from joerick/update-constraints-2020-11-26T18-06-10
Update dependencies
2020-11-26 23:23:30 +00:00
Joe Rickerby 54877b96e3 Update dependencies 2020-11-26 18:06:44 +00:00
Joe Rickerby e0f2f8fdac Merge pull request #458 from joerick/logger
Improve CI logs using fold groups
2020-11-26 17:44:49 +00:00
Joe Rickerby c065e3ce2d Scrap the stderr->stdout redirect (we don't seem to need it)
Let's keep an eye on this and if we see output outside of the fold
groups we can add it back
2020-11-24 19:04:27 +00:00
Joe Rickerby 27bda4fa64 Hide some errant output 2020-11-24 19:02:50 +00:00
Joe Rickerby 5665b61cbf Double-check this 2020-11-24 18:53:43 +00:00
Joe Rickerby 4c035a441b Try using an Unbuffered sys.stderr 2020-11-24 18:48:27 +00:00
Joe Rickerby ba01ec546e Update pr-labels-action 2020-11-24 09:05:14 +00:00
Joe Rickerby b9cf466cd8 Merge pull request #445 from jbarlow83/patch-3
README: Mention which CIs support ARM builds
2020-11-24 09:00:56 +00:00
Joe Rickerby 6413732187 Merge pull request #464 from YannickJadoul/manylinux-python-version
Ensure modern version of Python in CIBW_BEFORE_ALL on manylinux
2020-11-24 08:58:51 +00:00
jbarlow83andHenry Schreiner 10c244d827 Update README.md
Co-authored-by: Henry Schreiner <HenrySchreinerIII@gmail.com>
2020-11-23 16:42:58 -08:00
Joe Rickerby bfd9bb482b Fix unit test 2020-11-23 21:21:40 +00:00
Joe Rickerby c2a7cdf98a Fix flake8 errors 2020-11-23 21:06:36 +00:00
Joe Rickerby f8a4fbe42d Share CI platform detection 2020-11-23 21:00:22 +00:00
Joe Rickerby 95fecc2d58 Remove debug code 2020-11-23 20:56:24 +00:00
Joe Rickerby ece358f29d lowercase for command line argument 2020-11-23 20:24:08 +00:00
Yannick Jadoul 6f3fcf8b12 Fix PATH of CPython 3.8 binary for CIBW_BEFORE_ALL 2020-11-23 00:49:32 +01:00
Yannick Jadoul c67de74e28 Demonstrate old version of Python in CIBW_BEFORE_ALL on manylinux 2020-11-23 00:41:52 +01:00
Yannick Jadoul 2f4ed1fafc Update to PyPy 7.3.3 (#460)
* Test PyPy 7.3.3rc1

* Revert "Update Travis CI and CircleCI to use macOS 10.14 " and "Change examples to use macOS >= 10.14"

This reverts commits 870bf3f740 and cd53552b4b.

* PyPy 7.3.3rc2

* PyPy 7.3.3 released

* Revert to using pypywheels docker images
2020-11-22 14:55:04 +01:00
Joe Rickerby 05d7c142e9 Subprocess stderr goes to stdout on Mac and Windows too 2020-11-22 10:35:40 +00:00
Joe Rickerby e84c6b2de0 Remove old sample build workflow 2020-11-22 01:20:14 +00:00
Joe Rickerby a93cee1a30 Run a sample build before tests on PRs with this label 2020-11-22 01:15:44 +00:00
Joe Rickerby d3f57bbb22 Merge pull request #461 from joerick/azure-errexit
Use set -o errexit in the Azure example
2020-11-20 10:07:43 +00:00
Henry Schreiner a50be4d820 Update README.md 2020-11-19 10:23:37 -05:00
Henry Schreiner b8a41130c3 Update README.md 2020-11-19 10:22:55 -05:00
Joe Rickerby 9d731cd440 Make the sample build only happen from a manual trigger 2020-11-14 14:52:20 +00:00
Joe Rickerby 309222cca3 Merge remote-tracking branch 'origin/master' into logger 2020-11-14 14:51:18 +00:00
Joe Rickerby fe6eadc1f2 Merge remote-tracking branch 'origin/master' into logger 2020-11-14 14:50:52 +00:00
Joe Rickerby 91906b2aea Skip the example output test 2020-11-14 14:50:29 +00:00
Joe Rickerby 0760c330cf Merge pull request #462 from joerick/github-triggers
Improve Github triggers to prevent multiple runs on origin branches
2020-11-14 14:46:30 +00:00
Joe Rickerby d054b45ecf Perhaps displayName must come second 2020-11-14 14:33:58 +00:00
Joe Rickerby 8606c4771e Add explicit sample build test to keep the first test simple 2020-11-14 14:28:47 +00:00
Joe Rickerby 4c94e7ef20 Add back newline after stage header. Also flush stdout to help with ordering 2020-11-14 14:28:17 +00:00
Joe Rickerby c56448eba7 Named steps and set -o errexit 2020-11-13 19:20:16 +00:00
Joe Rickerby ebe632eff0 Limit push to master instead 2020-11-13 19:15:17 +00:00
Joe Rickerby a732525084 Move encoding switch to before the unicode decision is made 2020-11-13 19:04:02 +00:00
Joe Rickerby e8aef6962a Set output to UTF8 on windows (on Python >= 3.7) 2020-11-13 18:57:07 +00:00
Joe Rickerby fba3248163 Remove encoding debug code 2020-11-13 18:46:41 +00:00
Joe Rickerby 113350b7fb Remove unicode test 2020-11-13 18:37:48 +00:00
Joe Rickerby 54858bbd64 Support non-unicode stdout 2020-11-13 18:37:30 +00:00
Joe Rickerby 0227b9d941 Improve debug code 2020-11-13 17:44:13 +00:00
Joe Rickerby df71e028a9 grumble 2020-11-13 17:41:43 +00:00
Joe Rickerby 8e2381bfb1 add some encoding debug code 2020-11-13 17:40:07 +00:00
Joe Rickerby 3d59c56584 Ensure sample build shell is bash on Windows 2020-11-13 17:32:49 +00:00
Joe Rickerby 57d38efd4d Add mac/windows sample builds 2020-11-13 17:21:14 +00:00
Joe Rickerby 1f830a3626 Improve Github triggers to prevent multiple runs on origin branches 2020-11-13 17:08:20 +00:00
Joe Rickerby 1ab1130fe1 Move initialization of the global logger to the end of the file 2020-11-13 16:51:26 +00:00
Joe Rickerby 931f8e106e Shorten the travis IDs 2020-11-13 16:46:58 +00:00
Joe Rickerby 8b8d6d749c Prevent double-builds of the sample 2020-11-13 16:33:59 +00:00
Joe Rickerby 38297e6663 Add log steps to macOS/Windows 2020-11-13 16:30:35 +00:00
Joe RickerbyandHenry Schreiner 246aa0848e Update cibuildwheel/util.py
Co-authored-by: Henry Schreiner <HenrySchreinerIII@gmail.com>
2020-11-13 15:38:34 +00:00
Joe Rickerby 7914432a68 fix appearance on Travis with headers and identifiers 2020-11-13 15:26:06 +00:00
Joe Rickerby 5e99d962f5 Wrap the sample build output in a fold group 2020-11-13 15:22:43 +00:00
Joe Rickerby df04fa5ac3 Use set -o errexit in the Azure example 2020-11-13 14:57:09 +00:00
Joe Rickerby 8e38132000 Merge pull request #454 from nsoranzo/patch-1
Update repos using cibuildwheel
2020-11-13 09:31:26 +00:00
Joe Rickerby 8108deacfe Don't capture the output of the first test 2020-11-05 23:10:25 +00:00
Joe Rickerby c9ea0251fe Sample build uses a testcase failure project 2020-11-04 16:08:40 +00:00
Joe Rickerby fbbc295901 Starting a build implicitly closes a log step 2020-11-04 16:08:24 +00:00
Joe Rickerby 888da8274c GHA build tweak 2020-11-04 15:43:27 +00:00
Joe Rickerby 06b6823637 Remove some unnecessary step_end calls 2020-11-04 11:48:12 +00:00
Joe Rickerby 2f9ee793f0 Adjust sample build to show passing/failing test
Drop the 'allow fail' approach, it shows up as red in PR/commit status
2020-11-04 11:38:03 +00:00
Joe Rickerby 75c6e6a0a4 Improvements from code review 2020-11-04 11:11:42 +00:00
Joe Rickerby c5bbfb3cc6 ...and make that step fail 2020-11-03 09:15:22 +00:00
Joe Rickerby 53ee55bad7 and again 2020-11-03 09:13:42 +00:00
Joe Rickerby 225342c777 fix syntax 2020-11-03 09:12:19 +00:00
Joe Rickerby 8808add708 Try allow failure Github job 2020-11-03 08:51:45 +00:00
Joe Rickerby fa4a0cbd33 Improve error output 2020-11-01 21:36:44 +00:00
Joe Rickerby 4a736cdcb1 Improve options output 2020-11-01 21:17:25 +00:00
Joe Rickerby 4b402e0593 Experiment 2020-11-01 20:44:38 +00:00
Joe Rickerby 4eff3bc7a8 Add a failure example build 2020-11-01 17:06:55 +00:00
Joe Rickerby 0a32e3bc0e Improve appearance outside CI 2020-11-01 16:57:22 +00:00
Joe Rickerby b22001b26d Add build end message 2020-11-01 15:19:42 +00:00
Joe Rickerby 39b94b7dec Tidy up log output 2020-11-01 15:19:25 +00:00
Joe Rickerby 152483bcb4 Try putting all build output on stdout 2020-11-01 15:16:28 +00:00
Joe Rickerby f51c8dc1e3 More tweaks 2020-11-01 12:33:14 +00:00
Joe Rickerby 45c723cdea Fix folding 2020-11-01 12:03:21 +00:00
Joe Rickerby dac4006083 More formatting tweaks 2020-11-01 12:00:59 +00:00
Joe Rickerby f48a84d92f Improve some formatting 2020-11-01 11:43:28 +00:00
Joe Rickerby 38e7b5a91d Change to an imperative-style API 2020-11-01 11:34:02 +00:00
Yannick Jadoul beda0e5ce8 Add description to Parselmouth in README.md 2020-10-31 20:57:45 +01:00
Nicola SoranzoandJoe Rickerby 957a4fb8e1 Add context to repos
Co-authored-by: Joe Rickerby <joerick@mac.com>
2020-10-31 20:57:45 +01:00
Nicola Soranzo 7e4b44b6ee Add Matplotlib, twisted-iocpsupport and bx-python 2020-10-31 20:57:45 +01:00
Nicola Soranzo a494f9bbe5 twisted not using cibuildwheel any more 2020-10-31 20:57:45 +01:00
Joe Rickerby 946306b21d Fix sample project gen command 2020-10-31 18:19:02 +00:00
Joe Rickerby 0191496fc9 Install dependencies in sample build 2020-10-31 18:17:36 +00:00
Joe Rickerby 4ec28cb37e Fix flake8 2020-10-31 18:16:23 +00:00
Joe Rickerby 136adebf09 Add a github action to run a sample build to check output 2020-10-31 18:13:31 +00:00
Joe Rickerby 461aa35f99 Initial commit of logger functionality 2020-10-31 17:48:34 +00:00
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
jbarlow83 c89b74604d README: Mention which CIs support ARM builds 2020-10-08 01:35:22 -07: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
Joe Rickerby c0cb43800b Bump version: v1.5.4 2020-07-19 22:40:33 +01:00
Joe Rickerby cc4e8975c8 Merge pull request #408 from YannickJadoul/fix-bashlex_eval-quotes
Fix quotes in command in bashlex_eval
2020-07-19 19:47:05 +01:00
Joe Rickerby c5a9837784 Update cibuildwheel/bashlex_eval.py 2020-07-19 19:46:40 +01:00
Joe Rickerby ceecee0e68 Merge pull request #407 from samuelstjean/patch-1
fix typo in doc
2020-07-19 19:40:48 +01:00
Yannick Jadoul 28af49a006 Simplify by removing shlex.quote and shlex.split when using EnvironmentExecutor 2020-07-19 17:37:25 +02:00
Yannick Jadoul 3a2d7a21b1 Fix quotes-in-commandsubstitution problem with well-placed shlex.quote 2020-07-19 17:32:07 +02:00
Yannick Jadoul 44fd8b5c26 Fix test to demonstrate failure 2020-07-19 17:19:48 +02:00
Samuel St-Jean fddfaba0a4 fix typo 2020-07-19 10:32:27 -04: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
91 changed files with 2648 additions and 628 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: 9.4.1
environment:
PYTHON: python3
steps:
@@ -54,6 +38,5 @@ workflows:
version: 2
all-tests:
jobs:
- flake8-mypy
- osx-python3.6
- linux-python3.6
+25 -4
View File
@@ -1,22 +1,32 @@
name: Test
on:
push: {}
push:
branches:
- master
pull_request:
paths-ignore:
- 'docs/**'
workflow_dispatch:
# allow manual runs on branches without a PR
jobs:
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'
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:
name: Test cibuildwheel on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
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
@@ -27,10 +37,21 @@ jobs:
- name: Install dependencies
run: |
python -m pip install -r requirements-dev.txt
- name: Install Visual C++ for Python 2.7
if: runner.os == 'Windows'
run: |
choco install vcpython27 -f -y
- name: Get PR labels
id: pr-labels
uses: joerick/pr-labels-action@v1.0.6
- name: Sample build
if: contains(steps.pr-labels.outputs.labels, ' ci-sample-build ')
run: |
python bin/sample_build.py
- name: Test cibuildwheel
run: |
python ./bin/run_tests.py
+34
View File
@@ -0,0 +1,34 @@
name: Update dependencies
on:
workflow_dispatch:
schedule:
- cron: '0 6 * * 1' # "At 06:00 on Monday."
jobs:
update-dependencies:
name: Update dependencies
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
name: Install Python 3.9
with:
python-version: 3.9
architecture: x64
- name: Install dependencies
run: python -m pip install requests pip-tools
- name: Run update
run: python ./bin/update_dependencies.py
- name: Create Pull Request
if: github.ref == 'refs/heads/master'
uses: peter-evans/create-pull-request@v3
with:
commit-message: Update dependencies
title: '[Bot] Update dependencies'
body: |
Update the versions of our dependencies.
PR generated by "Update dependencies" [workflow](https://github.com/${{github.repository}}/actions/runs/${{github.run_id}}).
branch: update-dependencies-pr
delete-branch: true
+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)|(.svg$)
- id: mixed-line-ending
- id: trailing-whitespace
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v0.782
hooks:
- id: mypy
files: ^(cibuildwheel/|test/|bin/projects.py)
pass_filenames: false
+4 -2
View File
@@ -28,7 +28,9 @@ jobs:
- name: macOS | x86_64 | Python 3.x
os: osx
env: PYTHON=python3
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 +54,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
+293 -69
View File
@@ -9,7 +9,7 @@ cibuildwheel
Python wheels are great. Building them across **Mac, Linux, Windows**, on **multiple versions of Python**, is not.
`cibuildwheel` is here to help. `cibuildwheel` runs on your CI server - currently it supports Azure Pipelines, Travis CI, AppVeyor, GitHub Actions and CircleCI - and it builds and tests your wheels across all of your platforms.
`cibuildwheel` is here to help. `cibuildwheel` runs on your CI server - currently it supports GitHub Actions, Azure Pipelines, Travis CI, AppVeyor, and CircleCI - and it builds and tests your wheels across all of your platforms.
What does it do?
@@ -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.3 | ✅ | | ✅ | ✅ | | | | |
| PyPy 3.6 v7.3.3 | ✅ | | ✅ | ✅ | | | | |
| PyPy 3.7 (beta) v7.3.3 | ✅ | | ✅ | ✅ | | | | |
<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,64 +38,61 @@ 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 |
|-----------------|-------|-------|---------|
| Azure Pipelines | ✅ | ✅ | ✅ |
| Travis CI | ✅ | ✅ | ✅ |
| AppVeyor | ✅ | ✅ | ✅ |
| GitHub Actions | ✅ | ✅ | ✅ |
| CircleCI | ✅ | ✅ | |
| | Linux | macOS | Windows | Linux ARM |
|-----------------|-------|-------|---------|--------------|
| Azure Pipelines | ✅ | ✅ | ✅ | ✴️¹ |
| Travis CI | ✅ | ✅ | ✅ | ✅ |
| 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.
<sup>¹ Requires a "third-party build host"; expected to work with cibuildwheel but not directly tested by our CI.</sup><br>
`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-->
Example setup
-------------
To build manylinux, macOS, and Windows wheels on Travis CI and upload them to PyPI whenever you tag a version, you could use this `.travis.yml`:
To build manylinux, macOS, and Windows wheels on Github Actions, you could use this `.github/workflows/wheels.yml`:
```yaml
language: python
name: Build
on: [push, pull_request]
jobs:
include:
# perform a linux build
- services: docker
# and a mac build
- os: osx
language: shell
# and a windows build
- os: windows
language: shell
before_install:
- choco install python --version 3.8.0
- export PATH="/c/Python38:/c/Python38/Scripts:$PATH"
build_wheels:
name: Build wheels on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-20.04, windows-2019, macOS-10.15]
env:
global:
- TWINE_USERNAME=__token__
# Note: TWINE_PASSWORD is set to a PyPI API token in Travis settings
steps:
- uses: actions/checkout@v2
install:
- python3 -m pip install cibuildwheel==1.5.3
- uses: actions/setup-python@v2
name: Install Python
script:
# build the wheels, put them into './wheelhouse'
- python3 -m cibuildwheel --output-dir wheelhouse
- name: Install cibuildwheel
run: python -m pip install cibuildwheel==1.7.3
after_success:
# if the release was tagged, upload them to PyPI
- |
if [[ $TRAVIS_TAG ]]; then
python3 -m pip install twine
python3 -m twine upload wheelhouse/*.whl
fi
- name: Build wheels
run: python -m cibuildwheel --output-dir wheelhouse
env:
CIBW_SKIP: "cp27-* pp27-*" # skip Python 2.7 wheels
- uses: actions/upload-artifact@v2
with:
path: ./wheelhouse/*.whl
```
For more information, including how to build on GitHub Actions, Appveyor, Azure Pipelines, or CircleCI, check out the [documentation](https://cibuildwheel.readthedocs.org) and the [examples](https://github.com/joerick/cibuildwheel/tree/master/examples).
For more information, including building on Python 2, PyPI deployment, and the use of other CI services like Travis CI, Appveyor, Azure Pipelines, or CircleCI, check out the [documentation](https://cibuildwheel.readthedocs.org) and the [examples](https://github.com/joerick/cibuildwheel/tree/master/examples).
Options
-------
@@ -119,26 +117,144 @@ Options
Working examples
----------------
<!--working-examples-start-->
Here are some repos that use cibuildwheel.
- [pyinstrument_cext](https://github.com/joerick/pyinstrument_cext)
- [websockets](https://github.com/aaugustin/websockets)
- [Parselmouth](https://github.com/YannickJadoul/Parselmouth)
- [python-admesh](https://github.com/admesh/python-admesh)
- [pybase64](https://github.com/mayeut/pybase64)
- [KDEpy](https://github.com/tommyod/KDEpy)
- [AutoPy](https://github.com/autopilot-rs/autopy)
- [apriltags2-ethz](https://github.com/safijari/apriltags2_ethz)
- [TgCrypto](https://github.com/pyrogram/tgcrypto)
- [Twisted](https://github.com/twisted/twisted)
- [gmic-py](https://github.com/dtschump/gmic-py)
- [creme](https://github.com/creme-ml/creme)
- [PyAV](https://github.com/PyAV-Org/PyAV)
- [aiortc](https://github.com/aiortc/aiortc)
- [aioquic](https://github.com/aiortc/aioquic)
- [pikepdf](https://github.com/pikepdf/pikepdf)
<!-- START bin/projects.py -->
> Add your repo here! Send a PR.
<!-- this section is generated by bin/projects.py. Don't edit it directly, instead, edit docs/data/projects.yml -->
| Name | CI | OS | Notes |
|-----------------------------------|----|----|:------|
| [scikit-learn][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | The machine learning library. A complex but clean config using many of cibuildwheel's features to build a large project with Cython and C++ extensions. |
| [Matplotlib][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | The venerable Matplotlib, a Python library with C++ portions |
| [psutil][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Cross-platform lib for process and system monitoring in Python |
| [twisted-iocpsupport][] | ![github icon][] | ![windows icon][] | A submodule of Twisted that hooks into native C APIs using Cython. |
| [scikit-image][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Image processing library. Uses cibuildwheel to build and test a project that uses Cython with platform-native code. |
| [websockets][] | ![travisci icon][] | ![apple icon][] ![linux icon][] | Library for building WebSocket servers and clients. Mostly written in Python, with a small C 'speedups' extension module. |
| [pyzmq][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Python bindings for zeromq, the networking library. Uses Cython and CFFI. |
| [aiortc][] | ![github icon][] | ![apple icon][] ![linux icon][] | WebRTC and ORTC implementation for Python using asyncio. |
| [h5py][] | ![azurepipelines icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | HDF5 for Python -- The h5py package is a Pythonic interface to the HDF5 binary data format. |
| [coverage.py][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | The coverage tool for Python |
| [River][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | 🌊 Online machine learning in Python |
| [PyAV][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Pythonic bindings for FFmpeg's libraries. |
| [Dependency Injector][] | ![travisci icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Dependency injection framework for Python, uses Windows TravisCI |
| [aioquic][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | QUIC and HTTP/3 implementation in Python |
| [google neuroglancer][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | WebGL-based viewer for volumetric data |
| [AutoPy][] | ![travisci icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Includes a Windows Travis build. |
| [pikepdf][] | ![azurepipelines icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | A Python library for reading and writing PDF, powered by qpdf |
| [Parselmouth][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | A Python interface to the Praat software package, using pybind11, C++17 and CMake, with the core Praat static library built only once and shared between wheels. |
| [python-rapidjson][] | ![travisci icon][] ![gitlab icon][] ![appveyor icon][] | ![windows icon][] ![linux icon][] | Python wrapper around rapidjson |
| [Rtree][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Rtree: spatial index for Python GIS ¶ |
| [KDEpy][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Kernel Density Estimation in Python |
| [pybind11 python_example][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Example pybind11 module built with a Python-based build system |
| [pybind11 cmake_example][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Example pybind11 module built with a CMake-based build system |
| [iminuit][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Jupyter-friendly Python interface for C++ MINUIT2 |
| [jq.py][] | ![travisci icon][] | ![apple icon][] ![linux icon][] | Python bindings for jq |
| [bx-python][] | ![travisci icon][] | ![apple icon][] ![linux icon][] | A library that includes Cython extensions. |
| [boost-histogram][] | ![github icon][] ![travisci icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Supports full range of wheels, including PyPy and alternate archs. |
| [pybase64][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Fast Base64 encoding/decoding in Python |
| [TgCrypto][] | ![travisci icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Includes a Windows Travis build. |
| [etebase-py][] | ![travisci icon][] | ![linux icon][] | Python bindings to a Rust library using `setuptools-rust`, and `sccache` for improved speed. |
| [pyjet][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | The interface between FastJet and NumPy |
| [numpythia][] | ![github icon][] | ![apple icon][] ![linux icon][] | The interface between PYTHIA and NumPy |
| [fathon][] | ![travisci icon][] | ![apple icon][] ![linux icon][] | python package for DFA (Detrended Fluctuation Analysis) and related algorithms |
| [pyinstrument_cext][] | ![travisci icon][] ![appveyor icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | A simple C extension, without external dependencies |
| [xmlstarlet][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Python 3.6+ CFFI bindings with true MSVC build. |
| [pybind11 scikit_build_example][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | An example combining scikit-build and pybind11 |
[scikit-learn]: https://github.com/scikit-learn/scikit-learn
[Matplotlib]: https://github.com/matplotlib/matplotlib
[psutil]: https://github.com/giampaolo/psutil
[twisted-iocpsupport]: https://github.com/twisted/twisted-iocpsupport
[scikit-image]: https://github.com/scikit-image/scikit-image
[websockets]: https://github.com/aaugustin/websockets
[pyzmq]: https://github.com/zeromq/pyzmq
[aiortc]: https://github.com/aiortc/aiortc
[h5py]: https://github.com/h5py/h5py
[coverage.py]: https://github.com/nedbat/coveragepy
[River]: https://github.com/online-ml/river
[PyAV]: https://github.com/PyAV-Org/PyAV
[Dependency Injector]: https://github.com/ets-labs/python-dependency-injector
[aioquic]: https://github.com/aiortc/aioquic
[google neuroglancer]: https://github.com/google/neuroglancer
[AutoPy]: https://github.com/autopilot-rs/autopy
[pikepdf]: https://github.com/pikepdf/pikepdf
[Parselmouth]: https://github.com/YannickJadoul/Parselmouth
[python-rapidjson]: https://github.com/python-rapidjson/python-rapidjson
[Rtree]: https://github.com/Toblerity/rtree
[KDEpy]: https://github.com/tommyod/KDEpy
[pybind11 python_example]: https://github.com/pybind/python_example
[pybind11 cmake_example]: https://github.com/pybind/cmake_example
[iminuit]: https://github.com/scikit-hep/iminuit
[jq.py]: https://github.com/mwilliamson/jq.py
[bx-python]: https://github.com/bxlab/bx-python
[boost-histogram]: https://github.com/scikit-hep/boost-histogram
[pybase64]: https://github.com/mayeut/pybase64
[TgCrypto]: https://github.com/pyrogram/tgcrypto
[etebase-py]: https://github.com/etesync/etebase-py
[pyjet]: https://github.com/scikit-hep/pyjet
[numpythia]: https://github.com/scikit-hep/numpythia
[fathon]: https://github.com/stfbnc/fathon
[pyinstrument_cext]: https://github.com/joerick/pyinstrument_cext
[xmlstarlet]: https://github.com/dimitern/xmlstarlet
[pybind11 scikit_build_example]: https://github.com/pybind/scikit_build_example
[appveyor icon]: docs/data/readme_icons/appveyor.svg
[github icon]: docs/data/readme_icons/github.svg
[azurepipelines icon]: docs/data/readme_icons/azurepipelines.svg
[circleci icon]: docs/data/readme_icons/circleci.svg
[gitlab icon]: docs/data/readme_icons/gitlab.svg
[travisci icon]: docs/data/readme_icons/travisci.svg
[windows icon]: docs/data/readme_icons/windows.svg
[apple icon]: docs/data/readme_icons/apple.svg
[linux icon]: docs/data/readme_icons/linux.svg
<!-- scikit-learn: 43477, last pushed 0 days ago -->
<!-- Matplotlib: 12823, last pushed 0 days ago -->
<!-- psutil: 6887, last pushed 0 days ago -->
<!-- twisted-iocpsupport: 4114, last pushed 2 days ago -->
<!-- scikit-image: 4104, last pushed 0 days ago -->
<!-- websockets: 3089, last pushed 10 days ago -->
<!-- pyzmq: 2654, last pushed 20 days ago -->
<!-- aiortc: 2073, last pushed 7 days ago -->
<!-- h5py: 1455, last pushed 12 days ago -->
<!-- coverage.py: 1441, last pushed 3 days ago -->
<!-- River: 1219, last pushed 0 days ago -->
<!-- PyAV: 1114, last pushed 14 days ago -->
<!-- Dependency Injector: 1030, last pushed 0 days ago -->
<!-- aioquic: 552, last pushed 49 days ago -->
<!-- google neuroglancer: 550, last pushed 7 days ago -->
<!-- AutoPy: 507, last pushed 105 days ago -->
<!-- pikepdf: 487, last pushed 0 days ago -->
<!-- Parselmouth: 433, last pushed 26 days ago -->
<!-- python-rapidjson: 407, last pushed 10 days ago -->
<!-- Rtree: 378, last pushed 0 days ago -->
<!-- KDEpy: 230, last pushed 9 days ago -->
<!-- pybind11 python_example: 221, last pushed 44 days ago -->
<!-- pybind11 cmake_example: 219, last pushed 7 days ago -->
<!-- iminuit: 166, last pushed 0 days ago -->
<!-- jq.py: 138, last pushed 73 days ago -->
<!-- bx-python: 94, last pushed 1 days ago -->
<!-- boost-histogram: 63, last pushed 0 days ago -->
<!-- pybase64: 52, last pushed 2 days ago -->
<!-- TgCrypto: 49, last pushed 36 days ago -->
<!-- etebase-py: 40, last pushed 3 days ago -->
<!-- pyjet: 27, last pushed 29 days ago -->
<!-- numpythia: 23, last pushed 28 days ago -->
<!-- fathon: 18, last pushed 1 days ago -->
<!-- pyinstrument_cext: 10, last pushed 29 days ago -->
<!-- xmlstarlet: 7, last pushed 0 days ago -->
<!-- pybind11 scikit_build_example: 0, last pushed 42 days ago -->
<!-- END bin/projects.py -->
> Add your repo here! Send a PR, adding your information to `docs/data/projects.yml`.
>
> <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>
<!--working-examples-end-->
Legal note
----------
@@ -152,6 +268,111 @@ This is similar to static linking, so it might have some licence implications. C
Changelog
=========
<!--changelog-start-->
### 1.7.3
_1 January 2021_
- 🛠 Added a patch for Pypy to ensure header files are available for building
in a virtualenv. (#502)
- 🛠 Some preparatory work towards using cibuildwheel as a Github Action.
Check out
[the FAQ](https://cibuildwheel.readthedocs.io/en/stable/faq/#option-1-github-action)
for information on how to use it. We'll be fully updating the docs to this
approach in a subsequent release (#494)
### 1.7.2
_21 December 2020_
- 🛠 Update dependencies, notably wheel==0.36.2 and pip==20.3.3, and CPython to
their latest bugfix releases (#489)
- 📚 Switch to a Github example in the README (#479)
- 📚 Create Working Examples table, with many projects that use cibuildwheel (#474)
- 📚 Import Working Examples table and Changelog to docs
### 1.7.1
_3 December 2020_
- 🛠 Update manylinux2010 image to resolve issues with 'yum' repositories
(#472)
### 1.7.0
_26 November 2020_
- ✨ New logging format, that uses 'fold groups' in CI services that support
it. (#458)
- 🛠 Update PyPy to 7.3.3 (#460)
- 🐛 Fix a bug where CIBW_BEFORE_ALL runs with a very old version of Python on
Linux. (#464)
### 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_
- 🐛 Fix a bug that would cause command substitutions in CIBW_ENVIRONMENT
variables to not interpret quotes in commands correctly (#406, #408)
### 1.5.3
_19 July 2020_
@@ -478,6 +699,8 @@ _31 March 2017_
- 🌟 First public release!
<!--changelog-end-->
Contributing
============
@@ -489,6 +712,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
-------
@@ -510,4 +734,4 @@ See also
If you'd like to keep wheel building separate from the package itself, check out [astrofrog/autowheel](https://github.com/astrofrog/autowheel). It builds packages using cibuildwheel from source distributions on PyPI.
If `cibuildwheel` is too limited for your needs, consider [matthew-brett/multibuild](http://github.com/matthew-brett/multibuild). `multibuild` is a toolbox for building a wheel on various platforms. It can do a lot more than this project - it's used to build SciPy!
Another very similar tool to consider is [matthew-brett/multibuild](http://github.com/matthew-brett/multibuild). `multibuild` is a shell script toolbox for building a wheel on various platforms. It is used as a basis to build some of the big data science tools, like SciPy.
+26
View File
@@ -0,0 +1,26 @@
name: cibuildwheel
description: 'Installs and runs cibuildwheel on the current runner'
inputs:
package-dir:
description: 'Input directory, defaults to "."'
required: false
default: .
output-dir:
description: 'Folder to place the outputs in, defaults to "wheelhouse"'
required: false
default: wheelhouse
branding:
icon: package
color: yellow
runs:
using: composite
steps:
# This needs powershell-core because github.action path is a Windows-style
# path on Windows. Powershell-core understands both types of paths.
- run: python -m pip install ${{ github.action_path }}
shell: pwsh
- run: python -m cibuildwheel ${{ inputs.package-dir }} --output-dir ${{ inputs.output-dir }}
shell: bash
+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:
+26 -3
View File
@@ -7,18 +7,41 @@ import cibuildwheel
from packaging.version import Version, InvalidVersion
import subprocess
import glob
import urllib.parse
config = [
# file path, version find/replace format
('cibuildwheel/__init__.py', "__version__ = '{}'"),
('setup.py', "version='{}'"),
('README.md', "cibuildwheel=={}"),
('cibuildwheel/__init__.py', "__version__ = '{}'"),
('docs/faq.md', "cibuildwheel=={}"),
('docs/faq.md', "cibuildwheel@v{}"),
('docs/setup.md', "cibuildwheel@v{}"),
('examples/*', "cibuildwheel=={}"),
('setup.py', "version='{}'"),
]
@click.command()
def bump_version():
current_version = cibuildwheel.__version__
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.')
git_changes_result = subprocess.run(['git diff-index --quiet HEAD --'], shell=True)
repo_has_uncommitted_changes = git_changes_result.returncode != 0
@@ -26,7 +49,6 @@ def bump_version():
print('error: Uncommitted changes detected.')
exit(1)
current_version = cibuildwheel.__version__
print( 'Current version:', current_version) # noqa
new_version = input(' New version: ').strip()
@@ -87,6 +109,7 @@ def bump_version():
print('Files updated. If you want to update the changelog as part of this')
print('commit, do that now.')
print()
while input('Type "done" to continue: ').strip().lower() != 'done':
pass
+198
View File
@@ -0,0 +1,198 @@
#!/usr/bin/env python3
"""
Convert a yaml project list into a nice table.
Suggested usage:
./bin/projects.py docs/data/projects.yml --online --auth $GITHUB_API_TOKEN --readme README.md
git diff
"""
import builtins
import functools
from datetime import datetime
from io import StringIO
from typing import Dict, Any, List, Optional, TextIO
import click
import yaml
from github import Github
import urllib.request
import xml.dom.minidom
from pathlib import Path
ICONS = (
"appveyor",
"github",
"azurepipelines",
"circleci",
"gitlab",
"travisci",
"windows",
"apple",
"linux",
)
class Project:
NAME: int = 0
def __init__(self, config: Dict[str, Any], github: Optional[Github] = None):
try:
self.name: str = config["name"]
self.gh: str = config["gh"]
except KeyError:
print("Invalid config, needs at least gh and name!", config)
raise
self.stars_repo: str = config.get("stars", self.gh)
self.notes: str = config.get("notes", "")
self.ci: List[str] = config.get("ci", [])
self.os: List[str] = config.get("os", [])
self.online = github is not None
if github is not None:
repo = github.get_repo(self.stars_repo)
self.num_stars = repo.stargazers_count
self.pushed_at = repo.pushed_at
if not self.notes:
notes = repo.description
if repo.description:
self.notes = notes
else:
self.num_stars = 0
self.pushed_at = datetime.utcnow()
name_len = len(self.name) + 4
self.__class__.NAME = max(self.__class__.NAME, name_len)
def __lt__(self, other: "Project") -> bool:
if self.online:
return self.num_stars < other.num_stars
else:
return self.name < other.name
@classmethod
def header(cls) -> str:
return (
f"| {'Name':{cls.NAME}} | CI | OS | Notes |\n"
f"|{'':-^{cls.NAME+2 }}|----|----|:------|"
)
@property
def namelink(self) -> str:
return f"[{self.name}][]"
@property
def starslink(self) -> str:
return f"![{self.name} stars][]"
@property
def url(self) -> str:
return f"https://github.com/{self.gh}"
@property
def ci_icons(self) -> str:
return " ".join(f"![{icon} icon][]" for icon in self.ci)
@property
def os_icons(self) -> str:
return " ".join(f"![{icon} icon][]" for icon in self.os)
def table_row(self) -> str:
notes = self.notes.replace('\n', ' ')
return f"| {self.namelink: <{self.NAME}} | {self.ci_icons} | {self.os_icons} | {notes} |"
def links(self) -> str:
return f"[{self.name}]: {self.url}"
def info(self) -> str:
days = (datetime.utcnow() - self.pushed_at).days
return f"<!-- {self.name}: {self.num_stars}, last pushed {days} days ago -->"
def fetch_icon(icon_name: str) -> None:
url = f'https://cdn.jsdelivr.net/npm/simple-icons@v4/icons/{icon_name}.svg'
with urllib.request.urlopen(url) as f:
original_svg_data = f.read()
document = xml.dom.minidom.parseString(original_svg_data)
svgElement = document.documentElement
assert svgElement.nodeName == 'svg'
svgElement.setAttribute('width', '16px')
svgElement.setAttribute('fill', '#606060')
icon_path = path_for_icon(icon_name)
icon_path.parent.mkdir(parents=True, exist_ok=True)
with open(path_for_icon(icon_name), 'w') as f:
f.write(svgElement.toxml())
def path_for_icon(icon_name: str) -> Path:
return Path('.') / 'docs' / 'data' / 'readme_icons' / f'{icon_name}.svg'
def str_projects(
config: List[Dict[str, Any]], *, online: bool = True, auth: Optional[str] = None
) -> str:
io = StringIO()
print = functools.partial(builtins.print, file=io)
if online:
for icon in ICONS:
fetch_icon(icon)
github = Github(auth) if online else None
projects = sorted((Project(item, github) for item in config), reverse=online)
print(Project.header())
for project in projects:
print(project.table_row())
print()
for project in projects:
print(project.links())
print()
for icon in ICONS:
print(f"[{icon} icon]: {path_for_icon(icon).as_posix()}")
print()
for project in projects:
print(project.info())
return io.getvalue()
@click.command()
@click.argument("input", type=click.File("r"))
@click.option("--online/--no-online", default=True, help="Get info from GitHub")
@click.option("--auth", help="GitHub authentication token")
@click.option("--readme", type=click.File("r+"), help="Modify a readme file if given")
def projects(
input: TextIO, online: bool, auth: Optional[str], readme: Optional[TextIO]
) -> None:
config = yaml.safe_load(input)
output = str_projects(config, online=online, auth=auth)
if readme is None:
print(output)
else:
text = readme.read()
start_str = "<!-- START bin/projects.py -->\n"
start = text.find(start_str)
end = text.find("<!-- END bin/projects.py -->\n")
generated_note = f'<!-- this section is generated by bin/projects.py. Don\'t edit it directly, instead, edit {input.name} -->'
new_text = f"{text[:start + len(start_str)]}\n{generated_note}\n\n{output}\n{text[end:]}"
readme.seek(0)
readme.write(new_text)
readme.truncate()
if __name__ == "__main__":
projects()
+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
@@ -17,4 +17,4 @@ if __name__ == '__main__':
subprocess.check_call(unit_test_args)
# run the integration tests
subprocess.check_call([sys.executable, '-m', 'pytest', '-x', '--durations', '0', 'test'])
subprocess.check_call([sys.executable, '-m', 'pytest', '-x', '--durations', '0', '--timeout=1200', 'test'])
+25
View File
@@ -0,0 +1,25 @@
#!/usr/bin/env python3
import os
import subprocess
import sys
import argparse
import tempfile
from pathlib import Path
if __name__ == '__main__':
# move cwd to the project root
os.chdir(Path(__file__).resolve().parents[1])
parser = argparse.ArgumentParser(description='Runs a sample build')
parser.add_argument('project_python_path', nargs='?', default='test.test_0_basic.basic_project')
options = parser.parse_args()
project_dir = tempfile.mkdtemp()
subprocess.run([
sys.executable, '-m', 'test.test_projects',
options.project_python_path, project_dir
], check=True)
exit(subprocess.run(['cibuildwheel'], cwd=project_dir).returncode)
+35 -15
View File
@@ -2,7 +2,9 @@
import configparser
import os
import shutil
import subprocess
import sys
from collections import namedtuple
import requests
@@ -12,21 +14,39 @@ os.chdir('..')
# CUSTOM_COMPILE_COMMAND is a pip-compile option that tells users how to
# regenerate the constraints files
os.environ['CUSTOM_COMPILE_COMMAND'] = "bin/update_constraints.py"
subprocess.check_call([
'pip-compile',
'--allow-unsafe',
'--upgrade',
'cibuildwheel/resources/constraints.in',
])
for python_version in ['27', '35', '36']:
subprocess.check_call([
f'./env{python_version}/bin/pip-compile',
'--allow-unsafe',
'--upgrade',
'cibuildwheel/resources/constraints.in',
'--output-file', f'cibuildwheel/resources/constraints-python{python_version}.txt'
])
os.environ['CUSTOM_COMPILE_COMMAND'] = "bin/update_dependencies.py"
PYTHON_VERSIONS = ['27', '35', '36', '37', '38', '39']
if '--no-docker' in sys.argv:
for python_version in PYTHON_VERSIONS:
subprocess.check_call([
f'./env{python_version}/bin/pip-compile',
'--allow-unsafe',
'--upgrade',
'cibuildwheel/resources/constraints.in',
'--output-file', f'cibuildwheel/resources/constraints-python{python_version}.txt'
])
else:
image = 'quay.io/pypa/manylinux2010_x86_64:latest'
subprocess.check_call(['docker', 'pull', image])
for python_version in PYTHON_VERSIONS:
abi_flags = '' if int(python_version) >= 38 else 'm'
python_path = f'/opt/python/cp{python_version}-cp{python_version}{abi_flags}/bin/'
subprocess.check_call([
'docker', 'run', '--rm',
'-e', 'CUSTOM_COMPILE_COMMAND',
'-v', f'{os.getcwd()}:/volume',
'--workdir', '/volume', image,
'bash', '-c',
f'{python_path}pip install pip-tools &&'
f'{python_path}pip-compile --allow-unsafe --upgrade '
'cibuildwheel/resources/constraints.in '
f'--output-file cibuildwheel/resources/constraints-python{python_version}.txt'
])
# default constraints.txt
shutil.copyfile(f'cibuildwheel/resources/constraints-python{PYTHON_VERSIONS[-1]}.txt', 'cibuildwheel/resources/constraints.txt')
Image = namedtuple('Image', [
'manylinux_version',
+1 -1
View File
@@ -1 +1 @@
__version__ = '1.5.3'
__version__ = '1.7.3'
+9 -13
View File
@@ -21,6 +21,7 @@ from cibuildwheel.util import (
BuildSelector,
DependencyConstraints,
Unbuffered,
detect_ci_provider,
resources_dir,
)
@@ -47,12 +48,6 @@ def get_option_from_environment(option_name: str, platform: Optional[str] = None
return os.environ.get(option_name, default)
def strtobool(val: str) -> bool:
if val.lower() in ('y', 'yes', 't', 'true', 'on', '1'):
return True
return False
def main() -> None:
parser = argparse.ArgumentParser(
description='Build wheels for all the platforms.',
@@ -96,13 +91,14 @@ def main() -> None:
if args.platform != 'auto':
platform = args.platform
else:
ci = strtobool(os.environ.get('CI', 'false')) or 'BITRISE_BUILD_NUMBER' in os.environ or 'AZURE_HTTP_USER_AGENT' in os.environ or 'GITHUB_WORKFLOW' in os.environ
if not ci:
print('cibuildwheel: Unable to detect platform. cibuildwheel should run on your CI server, '
'Travis CI, AppVeyor, Azure Pipelines, GitHub Actions and CircleCI are supported. You '
'can run on your development machine or other CI providers using the --platform argument. '
'Check --help output for more information.',
file=sys.stderr)
ci_provider = detect_ci_provider()
if ci_provider is None:
print(textwrap.dedent('''
cibuildwheel: Unable to detect platform. cibuildwheel should run on your CI server;
Travis CI, AppVeyor, Azure Pipelines, GitHub Actions, CircleCI, and Gitlab are
supported. You can run on your development machine or other CI providers using the
--platform argument. Check --help output for more information.
'''), file=sys.stderr)
exit(2)
if sys.platform.startswith('linux'):
platform = 'linux'
+5 -7
View File
@@ -1,15 +1,14 @@
import shlex
import subprocess
from typing import Callable, Dict, List, NamedTuple, Optional, Sequence
import bashlex # type: ignore
# a function that takes a shell command and the environment, and returns the result
EnvironmentExecutor = Callable[[str, Dict[str, str]], str]
# a function that takes a command and the environment, and returns the result
EnvironmentExecutor = Callable[[List[str], Dict[str, str]], str]
def local_environment_executor(command: str, env: Dict[str, str]) -> str:
return subprocess.check_output(shlex.split(command), env=env, universal_newlines=True)
def local_environment_executor(command: List[str], env: Dict[str, str]) -> str:
return subprocess.check_output(command, env=env, universal_newlines=True)
class NodeExecutionContext(NamedTuple):
@@ -97,8 +96,7 @@ def evaluate_nodes_as_compound_command(nodes: Sequence[bashlex.ast.node], contex
def evaluate_nodes_as_simple_command(nodes: List[bashlex.ast.node], context: NodeExecutionContext):
words = [evaluate_node(part, context=context) for part in nodes]
command = ' '.join(words)
command = [evaluate_node(part, context=context) for part in nodes]
return context.executor(command, context.environment)
+10 -6
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
],
@@ -70,7 +73,7 @@ class DockerContainer:
self.process.terminate()
self.process.wait()
subprocess.run(['docker', 'rm', '--force', '-v', self.name])
subprocess.run(['docker', 'rm', '--force', '-v', self.name], stdout=subprocess.DEVNULL)
self.name = None
def copy_into(self, from_path: Path, to_path: PurePath) -> None:
@@ -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())
@@ -180,9 +184,9 @@ class DockerContainer:
'import sys, json, os; json.dump(os.environ.copy(), sys.stdout)'
], capture_output=True))
def environment_executor(self, command: str, environment: Dict[str, str]) -> str:
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(shlex.split(command), env=environment)
return self.call(command, env=environment, capture_output=True)
def shell_quote(path: PurePath) -> str:
+57 -17
View File
@@ -7,7 +7,8 @@ from pathlib import Path, PurePath
from typing import List, NamedTuple, Union
from .docker_container import DockerContainer
from .util import (BuildOptions, BuildSelector,
from .logger import log
from .util import (BuildOptions, BuildSelector, NonPlatformWheelError,
get_build_verbosity_extra_flags, prepare_command)
@@ -50,26 +51,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)]
@@ -77,7 +84,7 @@ def get_python_configurations(build_selector: BuildSelector) -> List[PythonConfi
def build(options: BuildOptions) -> None:
try:
subprocess.check_call(['docker', '--version'])
subprocess.check_output(['docker', '--version'])
except Exception:
print('cibuildwheel: Docker not found. Docker is required to run Linux builds. '
'If you\'re building on Travis CI, add `services: [docker]` to your .travis.yml.'
@@ -101,7 +108,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,19 +118,36 @@ 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'))
log.step(f'Starting Docker image {docker_image}...')
with DockerContainer(docker_image, simulate_32_bit=platform_tag.endswith('i686'), cwd=container_project_path) as docker:
log.step('Copying project into Docker...')
docker.copy_into(Path.cwd(), container_project_path)
if options.before_all:
log.step('Running before_all...')
env = docker.get_environment()
env['PATH'] = f'/opt/python/cp38-cp38:{env["PATH"]}'
env['PATH'] = f'/opt/python/cp38-cp38/bin:{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:
log.build_start(config.identifier)
dependency_constraint_flags: List[Union[str, PathLike]] = []
if config.identifier.startswith("pp"):
# Patch PyPy to make sure headers get installed into a venv
patch_version = '_27' if config.version == '2.7' else ''
patch_path = Path(__file__).absolute().parent / 'resources' / f'pypy_venv{patch_version}.patch'
patch_docker_path = PurePath('/pypy_venv.patch')
docker.copy_into(patch_path, patch_docker_path)
try:
docker.call(['patch', '--force', '-p1', '-d', config.path, '-i', patch_docker_path])
except subprocess.CalledProcessError:
print("PyPy patch not applied", file=sys.stderr)
if options.dependency_constraints:
constraints_file = options.dependency_constraints.get_for_python_version(config.version)
@@ -131,6 +156,8 @@ def build(options: BuildOptions) -> None:
docker.copy_into(constraints_file, container_constraints_file)
dependency_constraint_flags = ['-c', container_constraints_file]
log.step('Setting up build environment...')
env = docker.get_environment()
# put this config's python top of the list
@@ -151,9 +178,12 @@ 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)
log.step('Running before_build...')
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)
log.step('Building wheel...')
temp_dir = PurePath('/tmp/cibuildwheel')
built_wheel_dir = temp_dir / 'built_wheel'
docker.call(['rm', '-rf', built_wheel_dir])
@@ -173,15 +203,21 @@ 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:
log.step('Repairing wheel...')
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')
if options.test_command:
log.step('Testing wheel...')
# set up a virtual environment to install and test from, to make sure
# there are no dependencies that were pulled in at build time.
docker.call(['pip', 'install', 'virtualenv', *dependency_constraint_flags], env=env)
@@ -193,7 +229,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 +246,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
@@ -220,17 +256,21 @@ def build(options: BuildOptions) -> None:
docker.call(['mkdir', '-p', container_output_dir])
docker.call(['mv', *repaired_wheels, container_output_dir])
log.build_end()
log.step('Copying wheels back to host...')
# copy the output back into the host
docker.copy_out(container_output_dir, options.output_dir)
log.step_end()
except subprocess.CalledProcessError as error:
print(f'Command {error.cmd} failed with code {error.returncode}. {error.stdout}')
log.error(f'Command {error.cmd} failed with code {error.returncode}. {error.stdout}')
troubleshoot(options.package_dir, error)
exit(1)
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 +283,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]))
+263
View File
@@ -0,0 +1,263 @@
import codecs
import os
import re
import sys
import time
from typing import Optional, Union
from cibuildwheel.util import CIProvider, detect_ci_provider
DEFAULT_FOLD_PATTERN = ('{name}', '')
FOLD_PATTERNS = {
'azure': ('##[group]{name}', '##[endgroup]'),
'travis': ('travis_fold:start:{identifier}\n{name}', 'travis_fold:end:{identifier}'),
'github': ('::group::{name}', '::endgroup::{name}'),
}
PLATFORM_IDENTIFIER_DESCIPTIONS = {
'manylinux_x86_64': 'manylinux x86_64',
'manylinux_i686': 'manylinux i686',
'manylinux_aarch64': 'manylinux aarch64',
'manylinux_ppc64le': 'manylinux ppc64le',
'manylinux_s390x': 'manylinux s390x',
'win32': 'Windows 32bit',
'win_amd64': 'Windows 64bit',
'macosx_x86_64': 'macOS x86_64',
}
class Logger:
fold_mode: str
colors_enabled: bool
unicode_enabled: bool
active_build_identifier: Optional[str] = None
build_start_time: Optional[float] = None
step_start_time: Optional[float] = None
active_fold_group_name: Optional[str] = None
def __init__(self):
if sys.platform == 'win32' and hasattr(sys.stdout, 'reconfigure'):
# the encoding on Windows can be a 1-byte charmap, but all CIs
# support utf8, so we hardcode that
sys.stdout.reconfigure(encoding='utf8')
self.unicode_enabled = file_supports_unicode(sys.stdout)
ci_provider = detect_ci_provider()
if ci_provider == CIProvider.azure_pipelines:
self.fold_mode = 'azure'
self.colors_enabled = True
elif ci_provider == CIProvider.github_actions:
self.fold_mode = 'github'
self.colors_enabled = True
elif ci_provider == CIProvider.travis_ci:
self.fold_mode = 'travis'
self.colors_enabled = True
elif ci_provider == CIProvider.appveyor:
self.fold_mode = 'disabled'
self.colors_enabled = True
else:
self.fold_mode = 'disabled'
self.colors_enabled = file_supports_color(sys.stdout)
def build_start(self, identifier: str):
self.step_end()
c = self.colors
description = build_description_from_identifier(identifier)
print()
print(f'{c.bold}{c.blue}Building {identifier} wheel{c.end}')
print(f'{description}')
print()
self.build_start_time = time.time()
self.active_build_identifier = identifier
def build_end(self):
assert self.build_start_time is not None
assert self.active_build_identifier is not None
self.step_end()
c = self.colors
s = self.symbols
duration = time.time() - self.build_start_time
print()
print(f'{c.green}{s.done} {c.end}{self.active_build_identifier} finished in {duration:.2f}s')
self.build_start_time = None
self.active_build_identifier = None
def step(self, step_description: str):
self.step_end()
self.step_start_time = time.time()
self._start_fold_group(step_description)
def step_end(self, success=True):
if self.step_start_time is not None:
self._end_fold_group()
c = self.colors
s = self.symbols
duration = time.time() - self.step_start_time
if success:
print(f'{c.green}{s.done} {c.end}{duration:.2f}s'.rjust(78))
else:
print(f'{c.red}{s.error} {c.end}{duration:.2f}s'.rjust(78))
self.step_start_time = None
def error(self, error: Union[Exception, str]):
self.step_end(success=False)
print()
if self.fold_mode == 'github':
print(f'::error::{error}')
else:
c = self.colors
print(f'{c.bright_red}Error{c.end} {error}')
def _start_fold_group(self, name: str):
self._end_fold_group()
self.active_fold_group_name = name
fold_start_pattern = FOLD_PATTERNS.get(self.fold_mode, DEFAULT_FOLD_PATTERN)[0]
identifier = self._fold_group_identifier(name)
print(fold_start_pattern.format(name=self.active_fold_group_name, identifier=identifier))
print()
sys.stdout.flush()
def _end_fold_group(self):
if self.active_fold_group_name:
fold_start_pattern = FOLD_PATTERNS.get(self.fold_mode, DEFAULT_FOLD_PATTERN)[1]
identifier = self._fold_group_identifier(self.active_fold_group_name)
print(fold_start_pattern.format(name=self.active_fold_group_name, identifier=identifier))
sys.stdout.flush()
self.active_fold_group_name = None
def _fold_group_identifier(self, name: str):
'''
Travis doesn't like fold groups identifiers that have spaces in. This
method converts them to ascii identifiers
'''
# whitespace to underscores
identifier = re.sub(r'\s+', '_', name)
# remove non-alphanum
identifier = re.sub(r'[^A-Za-z\d_]+', '', identifier)
# trim underscores
identifier = identifier.strip('_')
# lowercase, shorten
return identifier.lower()[:20]
@property
def colors(self):
if self.colors_enabled:
return Colors.enabled
else:
return Colors.disabled
@property
def symbols(self):
if self.unicode_enabled:
return Symbols.unicode
else:
return Symbols.ascii
def build_description_from_identifier(identifier: str):
python_identifier, _, platform_identifier = identifier.partition('-')
build_description = ''
python_interpreter = python_identifier[0:2]
python_version = python_identifier[2:4]
if python_interpreter == 'cp':
build_description += 'CPython'
elif python_interpreter == 'pp':
build_description += 'PyPy'
else:
raise Exception('unknown python')
build_description += f' {python_version[0]}.{python_version[1]} '
try:
build_description += PLATFORM_IDENTIFIER_DESCIPTIONS[platform_identifier]
except KeyError as e:
raise Exception('unknown platform') from e
return build_description
class Colors:
class Enabled:
red = '\033[31m'
green = '\033[32m'
yellow = '\033[33m'
blue = '\033[34m'
cyan = '\033[36m'
bright_red = '\033[91m'
bright_green = '\033[92m'
white = '\033[37m\033[97m'
bg_grey = '\033[48;5;235m'
bold = '\033[1m'
faint = '\033[2m'
end = '\033[0m'
class Disabled:
def __getattr__(self, attr: str) -> str:
return ''
enabled = Enabled()
disabled = Disabled()
class Symbols:
class Unicode:
done = ''
error = ''
class Ascii:
done = 'done'
error = 'failed'
unicode = Unicode()
ascii = Ascii()
def file_supports_color(file_obj):
"""
Returns True if the running system's terminal supports color.
"""
plat = sys.platform
supported_platform = (plat != 'win32' or 'ANSICON' in os.environ)
is_a_tty = file_is_a_tty(file_obj)
return (supported_platform and is_a_tty)
def file_is_a_tty(file_obj):
return hasattr(file_obj, 'isatty') and file_obj.isatty()
def file_supports_unicode(file_obj):
encoding = getattr(file_obj, 'encoding', None)
if not encoding:
return False
codec_info = codecs.lookup(encoding)
return ('utf' in codec_info.name)
'''
Global instance of the Logger.
'''
# (there's only one stdout per-process, so a global instance is justified)
log = Logger()
+120 -90
View File
@@ -9,9 +9,10 @@ from pathlib import Path
from typing import Dict, List, NamedTuple, Optional, Sequence, Union
from .environment import ParsedEnvironment
from .util import (BuildOptions, BuildSelector, download,
get_build_verbosity_extra_flags, get_pip_script,
prepare_command)
from .logger import log
from .util import (BuildOptions, BuildSelector, NonPlatformWheelError,
download, get_build_verbosity_extra_flags, get_pip_script,
install_certifi_script, prepare_command)
def call(args: Union[str, Sequence[Union[str, PathLike]]], env: Optional[Dict[str, str]] = None, cwd: Optional[str] = None, shell: bool = False) -> int:
@@ -36,11 +37,13 @@ def get_python_configurations(build_selector: BuildSelector) -> List[PythonConfi
PythonConfiguration(version='2.7', identifier='cp27-macosx_x86_64', url='https://www.python.org/ftp/python/2.7.18/python-2.7.18-macosx10.9.pkg'),
PythonConfiguration(version='3.5', identifier='cp35-macosx_x86_64', url='https://www.python.org/ftp/python/3.5.4/python-3.5.4-macosx10.6.pkg'),
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.7', identifier='cp37-macosx_x86_64', url='https://www.python.org/ftp/python/3.7.9/python-3.7.9-macosx10.9.pkg'),
PythonConfiguration(version='3.8', identifier='cp38-macosx_x86_64', url='https://www.python.org/ftp/python/3.8.7/python-3.8.7-macosx10.9.pkg'),
PythonConfiguration(version='3.9', identifier='cp39-macosx_x86_64', url='https://www.python.org/ftp/python/3.9.1/python-3.9.1-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.3-osx64.tar.bz2'),
PythonConfiguration(version='3.6', identifier='pp36-macosx_x86_64', url='https://downloads.python.org/pypy/pypy3.6-v7.3.3-osx64.tar.bz2'),
PythonConfiguration(version='3.7', identifier='pp37-macosx_x86_64', url='https://downloads.python.org/pypy/pypy3.7-v7.3.3-osx64.tar.bz2'),
]
# skip builds as required
@@ -70,6 +73,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 +83,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)
@@ -99,6 +105,10 @@ def install_pypy(version: str, url: str) -> Path:
downloaded_tar_bz2 = Path("/tmp") / pypy_tar_bz2
download(url, downloaded_tar_bz2)
call(['tar', '-C', '/tmp', '-xf', downloaded_tar_bz2])
# Patch PyPy to make sure headers get installed into a venv
patch_version = '_27' if version == '2.7' else ''
patch_path = Path(__file__).absolute().parent / 'resources' / f'pypy_venv{patch_version}.patch'
call(['patch', '--force', '-d', installation_path, patch_path])
installation_bin_path = installation_path / 'bin'
python_executable = 'pypy3' if version[0] == '3' else 'pypy'
@@ -111,13 +121,18 @@ def install_pypy(version: str, url: str) -> Path:
def setup_python(python_configuration: PythonConfiguration,
dependency_constraint_flags: Sequence[Union[str, PathLike]],
environment: ParsedEnvironment) -> Dict[str, str]:
if python_configuration.identifier.startswith('cp'):
implementation_id = python_configuration.identifier.split("-")[0]
log.step(f'Installing Python {implementation_id}...')
if implementation_id.startswith('cp'):
installation_bin_path = install_cpython(python_configuration.version, python_configuration.url)
elif python_configuration.identifier.startswith('pp'):
elif implementation_id.startswith('pp'):
installation_bin_path = install_pypy(python_configuration.version, python_configuration.url)
else:
raise ValueError("Unknown Python implementation")
log.step('Setting up build environment...')
env = os.environ.copy()
env['PATH'] = os.pathsep.join([
str(SYMLINKS_DIR),
@@ -151,7 +166,6 @@ def setup_python(python_configuration: PythonConfiguration,
if which_pip != '/tmp/cibw_bin/pip':
print("cibuildwheel: pip available on PATH doesn't match our installed instance. If you have modified PATH, ensure that you don't overwrite cibuildwheel's entry or insert pip above it.", file=sys.stderr)
exit(1)
call(['pip', 'install', '--upgrade', 'setuptools', 'wheel', 'delocate', *dependency_constraint_flags], env=env)
# Set MACOSX_DEPLOYMENT_TARGET to 10.9, if the user didn't set it.
# CPython 3.5 defaults to 10.6, and pypy defaults to 10.7, causing
@@ -165,6 +179,9 @@ def setup_python(python_configuration: PythonConfiguration,
# https://github.com/python/cpython/blob/a5ed2fe0eedefa1649aa93ee74a0bafc8e628a10/Lib/_osx_support.py#L260
env.setdefault('ARCHFLAGS', '-arch x86_64')
log.step('Installing build tools...')
call(['pip', 'install', '--upgrade', 'setuptools', 'wheel', 'delocate', *dependency_constraint_flags], env=env)
return env
@@ -173,98 +190,111 @@ def build(options: BuildOptions) -> None:
built_wheel_dir = temp_dir / 'built_wheel'
repaired_wheel_dir = temp_dir / 'repaired_wheel'
if options.before_all:
env = options.environment.as_dictionary(prev_environment=os.environ)
before_all_prepared = prepare_command(options.before_all, project='.', package=options.package_dir)
call([before_all_prepared], shell=True, env=env)
try:
if options.before_all:
log.step('Running before_all...')
env = options.environment.as_dictionary(prev_environment=os.environ)
before_all_prepared = prepare_command(options.before_all, project='.', package=options.package_dir)
call([before_all_prepared], shell=True, env=env)
python_configurations = get_python_configurations(options.build_selector)
python_configurations = get_python_configurations(options.build_selector)
for config in python_configurations:
dependency_constraint_flags: Sequence[Union[str, PathLike]] = []
if options.dependency_constraints:
dependency_constraint_flags = [
'-c', options.dependency_constraints.get_for_python_version(config.version)
]
for config in python_configurations:
log.build_start(config.identifier)
env = setup_python(config, dependency_constraint_flags, options.environment)
dependency_constraint_flags: Sequence[Union[str, PathLike]] = []
if options.dependency_constraints:
dependency_constraint_flags = [
'-c', options.dependency_constraints.get_for_python_version(config.version)
]
# run the before_build command
if options.before_build:
before_build_prepared = prepare_command(options.before_build, project='.', package=options.package_dir)
call(before_build_prepared, env=env, shell=True)
env = setup_python(config, dependency_constraint_flags, options.environment)
# build the wheel
if built_wheel_dir.exists():
shutil.rmtree(built_wheel_dir)
built_wheel_dir.mkdir(parents=True)
if options.before_build:
log.step('Running before_build...')
before_build_prepared = prepare_command(options.before_build, project='.', package=options.package_dir)
call(before_build_prepared, env=env, shell=True)
# Path.resolve() is needed. Without it pip wheel may try to fetch package from pypi.org
# see https://github.com/joerick/cibuildwheel/pull/369
call([
'pip', 'wheel',
options.package_dir.resolve(),
'-w', built_wheel_dir,
'--no-deps',
*get_build_verbosity_extra_flags(options.build_verbosity)
], env=env)
log.step('Building wheel...')
if built_wheel_dir.exists():
shutil.rmtree(built_wheel_dir)
built_wheel_dir.mkdir(parents=True)
built_wheel = next(built_wheel_dir.glob('*.whl'))
# Path.resolve() is needed. Without it pip wheel may try to fetch package from pypi.org
# see https://github.com/joerick/cibuildwheel/pull/369
call([
'pip', 'wheel',
options.package_dir.resolve(),
'-w', built_wheel_dir,
'--no-deps',
*get_build_verbosity_extra_flags(options.build_verbosity)
], env=env)
# repair the wheel
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:
repair_command_prepared = prepare_command(options.repair_command, wheel=built_wheel, dest_dir=repaired_wheel_dir)
call(repair_command_prepared, env=env, shell=True)
repaired_wheel = next(repaired_wheel_dir.glob('*.whl'))
built_wheel = next(built_wheel_dir.glob('*.whl'))
if options.test_command:
# set up a virtual environment to install and test from, to make sure
# there are no dependencies that were pulled in at build time.
call(['pip', 'install', 'virtualenv', *dependency_constraint_flags], env=env)
venv_dir = Path(tempfile.mkdtemp())
if repaired_wheel_dir.exists():
shutil.rmtree(repaired_wheel_dir)
repaired_wheel_dir.mkdir(parents=True)
# Use --no-download to ensure determinism by using seed libraries
# built into virtualenv
call(['python', '-m', 'virtualenv', '--no-download', venv_dir], env=env)
if built_wheel.name.endswith('none-any.whl'):
raise NonPlatformWheelError()
virtualenv_env = env.copy()
virtualenv_env['PATH'] = os.pathsep.join([
str(venv_dir / 'bin'),
virtualenv_env['PATH'],
])
if options.repair_command:
log.step('Repairing wheel...')
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)
# check that we are using the Python from the virtual environment
call(['which', 'python'], env=virtualenv_env)
repaired_wheel = next(repaired_wheel_dir.glob('*.whl'))
if options.before_test:
before_test_prepared = prepare_command(options.before_test, project='.', package=options.package_dir)
call(before_test_prepared, env=virtualenv_env, shell=True)
if options.test_command:
log.step('Testing wheel...')
# set up a virtual environment to install and test from, to make sure
# there are no dependencies that were pulled in at build time.
call(['pip', 'install', 'virtualenv', *dependency_constraint_flags], env=env)
venv_dir = Path(tempfile.mkdtemp())
# install the wheel
call(['pip', 'install', str(repaired_wheel) + options.test_extras], env=virtualenv_env)
# Use --no-download to ensure determinism by using seed libraries
# built into virtualenv
call(['python', '-m', 'virtualenv', '--no-download', venv_dir], env=env)
# test the wheel
if options.test_requires:
call(['pip', 'install'] + options.test_requires, env=virtualenv_env)
virtualenv_env = env.copy()
virtualenv_env['PATH'] = os.pathsep.join([
str(venv_dir / 'bin'),
virtualenv_env['PATH'],
])
# run the tests from $HOME, with an absolute path in the command
# (this ensures that Python runs the tests against the installed wheel
# and not the repo code)
test_command_prepared = prepare_command(
options.test_command,
project=Path('.').resolve(),
package=options.package_dir.resolve()
)
call(test_command_prepared, cwd=os.environ['HOME'], env=virtualenv_env, shell=True)
# check that we are using the Python from the virtual environment
call(['which', 'python'], env=virtualenv_env)
# clean up
shutil.rmtree(venv_dir)
if options.before_test:
before_test_prepared = prepare_command(options.before_test, project='.', package=options.package_dir)
call(before_test_prepared, env=virtualenv_env, shell=True)
# we're all done here; move it to output (overwrite existing)
shutil.move(str(repaired_wheel), options.output_dir)
# install the wheel
call(['pip', 'install', str(repaired_wheel) + options.test_extras], env=virtualenv_env)
# test the wheel
if options.test_requires:
call(['pip', 'install'] + options.test_requires, env=virtualenv_env)
# run the tests from $HOME, with an absolute path in the command
# (this ensures that Python runs the tests against the installed wheel
# and not the repo code)
test_command_prepared = prepare_command(
options.test_command,
project=Path('.').resolve(),
package=options.package_dir.resolve()
)
call(test_command_prepared, cwd=os.environ['HOME'], env=virtualenv_env, shell=True)
# clean up
shutil.rmtree(venv_dir)
# we're all done here; move it to output (overwrite existing)
shutil.move(str(repaired_wheel), options.output_dir)
log.build_end()
except subprocess.CalledProcessError as error:
log.error(f'Command {error.cmd} failed with code {error.returncode}. {error.stdout}')
exit(1)
+48 -19
View File
@@ -2,25 +2,54 @@
# This file is autogenerated by pip-compile
# To update, run:
#
# bin/update_constraints.py
# bin/update_dependencies.py
#
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
filelock==3.0.12 # via virtualenv
importlib-metadata==1.6.0 # via importlib-resources, virtualenv
importlib-resources==1.5.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
zipp==1.2.0 # via importlib-metadata, importlib-resources
appdirs==1.4.4
# via virtualenv
configparser==4.0.2
# via importlib-metadata
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==2.1.1
# via virtualenv
importlib-resources==3.3.1
# 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.3
# via importlib-resources
virtualenv==20.2.2
# via -r cibuildwheel/resources/constraints.in
wheel==0.36.2
# 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.3.3
# via -r cibuildwheel/resources/constraints.in
setuptools==44.1.1
# via -r cibuildwheel/resources/constraints.in
+29 -13
View File
@@ -2,19 +2,35 @@
# This file is autogenerated by pip-compile
# To update, run:
#
# bin/update_constraints.py
# bin/update_dependencies.py
#
appdirs==1.4.4 # via virtualenv
delocate==0.8.0 # via -r cibuildwheel/resources/constraints.in
distlib==0.3.0 # via virtualenv
filelock==3.0.12 # via virtualenv
importlib-metadata==1.6.0 # via importlib-resources, virtualenv
importlib-resources==1.5.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==1.2.0 # via importlib-metadata, importlib-resources
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.1.1
# via virtualenv
importlib-resources==3.2.1
# via virtualenv
six==1.15.0
# via virtualenv
virtualenv==20.2.2
# via -r cibuildwheel/resources/constraints.in
wheel==0.36.2
# 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.3.3
# via -r cibuildwheel/resources/constraints.in
setuptools==50.3.2
# via -r cibuildwheel/resources/constraints.in
+31 -13
View File
@@ -2,19 +2,37 @@
# This file is autogenerated by pip-compile
# To update, run:
#
# bin/update_constraints.py
# bin/update_dependencies.py
#
appdirs==1.4.4 # via virtualenv
delocate==0.8.0 # via -r cibuildwheel/resources/constraints.in
distlib==0.3.0 # via virtualenv
filelock==3.0.12 # via virtualenv
importlib-metadata==1.6.0 # via importlib-resources, virtualenv
importlib-resources==1.5.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
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==3.3.0
# via virtualenv
importlib-resources==4.1.1
# via virtualenv
six==1.15.0
# via virtualenv
typing-extensions==3.7.4.3
# via importlib-metadata
virtualenv==20.2.2
# via -r cibuildwheel/resources/constraints.in
wheel==0.36.2
# via
# -r cibuildwheel/resources/constraints.in
# delocate
zipp==3.4.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.3.3
# via -r cibuildwheel/resources/constraints.in
setuptools==51.1.1
# via -r cibuildwheel/resources/constraints.in
@@ -0,0 +1,34 @@
#
# This file is autogenerated by pip-compile
# To update, run:
#
# bin/update_dependencies.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==3.3.0
# via virtualenv
six==1.15.0
# via virtualenv
typing-extensions==3.7.4.3
# via importlib-metadata
virtualenv==20.2.2
# via -r cibuildwheel/resources/constraints.in
wheel==0.36.2
# via
# -r cibuildwheel/resources/constraints.in
# delocate
zipp==3.4.0
# via importlib-metadata
# The following packages are considered to be unsafe in a requirements file:
pip==20.3.3
# via -r cibuildwheel/resources/constraints.in
setuptools==51.1.1
# via -r cibuildwheel/resources/constraints.in
@@ -0,0 +1,28 @@
#
# This file is autogenerated by pip-compile
# To update, run:
#
# bin/update_dependencies.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
six==1.15.0
# via virtualenv
virtualenv==20.2.2
# via -r cibuildwheel/resources/constraints.in
wheel==0.36.2
# via
# -r cibuildwheel/resources/constraints.in
# delocate
# The following packages are considered to be unsafe in a requirements file:
pip==20.3.3
# via -r cibuildwheel/resources/constraints.in
setuptools==51.1.1
# via -r cibuildwheel/resources/constraints.in
@@ -0,0 +1,28 @@
#
# This file is autogenerated by pip-compile
# To update, run:
#
# bin/update_dependencies.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
six==1.15.0
# via virtualenv
virtualenv==20.2.2
# via -r cibuildwheel/resources/constraints.in
wheel==0.36.2
# via
# -r cibuildwheel/resources/constraints.in
# delocate
# The following packages are considered to be unsafe in a requirements file:
pip==20.3.3
# via -r cibuildwheel/resources/constraints.in
setuptools==51.1.1
# via -r cibuildwheel/resources/constraints.in
+21 -12
View File
@@ -2,18 +2,27 @@
# This file is autogenerated by pip-compile
# To update, run:
#
# bin/update_constraints.py
# bin/update_dependencies.py
#
appdirs==1.4.4 # via virtualenv
delocate==0.8.0 # via -r cibuildwheel/resources/constraints.in
distlib==0.3.0 # 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
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
six==1.15.0
# via virtualenv
virtualenv==20.2.2
# via -r cibuildwheel/resources/constraints.in
wheel==0.36.2
# 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.3.3
# via -r cibuildwheel/resources/constraints.in
setuptools==51.1.1
# 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 -10
View File
@@ -1,22 +1,22 @@
[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-12-30-e2b3664
manylinux2010 = quay.io/pypa/manylinux2010_x86_64:2020-12-30-3161d69
manylinux2014 = quay.io/pypa/manylinux2014_x86_64:2020-12-30-68d3257
[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-12-30-e2b3664
manylinux2010 = quay.io/pypa/manylinux2010_i686:2020-12-30-3161d69
manylinux2014 = quay.io/pypa/manylinux2014_i686:2020-12-30-68d3257
[pypy_x86_64]
manylinux2010 = pypywheels/manylinux2010-pypy_x86_64:2020-04-25-eb2cdff
manylinux2010 = pypywheels/manylinux2010-pypy_x86_64:2020-12-11-f1e0e80
[aarch64]
manylinux2014 = quay.io/pypa/manylinux2014_aarch64:2020-05-17-2f8ac3b
manylinux2014 = quay.io/pypa/manylinux2014_aarch64:2020-12-30-68d3257
[ppc64le]
manylinux2014 = quay.io/pypa/manylinux2014_ppc64le:2020-05-17-2f8ac3b
manylinux2014 = quay.io/pypa/manylinux2014_ppc64le:2020-12-30-68d3257
[s390x]
manylinux2014 = quay.io/pypa/manylinux2014_s390x:2020-05-17-2f8ac3b
manylinux2014 = quay.io/pypa/manylinux2014_s390x:2020-12-30-68d3257
+36
View File
@@ -0,0 +1,36 @@
diff --git a/lib-python/3/sysconfig.py b/lib-python/3/sysconfig.py
index 0d08cde66b4150e1772c13fdc6fe34d079c2b10d..30c77d165a2505d98bc7660ff0cc3b728f56c682 100644
--- a/lib-python/3/sysconfig.py
+++ b/lib-python/3/sysconfig.py
@@ -618,9 +618,6 @@ def get_config_vars(*args):
import _osx_support
_osx_support.customize_config_vars(_CONFIG_VARS)
- _CONFIG_VARS['INCLUDEPY'] = os.path.join(_CONFIG_VARS['prefix'],
- 'include')
-
if args:
vals = []
for name in args:
diff --git a/lib_pypy/_sysconfigdata.py b/lib_pypy/_sysconfigdata.py
index f1cca41a4b7553819bb1a2a63af1c1a9b8591ce9..a34216e8e12b82abd72fabdd7793b3e8bb19bbcf 100644
--- a/lib_pypy/_sysconfigdata.py
+++ b/lib_pypy/_sysconfigdata.py
@@ -5,6 +5,7 @@ from distutils.spawn import find_executable
so_ext = _imp.extension_suffixes()[0]
+mybase = os.path.dirname(os.path.dirname(__file__))
build_time_vars = {
# SOABI is PEP 3149 compliant, but CPython3 has so_ext.split('.')[1]
@@ -25,7 +26,8 @@ build_time_vars = {
'AR': "ar",
'ARFLAGS': "rc",
'EXE': "",
- 'LIBDIR': os.path.join(sys.prefix, 'bin'),
+ 'LIBDIR': os.path.join(mybase, 'lib'),
+ 'INCLUDEPY': os.path.join(mybase, 'include'),
}
if find_executable("gcc"):
+27
View File
@@ -0,0 +1,27 @@
--- a/lib-python/2.7/sysconfig.py
+++ b/lib-python/2.7/sysconfig.py
@@ -553,9 +553,6 @@ def get_config_vars(*args):
if type_ == imp.C_EXTENSION:
_CONFIG_VARS['SOABI'] = suffix.split('.')[1]
break
- _CONFIG_VARS['INCLUDEPY'] = os.path.join(_CONFIG_VARS['prefix'],
- 'include')
-
if args:
vals = []
for name in args:
--- a/lib_pypy/_sysconfigdata.py
+++ b/lib_pypy/_sysconfigdata.py
@@ -1,5 +1,11 @@
-import imp
+import imp, os
+
+mybase = os.path.dirname(os.path.dirname(__file__))
build_time_vars = {
"SO": [s[0] for s in imp.get_suffixes() if s[2] == imp.C_EXTENSION][0]
}
+
+build_time_vars['LIBDIR'] = os.path.join(mybase, 'lib')
+build_time_vars['INCLUDEPY'] = os.path.join(mybase, 'include')
+
+68 -3
View File
@@ -1,11 +1,15 @@
import os
import ssl
import textwrap
import urllib.request
from enum import Enum
from fnmatch import fnmatch
from pathlib import Path
from time import sleep
from typing import Dict, List, NamedTuple, Optional, Union
import certifi
from .environment import ParsedEnvironment
@@ -39,7 +43,10 @@ class BuildSelector:
return match_any(self.build_patterns) and not match_any(self.skip_patterns)
def __repr__(self) -> str:
return f'BuildSelector({" ".join(self.build_patterns)!r} - {" ".join(self.skip_patterns)!r})'
if not self.skip_patterns:
return f'BuildSelector({" ".join(self.build_patterns)!r})'
else:
return f'BuildSelector({" ".join(self.build_patterns)!r} - {" ".join(self.skip_patterns)!r})'
# Taken from https://stackoverflow.com/a/107717
@@ -65,10 +72,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 +117,9 @@ class DependencyConstraints:
else:
return self.base_file_path
def __repr__(self):
return f'{self.__class__.__name__}{self.base_file_path!r})'
class BuildOptions(NamedTuple):
package_dir: Path
@@ -126,3 +140,54 @@ 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)
def strtobool(val: str) -> bool:
if val.lower() in ('y', 'yes', 't', 'true', 'on', '1'):
return True
return False
class CIProvider(str, Enum):
travis_ci = 'travis'
appveyor = 'appveyor'
circle_ci = 'circle_ci'
azure_pipelines = 'azure_pipelines'
github_actions = 'github_actions'
gitlab = 'gitlab'
other = 'other'
def detect_ci_provider() -> Optional[CIProvider]:
if 'TRAVIS' in os.environ:
return CIProvider.travis_ci
elif 'APPVEYOR' in os.environ:
return CIProvider.appveyor
elif 'CIRCLECI' in os.environ:
return CIProvider.circle_ci
elif 'AZURE_HTTP_USER_AGENT' in os.environ:
return CIProvider.azure_pipelines
elif 'GITHUB_ACTIONS' in os.environ:
return CIProvider.github_actions
elif 'GITLAB_CI' in os.environ:
return CIProvider.gitlab
elif strtobool(os.environ.get('CI', 'false')):
return CIProvider.other
else:
return None
+134 -103
View File
@@ -7,11 +7,13 @@ from os import PathLike
from pathlib import Path
from typing import Dict, List, NamedTuple, Optional, Sequence, Union
from zipfile import ZipFile
import toml
from .environment import ParsedEnvironment
from .util import (BuildOptions, BuildSelector, download,
get_build_verbosity_extra_flags, get_pip_script,
from .logger import log
from .util import (BuildOptions, BuildSelector, NonPlatformWheelError,
download, get_build_verbosity_extra_flags, get_pip_script,
prepare_command)
IS_RUNNING_ON_AZURE = Path('C:\\hostedtoolcache').exists()
@@ -54,13 +56,16 @@ def get_python_configurations(build_selector: BuildSelector) -> List[PythonConfi
PythonConfiguration(version='3.5.4', arch='64', identifier='cp35-win_amd64', url=None),
PythonConfiguration(version='3.6.8', arch='32', identifier='cp36-win32', url=None),
PythonConfiguration(version='3.6.8', arch='64', identifier='cp36-win_amd64', url=None),
PythonConfiguration(version='3.7.8', arch='32', identifier='cp37-win32', url=None),
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.7.9', arch='32', identifier='cp37-win32', url=None),
PythonConfiguration(version='3.7.9', arch='64', identifier='cp37-win_amd64', url=None),
PythonConfiguration(version='3.8.7', arch='32', identifier='cp38-win32', url=None),
PythonConfiguration(version='3.8.7', arch='64', identifier='cp38-win_amd64', url=None),
PythonConfiguration(version='3.9.1', arch='32', identifier='cp39-win32', url=None),
PythonConfiguration(version='3.9.1', 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.3-win32.zip'),
PythonConfiguration(version='3.6', arch='32', identifier='pp36-win32', url='https://downloads.python.org/pypy/pypy3.6-v7.3.3-win32.zip'),
PythonConfiguration(version='3.7', arch='32', identifier='pp37-win32', url='https://downloads.python.org/pypy/pypy3.7-v7.3.3-win32.zip'),
]
if IS_RUNNING_ON_TRAVIS:
@@ -106,11 +111,15 @@ def install_pypy(version: str, arch: str, url: str) -> Path:
def setup_python(python_configuration: PythonConfiguration, dependency_constraint_flags: Sequence[Union[str, PathLike]], environment: ParsedEnvironment) -> Dict[str, str]:
nuget = Path('C:\\cibw\\nuget.exe')
if not nuget.exists():
log.step('Downloading nuget...')
download('https://dist.nuget.org/win-x86-commandline/latest/nuget.exe', nuget)
if python_configuration.identifier.startswith('cp'):
implementation_id = python_configuration.identifier.split("-")[0]
log.step(f'Installing Python {implementation_id}...')
if implementation_id.startswith('cp'):
installation_path = install_cpython(python_configuration.version, python_configuration.arch, nuget)
elif python_configuration.identifier.startswith('pp'):
elif implementation_id.startswith('pp'):
assert python_configuration.url is not None
installation_path = install_pypy(python_configuration.version, python_configuration.arch, python_configuration.url)
else:
@@ -118,6 +127,8 @@ def setup_python(python_configuration: PythonConfiguration, dependency_constrain
assert (installation_path / 'python.exe').exists()
log.step('Setting up build environment...')
# set up PATH and environment variables for run_with_env
env = os.environ.copy()
env['PYTHON_VERSION'] = python_configuration.version
@@ -148,7 +159,8 @@ def setup_python(python_configuration: PythonConfiguration, dependency_constrain
print("cibuildwheel: pip available on PATH doesn't match our installed instance. If you have modified PATH, ensure that you don't overwrite cibuildwheel's entry or insert pip above it.", file=sys.stderr)
exit(1)
# prepare the Python environment
log.step('Installing build tools...')
call(['python', '-m', 'pip', 'install', '--upgrade', 'pip', *dependency_constraint_flags], env=env)
call(['pip', '--version'], env=env)
call(['pip', 'install', '--upgrade', 'setuptools', 'wheel', *dependency_constraint_flags], env=env)
@@ -177,8 +189,15 @@ 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)
log.step('Performing PEP518 workaround...')
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:
@@ -186,110 +205,122 @@ def build(options: BuildOptions) -> None:
built_wheel_dir = temp_dir / 'built_wheel'
repaired_wheel_dir = temp_dir / 'repaired_wheel'
# install nuget as best way to provide python
nuget = Path('C:\\cibw\\nuget.exe')
download('https://dist.nuget.org/win-x86-commandline/latest/nuget.exe', nuget)
try:
if options.before_all:
log.step('Running before_all...')
env = options.environment.as_dictionary(prev_environment=os.environ)
before_all_prepared = prepare_command(options.before_all, project='.', package=options.package_dir)
shell(before_all_prepared, env=env)
if options.before_all:
env = options.environment.as_dictionary(prev_environment=os.environ)
before_all_prepared = prepare_command(options.before_all, project='.', package=options.package_dir)
shell(before_all_prepared, env=env)
python_configurations = get_python_configurations(options.build_selector)
python_configurations = get_python_configurations(options.build_selector)
for config in python_configurations:
dependency_constraint_flags: Sequence[Union[str, PathLike]] = []
if options.dependency_constraints:
dependency_constraint_flags = [
'-c', options.dependency_constraints.get_for_python_version(config.version)
]
for config in python_configurations:
log.build_start(config.identifier)
# install Python
env = setup_python(config, dependency_constraint_flags, options.environment)
dependency_constraint_flags: Sequence[Union[str, PathLike]] = []
if options.dependency_constraints:
dependency_constraint_flags = [
'-c', options.dependency_constraints.get_for_python_version(config.version)
]
# run the before_build command
if options.before_build:
before_build_prepared = prepare_command(options.before_build, project='.', package=options.package_dir)
shell(before_build_prepared, env=env)
# install Python
env = setup_python(config, dependency_constraint_flags, options.environment)
# activate the PEP 518 patch if on Windows Python 3.5
# (will only have an effect if PEP 517 builds are used):
if config.version.startswith('3.5'):
pep_518_cp35_workaround(options.package_dir, env)
# run the before_build command
if options.before_build:
log.step('Running before_build...')
before_build_prepared = prepare_command(options.before_build, project='.', package=options.package_dir)
shell(before_build_prepared, env=env)
# build the wheel
if built_wheel_dir.exists():
shutil.rmtree(built_wheel_dir)
built_wheel_dir.mkdir(parents=True)
# Path.resolve() is needed. Without it pip wheel may try to fetch package from pypi.org
# see https://github.com/joerick/cibuildwheel/pull/369
call([
'pip', 'wheel',
options.package_dir.resolve(),
'-w', built_wheel_dir,
'--no-deps',
*get_build_verbosity_extra_flags(options.build_verbosity)
], env=env)
# activate the PEP 518 patch if on Windows Python 3.5
# (will only have an effect if PEP 517 builds are used):
if config.version.startswith('3.5'):
pep_518_cp35_workaround(options.package_dir, env)
built_wheel = next(built_wheel_dir.glob('*.whl'))
log.step('Building wheel...')
if built_wheel_dir.exists():
shutil.rmtree(built_wheel_dir)
built_wheel_dir.mkdir(parents=True)
# Path.resolve() is needed. Without it pip wheel may try to fetch package from pypi.org
# see https://github.com/joerick/cibuildwheel/pull/369
call([
'pip', 'wheel',
options.package_dir.resolve(),
'-w', built_wheel_dir,
'--no-deps',
*get_build_verbosity_extra_flags(options.build_verbosity)
], env=env)
# repair the wheel
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:
repair_command_prepared = prepare_command(options.repair_command, wheel=built_wheel, dest_dir=repaired_wheel_dir)
shell(repair_command_prepared, env=env)
repaired_wheel = next(repaired_wheel_dir.glob('*.whl'))
built_wheel = next(built_wheel_dir.glob('*.whl'))
if options.test_command:
# set up a virtual environment to install and test from, to make sure
# there are no dependencies that were pulled in at build time.
call(['pip', 'install', 'virtualenv', *dependency_constraint_flags], env=env)
venv_dir = Path(tempfile.mkdtemp())
# repair the wheel
if repaired_wheel_dir.exists():
shutil.rmtree(repaired_wheel_dir)
repaired_wheel_dir.mkdir(parents=True)
# Use --no-download to ensure determinism by using seed libraries
# built into virtualenv
call(['python', '-m', 'virtualenv', '--no-download', venv_dir], env=env)
if built_wheel.name.endswith('none-any.whl'):
raise NonPlatformWheelError()
virtualenv_env = env.copy()
virtualenv_env['PATH'] = os.pathsep.join([
str(venv_dir / 'Scripts'),
virtualenv_env['PATH'],
])
if options.repair_command:
log.step('Repairing wheel...')
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)
# check that we are using the Python from the virtual environment
call(['which', 'python'], env=virtualenv_env)
repaired_wheel = next(repaired_wheel_dir.glob('*.whl'))
if options.before_test:
before_test_prepared = prepare_command(
options.before_test,
project='.',
package=options.package_dir
if options.test_command:
log.step('Testing wheel...')
# set up a virtual environment to install and test from, to make sure
# there are no dependencies that were pulled in at build time.
call(['pip', 'install', 'virtualenv', *dependency_constraint_flags], env=env)
venv_dir = Path(tempfile.mkdtemp())
# Use --no-download to ensure determinism by using seed libraries
# built into virtualenv
call(['python', '-m', 'virtualenv', '--no-download', venv_dir], env=env)
virtualenv_env = env.copy()
virtualenv_env['PATH'] = os.pathsep.join([
str(venv_dir / 'Scripts'),
virtualenv_env['PATH'],
])
# check that we are using the Python from the virtual environment
call(['which', 'python'], env=virtualenv_env)
if options.before_test:
before_test_prepared = prepare_command(
options.before_test,
project='.',
package=options.package_dir
)
shell(before_test_prepared, env=virtualenv_env)
# install the wheel
call(['pip', 'install', str(repaired_wheel) + options.test_extras], env=virtualenv_env)
# test the wheel
if options.test_requires:
call(['pip', 'install'] + options.test_requires, env=virtualenv_env)
# run the tests from c:\, with an absolute path in the command
# (this ensures that Python runs the tests against the installed wheel
# and not the repo code)
test_command_prepared = prepare_command(
options.test_command,
project=Path('.').resolve(),
package=options.package_dir.resolve()
)
shell(before_test_prepared, env=virtualenv_env)
shell(test_command_prepared, cwd='c:\\', env=virtualenv_env)
# install the wheel
call(['pip', 'install', str(repaired_wheel) + options.test_extras], env=virtualenv_env)
# clean up
shutil.rmtree(venv_dir)
# test the wheel
if options.test_requires:
call(['pip', 'install'] + options.test_requires, env=virtualenv_env)
# run the tests from c:\, with an absolute path in the command
# (this ensures that Python runs the tests against the installed wheel
# and not the repo code)
test_command_prepared = prepare_command(
options.test_command,
project=Path('.').resolve(),
package=options.package_dir.resolve()
)
shell(test_command_prepared, cwd='c:\\', env=virtualenv_env)
# clean up
shutil.rmtree(venv_dir)
# we're all done here; move it to output (remove if already exists)
shutil.move(str(repaired_wheel), options.output_dir)
# we're all done here; move it to output (remove if already exists)
shutil.move(str(repaired_wheel), options.output_dir)
log.build_end()
except subprocess.CalledProcessError as error:
log.error(f'Command {error.cmd} failed with code {error.returncode}. {error.stdout}')
exit(1)
+17
View File
@@ -0,0 +1,17 @@
---
title: Changelog
---
{%
include-markdown "../README.md"
start="<!--changelog-start-->"
end="<!--changelog-end-->"
%}
<script>
// undo the scrollTop that the theme did on this page, as there are loads
// of toc entries and it's disorientating.
window.addEventListener('DOMContentLoaded', function() {
$('.wy-nav-side').scrollTop(0)
})
</script>
+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
```
+231
View File
@@ -0,0 +1,231 @@
# Fields:
# name: required, printed name
# gh: Github repo (eventually a url: could be added for non-github projects)
# stars: Github repo (optional, if different from package, such as for Twisted)
# os: Operating system list, [windows, apple, linux] (optional)
# ci: [appveyor, github, azurepipelines, circleci, gitlab, travisci] (optional)
# notes: (text, optional)
- name: Matplotlib
gh: matplotlib/matplotlib
notes: The venerable Matplotlib, a Python library with C++ portions
ci: [github]
os: [windows, apple, linux]
- name: pyinstrument_cext
gh: joerick/pyinstrument_cext
ci: [travisci, appveyor]
os: [windows, apple, linux]
notes: A simple C extension, without external dependencies
- name: websockets
gh: aaugustin/websockets
ci: [travisci]
ci_config: .travis.yml
os: [apple, linux]
notes: |
Library for building WebSocket servers and clients. Mostly written in
Python, with a small C 'speedups' extension module.
- name: Parselmouth
gh: YannickJadoul/Parselmouth
notes: A Python interface to the Praat software package, using pybind11, C++17 and CMake, with the core Praat static library built only once and shared between wheels.
ci: [github]
os: [windows, apple, linux]
# Seems to be defunct
# - name: python-admesh
# gh: admesh/python-admesh
- name: pybase64
gh: mayeut/pybase64
ci: [github]
os: [windows, apple, linux]
- name: KDEpy
gh: tommyod/KDEpy
ci: [github]
os: [windows, apple, linux]
- name: AutoPy
gh: autopilot-rs/autopy
ci: [travisci]
os: [windows, apple, linux]
notes: Includes a Windows Travis build.
# Seems to be defunct
# - name: apriltags2-ethz
# gh: safijari/apriltags2_ethz
- name: TgCrypto
gh: pyrogram/tgcrypto
ci: [travisci]
os: [windows, apple, linux]
notes: Includes a Windows Travis build.
- name: twisted-iocpsupport
gh: twisted/twisted-iocpsupport
stars: twisted/twisted
notes: A submodule of Twisted that hooks into native C APIs using Cython.
ci: [github]
os: [windows]
# cibuildwheel moved to backup folder
# - name: gmic-py
# gh: myselfhimself/gmic-py
- name: River
gh: online-ml/river
ci: [github]
os: [windows, apple, linux]
- name: PyAV
gh: PyAV-Org/PyAV
ci: [github]
os: [windows, apple, linux]
notes: Pythonic bindings for FFmpeg's libraries.
- name: aiortc
gh: aiortc/aiortc
ci: [github]
os: [apple, linux]
notes: WebRTC and ORTC implementation for Python using asyncio.
- name: aioquic
gh: aiortc/aioquic
ci: [github]
os: [windows, apple, linux]
- name: pikepdf
gh: pikepdf/pikepdf
ci: [azurepipelines]
os: [windows, apple, linux]
- name: fathon
gh: stfbnc/fathon
ci: [travisci]
os: [apple, linux]
- name: etebase-py
gh: etesync/etebase-py
notes: Python bindings to a Rust library using `setuptools-rust`, and `sccache` for improved speed.
ci: [travisci]
os: [linux]
- name: xmlstarlet
gh: dimitern/xmlstarlet
notes: Python 3.6+ CFFI bindings with true MSVC build.
ci: [github]
os: [windows, apple, linux]
- name: bx-python
gh: bxlab/bx-python
notes: A library that includes Cython extensions.
ci: [travisci]
os: [apple, linux]
- name: coverage.py
gh: nedbat/coveragepy
ci: [github]
os: [windows, apple, linux]
notes: The coverage tool for Python
- name: scikit-learn
gh: scikit-learn/scikit-learn
ci: [github]
os: [windows, apple, linux]
ci_config: .github/workflows/wheels.yml
notes: |
The machine learning library. A complex but clean config using many of
cibuildwheel's features to build a large project with Cython and C++
extensions.
- name: scikit-image
gh: scikit-image/scikit-image
ci: [github]
os: [windows, apple, linux]
ci_config: .github/workflows/cibuildwheel.yml
notes: |
Image processing library. Uses cibuildwheel to build and test a project
that uses Cython with platform-native code.
- name: google neuroglancer
gh: google/neuroglancer
ci: [github]
os: [windows, apple, linux]
- name: h5py
gh: h5py/h5py
ci: [azurepipelines]
os: [windows, apple, linux]
- name: pyzmq
gh: zeromq/pyzmq
ci: [github]
os: [windows, apple, linux]
ci_config: .github/workflows/wheels.yml
notes: |
Python bindings for zeromq, the networking library. Uses Cython and CFFI.
- name: python-rapidjson
gh: python-rapidjson/python-rapidjson
ci: [travisci, gitlab, appveyor]
os: [windows, linux]
- name: jq.py
gh: mwilliamson/jq.py
ci: [travisci]
os: [apple, linux]
- name: pybind11 python_example
gh: pybind/python_example
ci: [github]
os: [windows, apple, linux]
- name: pybind11 cmake_example
gh: pybind/cmake_example
ci: [github]
os: [windows, apple, linux]
- name: pybind11 scikit_build_example
gh: pybind/scikit_build_example
ci: [github]
os: [windows, apple, linux]
- name: iminuit
gh: scikit-hep/iminuit
ci: [github]
os: [windows, apple, linux]
- name: pyjet
gh: scikit-hep/pyjet
ci: [github]
os: [windows, apple, linux]
- name: numpythia
gh: scikit-hep/numpythia
ci: [github]
os: [apple, linux]
- name: boost-histogram
gh: scikit-hep/boost-histogram
ci: [github, travisci]
os: [windows, apple, linux]
notes: Supports full range of wheels, including PyPy and alternate archs.
- name: Rtree
gh: Toblerity/rtree
ci: [github]
os: [windows, apple, linux]
- name: psutil
gh: giampaolo/psutil
ci: [github]
os: [windows, apple, linux]
- name: Dependency Injector
gh: ets-labs/python-dependency-injector
ci: [travisci]
os: [windows, apple, linux]
notes: Dependency injection framework for Python, uses Windows TravisCI
+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" role="img" viewBox="0 0 24 24" width="16px" fill="#606060"><title>Apple icon</title><path d="M12.152 6.896c-.948 0-2.415-1.078-3.96-1.04-2.04.027-3.91 1.183-4.961 3.014-2.117 3.675-.546 9.103 1.519 12.09 1.013 1.454 2.208 3.09 3.792 3.039 1.52-.065 2.09-.987 3.935-.987 1.831 0 2.35.987 3.96.948 1.637-.026 2.676-1.48 3.676-2.948 1.156-1.688 1.636-3.325 1.662-3.415-.039-.013-3.182-1.221-3.22-4.857-.026-3.04 2.48-4.494 2.597-4.559-1.429-2.09-3.623-2.324-4.39-2.376-2-.156-3.675 1.09-4.61 1.09zM15.53 3.83c.843-1.012 1.4-2.427 1.245-3.83-1.207.052-2.662.805-3.532 1.818-.78.896-1.454 2.338-1.273 3.714 1.338.104 2.715-.688 3.559-1.701"/></svg>

After

Width:  |  Height:  |  Size: 683 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" role="img" viewBox="0 0 24 24" width="16px" fill="#606060"><title>AppVeyor icon</title><path d="M 12,0 C 18.6,0 24,5.4 24,12 24,18.6 18.6,24 12,24 5.4,24 0,18.6 0,12 0,5.4 5.4,0 12,0 Z m 2.94,14.34 C 16.26,12.66 16.08,10.26 14.4,9 12.78,7.74 10.38,8.04 9,9.72 7.68,11.4 7.86,13.8 9.54,15.06 c 1.68,1.26 4.08,0.96 5.4,-0.72 z m -6.42,7.8 c 0.72,0.3 2.28,0.6 3.06,0.6 l 5.22,-7.56 c 1.68,-2.52 1.26,-5.94 -1.08,-7.8 -2.1,-1.68 -5.04,-1.62 -7.14,0 l -7.26,5.58 c 0.18,1.92 0.72,2.88 0.72,2.94 l 4.14,-4.5 c -0.3,1.98 0.42,4.02 2.1,5.28 1.44,1.14 3.18,1.44 4.86,1.08 z"/></svg>

After

Width:  |  Height:  |  Size: 613 B

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" role="img" viewBox="0 0 24 24" width="16px" fill="#606060"><title>Azure Pipelines icon</title><path d="M1.8 18H0v6h6v-1.8H1.8zM23 0h-8.93a2 2 0 0 0-1.67.89L9 5.99H1a1 1 0 0 0-1 1v5.5l3.5 3.61 1.2-1.29 1.5 1.5L5 17.53l1.48 1.48 1.22-1.22 1.5 1.51L8 20.5l3.5 3.5H17a1 1 0 0 0 1-1v-8l5.11-3.4A2 2 0 0 0 24 9.92V1a1 1 0 0 0-1-1zm-5 9a3 3 0 1 1 0-6 3 3 0 0 1 0 6z"/></svg>

After

Width:  |  Height:  |  Size: 407 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" role="img" viewBox="0 0 24 24" width="16px" fill="#606060"><title>CircleCI icon</title><path d="M8.963 12c0-1.584 1.284-2.855 2.855-2.855 1.572 0 2.856 1.284 2.856 2.855 0 1.572-1.284 2.856-2.856 2.856-1.57 0-2.855-1.284-2.855-2.856zm2.855-12C6.215 0 1.522 3.84.19 9.025c-.01.036-.01.07-.01.12 0 .313.252.576.575.576H5.59c.23 0 .433-.13.517-.333.997-2.16 3.18-3.672 5.712-3.672 3.466 0 6.286 2.82 6.286 6.287 0 3.47-2.82 6.29-6.29 6.29-2.53 0-4.714-1.5-5.71-3.673-.097-.19-.29-.336-.517-.336H.755c-.312 0-.575.253-.575.576 0 .037.014.072.014.12C1.514 20.16 6.214 24 11.818 24c6.624 0 12-5.375 12-12 0-6.623-5.376-12-12-12z"/></svg>

After

Width:  |  Height:  |  Size: 671 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" role="img" viewBox="0 0 24 24" width="16px" fill="#606060"><title>GitHub icon</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg>

After

Width:  |  Height:  |  Size: 855 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" role="img" viewBox="0 0 24 24" width="16px" fill="#606060"><title>GitLab icon</title><path d="M4.845.904c-.435 0-.82.28-.955.692C2.639 5.449 1.246 9.728.07 13.335a1.437 1.437 0 00.522 1.607l11.071 8.045c.2.145.472.144.67-.004l11.073-8.04a1.436 1.436 0 00.522-1.61c-1.285-3.942-2.683-8.256-3.817-11.746a1.004 1.004 0 00-.957-.684.987.987 0 00-.949.69l-2.405 7.408H8.203l-2.41-7.408a.987.987 0 00-.942-.69h-.006zm-.006 1.42l2.173 6.678H2.675zm14.326 0l2.168 6.678h-4.341zm-10.593 7.81h6.862c-1.142 3.52-2.288 7.04-3.434 10.559L8.572 10.135zm-5.514.005h4.321l3.086 9.5zm13.567 0h4.325c-2.467 3.17-4.95 6.328-7.411 9.502 1.028-3.167 2.059-6.334 3.086-9.502zM2.1 10.762l6.977 8.947-7.817-5.682a.305.305 0 01-.112-.341zm19.798 0l.952 2.922a.305.305 0 01-.11.341v.002l-7.82 5.68.026-.035z"/></svg>

After

Width:  |  Height:  |  Size: 830 B

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.4 KiB

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" role="img" viewBox="0 0 24 24" width="16px" fill="#606060"><title>Travis CI icon</title><path d="M9.32 13.025a.485.485 0 1 1-.97 0c0-.446-.167-.758-.406-.758-.239 0-.405.312-.405.758a.485.485 0 1 1-.97 0c0-1.187.713-1.728 1.375-1.728s1.376.541 1.376 1.728zm6.017.485a.485.485 0 0 0 .485-.485c0-.446.167-.758.405-.758s.405.312.405.758a.485.485 0 1 0 .97 0c0-1.187-.713-1.728-1.375-1.728s-1.375.541-1.375 1.728c0 .268.217.485.485.485zm7.967-4.454l-.191 2.459a.801.801 0 0 1-.367.623.852.852 0 0 1-.46.13 1.07 1.07 0 0 1-.366-.068c-.271-.101-.544-.192-.817-.285a8.978 8.978 0 0 1-.094 1.614c-.04.242-.092.471-.138.707a.485.485 0 0 1-.024.125 19.471 19.471 0 0 1-1.033 3.513l.033-.02.897-.537c.193-.137.599-.122.815.1a.645.645 0 0 1 .173.577.743.743 0 0 1-.053.159c-.061.135-.319.706-.866 1.906-.675 1.483-2.06 1.77-2.121 1.782.001.001-.907.214-1.879.44C15.458 23.419 13.87 24 12.087 24c-1.84 0-3.448-.58-4.787-1.713l-1.924-.45c-.041-.008-1.427-.294-2.103-1.778l-.87-1.914c-.005-.019-.05-.158-.053-.177-.009-.625.621-.914 1.023-.632l.858.512c.006.003.074.043.171.085a20.443 20.443 0 0 1-.982-3.444c-.063-.317-.129-.63-.183-.96a8.937 8.937 0 0 1-.09-1.7c-.357.118-.713.24-1.066.372-.292.109-.593.087-.827-.062a.802.802 0 0 1-.366-.621L.695 9.055c-.036-.475.305-.969.794-1.152l.3-.117c.225-.089.505-.198.837-.318C3.65 3.124 7.566 0 12.041 0c4.516 0 8.438 3.158 9.434 7.549.472.153.843.281 1.036.355.492.183.833.677.793 1.152zm-4.612 8.973c.369-.815.678-1.708.93-2.67l-.997.713a.952.952 0 0 1-.655.166l-4.467-.47a.96.96 0 0 1-.821-.698l-.558-1.923a2.482 2.482 0 0 0-.244 0l-.56 1.93a.955.955 0 0 1-.82.691l-4.471.471a.951.951 0 0 1-.642-.162l-.723-.503c.231.889.506 1.708.824 2.451.609-.028 1.207-.069 1.209-.069.001 0 .434-.039.788-.332l1.061-.885c.148-.165.652-.465 1.33-.271.196.055.495.146.815.243.062.019.12.05.17.092.532.445 1.832.445 2.365.002a.481.481 0 0 1 .168-.091c.337-.103.631-.192.823-.247.68-.193 1.182.108 1.374.314l1.016.843c.353.294.785.332.789.332-.001.001.658.045 1.296.073zm-6.605 5.001a6.42 6.42 0 0 0 1.949-.313c-.932-.209-1.555-1.019-1.588-1.062l-.406-.542-.407.543c-.031.043-.641.842-1.558 1.06.63.196 1.295.314 2.01.314zm6.941-4.016a63.622 63.622 0 0 1-1.701-.089 2.519 2.519 0 0 1-1.339-.554l-1.065-.888c-.055-.051-.187-.152-.442-.083-.176.05-.436.13-.717.216-.878.655-2.567.655-3.443-.003a43.693 43.693 0 0 0-.709-.212c-.258-.076-.386.03-.411.052l-1.097.918a2.523 2.523 0 0 1-1.341.553s-.872.059-1.594.085h-.002l-.106.004a2.41 2.41 0 0 1-1.341-.343l-.018-.01.453.996c.463 1.017 1.389 1.225 1.427 1.232.014.004 2.754.646 3.822.889.781.174 1.447-.696 1.454-.705l.795-1.061c.183-.245.594-.245.776 0l.796 1.061c.007.009.682.881 1.455.705 1.067-.243 3.807-.886 3.807-.886a2.193 2.193 0 0 0 1.442-1.236l.452-.993-.026.015a2.27 2.27 0 0 1-1.327.337zm1.096-7.412a28.286 28.286 0 0 0-15.998-.075 8.025 8.025 0 0 0 .067 1.845c.045.275.1.535.152.8l1.591 1.108 4.461-.476.642-2.243a.488.488 0 0 1 .395-.345 3.855 3.855 0 0 1 1.135.003.482.482 0 0 1 .394.344l.652 2.245 4.462.468 1.864-1.336c.036-.19.079-.374.111-.568a7.89 7.89 0 0 0 .072-1.77zm2.214-2.623c-.005-.034-.073-.133-.165-.167l-.004-.001c-.22-.083-.68-.242-1.256-.423l-.007-.005c-.955-.299-2.771-.823-4.267-.99a.485.485 0 0 1 .108-.964c1.192.134 2.529.466 3.637.787C19.298 3.552 15.913.97 12.041.97c-3.832 0-7.207 2.549-8.318 6.165a20.252 20.252 0 0 1 3.27-.705.484.484 0 1 1 .121.962 19.235 19.235 0 0 0-3.909.899l-.005.004c-.432.149-.785.288-1.056.394l-.315.123c-.094.035-.162.135-.167.175l.177 2.264a29.36 29.36 0 0 1 10.164-1.817c3.442 0 6.881.607 10.157 1.82l.178-2.275zm-8.534-5.986h-3.539a.485.485 0 0 0-.485.485v.811a.485.485 0 1 0 .97 0v-.326h.746v3.308h-.521a.485.485 0 1 0 0 .97h2.061a.485.485 0 1 0 0-.97h-.57V3.963h.853v.326a.485.485 0 1 0 .97 0v-.811a.485.485 0 0 0-.485-.485z"/></svg>

After

Width:  |  Height:  |  Size: 3.7 KiB

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" role="img" viewBox="0 0 24 24" width="16px" fill="#606060"><title>Windows icon</title><path d="M0 3.449L9.75 2.1v9.451H0m10.949-9.602L24 0v11.4H10.949M0 12.6h9.75v9.451L0 20.699M10.949 12.6H24V24l-12.9-1.801"/></svg>

After

Width:  |  Height:  |  Size: 256 B

+3 -3
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')
@@ -33,4 +33,4 @@ Obviously, manual steps are for chumps, so we can automate this a little by usin
If you don't need much control over the release of a package, you can set up cibuildwheel to deliver the wheels straight to PyPI. This doesn't require anycloud storage to work - you just need to bump the version and tag it.
[`examples/travis-ci-deploy.yml`](https://github.com/joerick/cibuildwheel/blob/master/examples/travis-ci-deploy.yml) and [`examples/github-deploy.yml`](https://github.com/joerick/cibuildwheel/blob/master/examples/github-deploy.yml) are example configurations that automatocially upload wheels to PyPI. Also check out [this example repo](https://github.com/joerick/cibuildwheel-autopypi-example) for more detailed instructions on how to set this up.
[`examples/travis-ci-deploy.yml`](https://github.com/joerick/cibuildwheel/blob/master/examples/travis-ci-deploy.yml) and [`examples/github-deploy.yml`](https://github.com/joerick/cibuildwheel/blob/master/examples/github-deploy.yml) are example configurations that automatically upload wheels to PyPI. Also check out [this example repo](https://github.com/joerick/cibuildwheel-autopypi-example) for more detailed instructions on how to set this up.
+1 -2
View File
@@ -29,7 +29,6 @@ h1, h2, h3, h4, h5, h6 {
border-bottom: 1px solid #e1e4e5;
margin-bottom: 0.8em;
padding-bottom: 0.2em;
}
.rst-content blockquote {
@@ -59,7 +58,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;
+73
View File
@@ -61,3 +61,76 @@ 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.
### Automatic updates {: #automatic-updates}
Selecting a moving target (like the latest release) is generally a bad idea in CI. If something breaks, you can't tell whether it was your code or an upstream update that caused the breakage, and in a worse-case scenario, it could occur during a release.
There are two suggested methods for keeping cibuildwheel up to date that instead involve scheduled pull requests using GitHub's dependabot.
#### Option 1: GitHub Action
If you use GitHub Actions for builds, you can use cibuildwheel as an action:
```yaml
uses: joerick/cibuildwheel@v1.7.3
```
This is a composite step that just installs and runs cibuildwheel. You can set command-line options as `with:` parameters, and use `env:` as normal.
Then, your `dependabot.yml` file could look like this:
```yaml
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
ignore:
# Optional: Official actions have moving tags like v1;
# if you use those, you don't need updates.
- dependency-name: "actions/*"
```
#### Option 2: Requirement files
The second option, and the only one that supports other CI systems, is using a `requirements-*.txt` file. The file should have a distinct name and have only one entry:
```bash
# requirements-cibw.txt
cibuildwheel==1.7.3
```
Then your install step would have `python -m pip install -r requirements-cibw.txt` in it. Your `dependabot.yml` file could look like this:
```yaml
version: 2
updates:
- package-ecosystem: "pip"
directory: "/"
schedule:
interval: "daily"
```
This will also try to update other pins in all requirement files, so be sure you want to do that. The only control you have over the files used is via the directory option.
+3 -3
View File
@@ -2,9 +2,9 @@
title: Home
---
{%
includemarkdown "../README.md"
start="<!--intro-start-->"
{%
include-markdown "../README.md"
start="<!--intro-start-->"
end="<!--intro-end-->"
%}
@@ -1,84 +0,0 @@
import cgi
import re
from pathlib import Path
import mkdocs
INCLUDE_TAG_REGEX = re.compile(
r'''
{% # opening tag
\s*
include # directive name
\s+
"(?P<filename>[^"]+)" # "filename"
\s*
%} # closing tag
''',
flags=re.VERBOSE,
)
INCLUDEMARKDOWN_TAG_REGEX = re.compile(
r'''
{% # opening tag
\s*
includemarkdown # directive name
\s+
"(?P<filename>[^"]+)" # "filename"
(?:\s+start="(?P<start>[^"]+)")? # optional start expression
(?:\s+end="(?P<end>[^"]+)")? # optional end expression
\s*
%} # closing tag
''',
flags=re.VERBOSE,
)
class ImportMarkdownPlugin(mkdocs.plugins.BasePlugin):
def on_page_markdown(self, markdown, page, **kwargs):
page_src_path = page.file.abs_src_path
def found_include_tag(match):
filename = match.group('filename')
file_path_abs = Path(page_src_path).parent / filename
if not file_path_abs.exists():
raise ValueError('file not found', filename)
text_to_include = file_path_abs.read_text(encoding='utf8')
# Allow good practice of having a final newline in the file
if text_to_include.endswith('\n'):
text_to_include = text_to_include[:-1]
return text_to_include
def found_includemarkdown_tag(match):
filename = match.group('filename')
start = match.group('start')
end = match.group('end')
file_path_abs = Path(page_src_path).parent / filename
if not file_path_abs.exists():
raise ValueError('file not found', filename)
text_to_include = file_path_abs.read_text(encoding='utf8')
if start:
_, _, text_to_include = text_to_include.partition(start)
if end:
text_to_include, _, _ = text_to_include.partition(end)
return (
'<!-- BEGIN INCLUDE %s %s %s -->\n' % (
filename, cgi.escape(start or ''), cgi.escape(end or '')
)
+ text_to_include
+ '\n<!-- END INCLUDE -->'
)
markdown = re.sub(INCLUDE_TAG_REGEX, found_include_tag, markdown)
markdown = re.sub(INCLUDEMARKDOWN_TAG_REGEX, found_includemarkdown_tag, markdown)
return markdown
@@ -1,15 +0,0 @@
from setuptools import setup
setup(
name='mkdocs_include_markdown_plugin',
version='1.0',
author='Joe Rickerby',
license='Apache 2',
packages=['mkdocs_include_markdown_plugin'],
entry_points={
'mkdocs.plugins': [
'importmarkdown = mkdocs_include_markdown_plugin.plugin:ImportMarkdownPlugin',
]
},
zip_safe=False
)
+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.3 | pp27-macosx_x86_64 | pp27-manylinux_x86_64 | | | pp27-win32 | | | |
| PyPy 3.6 v7.3.3 | pp36-macosx_x86_64 | pp36-manylinux_x86_64 | | | pp36-win32 | | | |
| PyPy 3.7 (beta) v7.3.3 | 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
+16 -1
View File
@@ -17,6 +17,8 @@ For more info on this file, check out the [docs](https://help.github.com/en/acti
[`examples/github-deploy.yml`](https://github.com/joerick/cibuildwheel/blob/master/examples/github-deploy.yml) extends this minimal example with a demonstration of how to automatically upload the built wheels to PyPI.
You can also use cibuildwheel directly as an action with `uses: joerick/cibuildwheel@v1.7.3`; this combines the download and run steps into a single action, and command line arguments are available via `with:`. This makes it easy to manage cibuildwheel updates via normal actions update mechanisms like dependabot, see [Automatic updates](faq.md#automatic-updates).
# Azure Pipelines [linux/mac/windows] {: #azure-pipelines}
To build Linux, Mac, and Windows wheels on Azure Pipelines, create a `azure-pipelines.yml` file in your repo.
@@ -48,7 +50,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 +68,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.
+20
View File
@@ -0,0 +1,20 @@
---
title: Working examples
---
{%
include-markdown "../README.md"
start="<!--working-examples-start-->"
end="<!--working-examples-end-->"
%}
<style>
.wy-nav-content {
/* this table benefits from a wider page */
max-width: 1000px;
}
.rst-content .section table img {
/* make the icons darker on this page */
filter: brightness(0.5);
}
</style>
+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.3
install: python -m pip install cibuildwheel==1.7.3
build_script: python -m cibuildwheel --output-dir wheelhouse
+16 -7
View File
@@ -4,9 +4,12 @@ jobs:
steps:
- task: UsePythonVersion@0
- bash: |
set -o errexit
python3 -m pip install --upgrade pip
pip3 install cibuildwheel==1.5.3
cibuildwheel --output-dir wheelhouse .
pip3 install cibuildwheel==1.7.3
displayName: Install dependencies
- bash: cibuildwheel --output-dir wheelhouse .
displayName: Build wheels
- task: PublishBuildArtifacts@1
inputs: {pathtoPublish: 'wheelhouse'}
@@ -15,11 +18,14 @@ jobs:
steps:
- task: UsePythonVersion@0
- bash: |
set -o errexit
python3 -m pip install --upgrade pip
pip3 install cibuildwheel==1.5.3
cibuildwheel --output-dir wheelhouse .
python3 -m pip install cibuildwheel==1.7.3
displayName: Install dependencies
- bash: cibuildwheel --output-dir wheelhouse .
displayName: Build wheels
- task: PublishBuildArtifacts@1
inputs: {pathtoPublish: 'wheelhouse'}
inputs: {pathtoPublish: wheelhouse}
- job: windows
pool: {vmImage: 'vs2017-win2016'}
@@ -28,8 +34,11 @@ jobs:
- script: choco install vcpython27 -f -y
displayName: Install Visual C++ for Python 2.7
- bash: |
set -o errexit
python -m pip install --upgrade pip
pip install cibuildwheel==1.5.3
cibuildwheel --output-dir wheelhouse .
pip install cibuildwheel==1.7.3
displayName: Install dependencies
- bash: cibuildwheel --output-dir wheelhouse .
displayName: Build wheels
- task: PublishBuildArtifacts@1
inputs: {pathtoPublish: 'wheelhouse'}
+3 -3
View File
@@ -11,7 +11,7 @@ jobs:
- run:
name: Build the Linux wheels.
command: |
pip3 install --user cibuildwheel==1.5.3
pip3 install --user cibuildwheel==1.7.3
cibuildwheel --output-dir wheelhouse
- store_artifacts:
path: wheelhouse/
@@ -19,13 +19,13 @@ jobs:
osx-wheels:
working_directory: ~/osx-wheels
macos:
xcode: "10.0.0"
xcode: 10.0.0
steps:
- checkout
- run:
name: Build the OS X wheels.
command: |
pip3 install --user cibuildwheel==1.5.3
pip3 install cibuildwheel==1.7.3
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.3
python -m pip install cibuildwheel==1.7.3
- 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.3
python -m pip install cibuildwheel==1.7.3
- 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/
+9 -13
View File
@@ -19,22 +19,18 @@ jobs:
# make sure it's on PATH as 'python3'
- ln -s /c/Python38/python.exe /c/Python38/python3.exe
env:
global:
- TWINE_USERNAME=__token__
# Note: TWINE_PASSWORD is set to a PyPI API token in Travis settings
install:
- python3 -m pip install cibuildwheel==1.5.3
- python3 -m pip install cibuildwheel==1.7.3
script:
# build the wheels, put them into './wheelhouse'
- python3 -m cibuildwheel --output-dir wheelhouse
after_success:
# if the release was tagged, upload them to PyPI
- |
if [[ $TRAVIS_TAG ]]; then
python3 -m pip install twine
python3 -m twine upload wheelhouse/*.whl
fi
deploy:
provider: pypi
username: "__token__"
skip_cleanup: true
on:
tags: true
password:
secure: "" # Set to an encrypted API token. See https://docs.travis-ci.com/user/deployment/pypi/
+1 -1
View File
@@ -26,7 +26,7 @@ jobs:
- ln -s /c/Python38/python.exe /c/Python38/python3.exe
install:
- python3 -m pip install cibuildwheel==1.5.3
- python3 -m pip install cibuildwheel==1.7.3
script:
# build the wheels, put them into './wheelhouse'
+3 -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.3
install: python3 -m pip install cibuildwheel==1.7.3
script: python3 -m cibuildwheel --output-dir wheelhouse
after_success: |
python3 -m pip install twine
@@ -65,7 +65,7 @@ jobs:
name: Build and deploy macOS wheels
os: osx
language: shell
install: python3 -m pip install cibuildwheel==1.5.3
install: python3 -m pip install cibuildwheel==1.7.3
script: python3 -m cibuildwheel --output-dir wheelhouse
after_success: |
python3 -m pip install twine
@@ -75,7 +75,7 @@ jobs:
name: Build and deploy Windows wheels
os: windows
language: shell
install: python3 -m pip install cibuildwheel==1.5.3
install: python3 -m pip install cibuildwheel==1.7.3
script: python3 -m cibuildwheel --output-dir wheelhouse
after_success: |
python3 -m pip install twine
+3 -1
View File
@@ -20,7 +20,9 @@ nav:
- deliver-to-pypi.md
- cpp_standards.md
- faq.md
- working-examples.md
- contributing.md
- changelog.md
markdown_extensions:
- fenced_code
@@ -32,4 +34,4 @@ markdown_extensions:
repo_url_shortener: True
plugins:
- importmarkdown
- include-markdown
+7
View File
@@ -0,0 +1,7 @@
[build-system]
requires = [
"setuptools>=42",
"wheel"
]
build-backend = "setuptools.build_meta"
+4 -1
View File
@@ -1,10 +1,13 @@
-e .
-e ./docs/mkdocs_include_markdown_plugin
pytest
pytest-timeout
mkdocs==1.0.4
mkdocs-include-markdown-plugin==2.1.1
pymdown-extensions
pip-tools
requests
click
mypy
pyyaml
pygithub
typing-extensions
+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.3',
install_requires=['bashlex!=0.13', 'toml'],
version='1.7.3',
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,
+21 -3
View File
@@ -1,7 +1,9 @@
import textwrap
import platform
from . import test_projects
from . import utils
import textwrap
import pytest
from cibuildwheel.logger import Logger
from . import test_projects, utils
basic_project = test_projects.new_c_project(
setup_py_add=textwrap.dedent('''
@@ -25,6 +27,22 @@ def test(tmp_path):
assert set(actual_wheels) == set(expected_wheels)
@pytest.mark.skip(reason='to keep test output clean')
def test_sample_build(tmp_path, capfd):
project_dir = tmp_path / 'project'
basic_project.generate(project_dir)
# build the wheels, and let the output passthrough to the caller, so
# we can see how it looks
with capfd.disabled():
logger = Logger()
logger.step('test_sample_build')
try:
utils.cibuildwheel_run(project_dir)
finally:
logger.step_end()
def test_build_identifiers(tmp_path):
project_dir = tmp_path / 'project'
basic_project.generate(project_dir)
+31 -4
View File
@@ -1,4 +1,5 @@
import os
import pytest
import subprocess
import textwrap
from . import utils
@@ -21,18 +22,44 @@ 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
before_all_command = '''python -c "import os;open('{project}/text_info.txt', 'w').write('sample text '+os.environ.get('TEST_VAL', ''))"'''
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_ALL': '''python -c "import os;open('{project}/text_info.txt', 'w').write('sample text '+os.environ.get('TEST_VAL', ''))"''',
'CIBW_BEFORE_ALL': before_all_command,
'CIBW_BEFORE_ALL_LINUX': before_all_command + ''' && python -c "import sys; assert sys.version_info >= (3, 6)"''',
'CIBW_ENVIRONMENT': "TEST_VAL='123'"
})
# 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)
+4 -2
View File
@@ -37,13 +37,15 @@ class TestBeforeTest(TestCase):
def test(tmp_path):
project_dir = tmp_path / 'project'
before_test_project.generate(project_dir)
test_project_dir = project_dir / 'dependency'
test_projects.new_c_project().generate(test_project_dir)
# 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_TEST': '''python -c "import sys; open('/tmp/pythonversion.txt', 'w').write(sys.version)" && python -c "import sys; open('/tmp/pythonprefix.txt', 'w').write(sys.prefix)"''',
'CIBW_BEFORE_TEST_WINDOWS': '''python -c "import sys; open('c:\\pythonversion.txt', 'w').write(sys.version)" && python -c "import sys; open('c:\\pythonprefix.txt', 'w').write(sys.prefix)"''',
'CIBW_BEFORE_TEST': '''python -c "import sys; open('/tmp/pythonversion.txt', 'w').write(sys.version)" && python -c "import sys; open('/tmp/pythonprefix.txt', 'w').write(sys.prefix)" && python -m pip install {project}/dependency''',
'CIBW_BEFORE_TEST_WINDOWS': '''python -c "import sys; open('c:\\pythonversion.txt', 'w').write(sys.version)" && python -c "import sys; open('c:\\pythonprefix.txt', 'w').write(sys.prefix)" && python -m pip install {project}/dependency''',
'CIBW_TEST_REQUIRES': 'nose',
# the 'false ||' bit is to ensure this command runs in a shell on
# mac/linux.
+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)
+14 -7
View File
@@ -11,27 +11,34 @@ def main():
prog="python -m test.test_projects",
description='Generate a test project to check it out'
)
parser.add_argument('--open', action='store_true', help='''
Open the generated project in a file explorer
''')
parser.add_argument('PROJECT', help='''
Python path to a project object. E.g. test.test_0_basic.basic_project
''')
parser.add_argument('OUTPUT', nargs='?', help='''
Path to output dir. If no dir is passed, a tempdir will be generated.
''')
options = parser.parse_args()
module, _, name = options.PROJECT.rpartition('.')
project = getattr(importlib.import_module(module), name)
project_dir = Path(tempfile.mkdtemp())
project_dir = Path(options.OUTPUT or tempfile.mkdtemp())
project.generate(project_dir)
print('Project generated at', project_dir)
print()
if sys.platform == 'darwin':
subprocess.check_call(['open', '--', project_dir])
elif sys.platform == 'linux2':
subprocess.check_call(['xdg-open', '--', project_dir])
elif sys.platform == 'win32':
subprocess.check_call(['explorer', project_dir])
if options.open:
if sys.platform == 'darwin':
subprocess.check_call(['open', '--', project_dir])
elif sys.platform == 'linux2':
subprocess.check_call(['xdg-open', '--', project_dir])
elif sys.platform == 'win32':
subprocess.check_call(['explorer', project_dir])
if __name__ == '__main__':
+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")
''')
)
+17 -2
View File
@@ -64,6 +64,10 @@ class TestSpam(TestCase):
bits = struct.calcsize("P") * 8
if bits == 32:
self.assertEqual(platform.machine(), "i686")
def test_time_to_remove_the_pypy_venv_patch(self):
if sys.platform == "darwin":
assert not hasattr(sys, "pypy_version_info") or sys.pypy_version_info < (7,3,4)
'''
@@ -103,15 +107,26 @@ def test_extras_require(tmp_path):
assert set(actual_wheels) == set(expected_wheels)
project_with_a_failing_test = test_projects.new_c_project()
project_with_a_failing_test.files['test/spam_test.py'] = r'''
from unittest import TestCase
class TestSpam(TestCase):
def test_something(self):
self.fail('this test is supposed to fail')
'''
def test_failing_test(tmp_path):
"""Ensure a failing test causes cibuildwheel to error out and exit"""
project_dir = tmp_path / 'project'
output_dir = tmp_path / 'output'
project_with_a_test.generate(project_dir)
project_with_a_failing_test.generate(project_dir)
with pytest.raises(subprocess.CalledProcessError):
utils.cibuildwheel_run(project_dir, output_dir=output_dir, add_env={
'CIBW_TEST_COMMAND': 'false',
'CIBW_TEST_REQUIRES': 'nose',
'CIBW_TEST_COMMAND': 'nosetests {project}/test',
# manylinux1 has a version of bash that's been shown to have
# problems with this, so let's check that.
'CIBW_MANYLINUX_I686_IMAGE': 'manylinux1',
+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
+2 -1
View File
@@ -10,7 +10,8 @@ def test_defaults():
resources_dir = project_root / 'cibuildwheel' / 'resources'
assert dependency_constraints.base_file_path.samefile(resources_dir / 'constraints.txt')
assert dependency_constraints.get_for_python_version('3.8').samefile(resources_dir / 'constraints.txt')
assert dependency_constraints.get_for_python_version('3.99').samefile(resources_dir / 'constraints.txt')
assert dependency_constraints.get_for_python_version('3.9').samefile(resources_dir / 'constraints-python39.txt')
assert dependency_constraints.get_for_python_version('3.6').samefile(resources_dir / 'constraints-python36.txt')
assert dependency_constraints.get_for_python_version('3.5').samefile(resources_dir / 'constraints-python35.txt')
assert dependency_constraints.get_for_python_version('2.7').samefile(resources_dir / 'constraints-python27.txt')
+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)
+3 -3
View File
@@ -40,7 +40,7 @@ def test_inheritance():
def test_shell_eval():
environment_recipe = parse_environment('VAR="$(echo "a test" string)"')
environment_recipe = parse_environment('VAR="$(echo "a test" string)"')
env_copy = os.environ.copy()
env_copy.pop('VAR', None)
@@ -50,8 +50,8 @@ def test_shell_eval():
)
environment_cmds = environment_recipe.as_shell_commands()
assert environment_dict['VAR'] == 'a test string'
assert environment_cmds == ['export VAR="$(echo "a test" string)"']
assert environment_dict['VAR'] == 'a test string'
assert environment_cmds == ['export VAR="$(echo "a test" string)"']
def test_shell_eval_and_env():
+5 -1
View File
@@ -11,7 +11,11 @@ def test_unknown_platform_non_ci(monkeypatch, capsys):
monkeypatch.delenv('CI', raising=False)
monkeypatch.delenv('BITRISE_BUILD_NUMBER', raising=False)
monkeypatch.delenv('AZURE_HTTP_USER_AGENT', raising=False)
monkeypatch.delenv('GITHUB_WORKFLOW', raising=False)
monkeypatch.delenv('TRAVIS', raising=False)
monkeypatch.delenv('APPVEYOR', raising=False)
monkeypatch.delenv('GITHUB_ACTIONS', raising=False)
monkeypatch.delenv('GITLAB_CI', raising=False)
monkeypatch.delenv('CIRCLECI', raising=False)
monkeypatch.delenv('CIBW_PLATFORM', raising=False)
with pytest.raises(SystemExit) as exit: