Compare commits

...
42 Commits
Author SHA1 Message Date
Joe Rickerby 0b6307072a Bump version: v2.5.0 2022-04-29 14:46:08 +01:00
Joe Rickerby 61bcac854e Merge pull request #1091 from mayeut/abi3
feature: add support for ABI3 wheels
2022-04-29 14:31:27 +01:00
Joe Rickerby 75998410e0 Add tips+tricks entry for ABI3 building 2022-04-29 14:16:00 +01:00
Joe Rickerby 46702f581d Space out the log statements a little 2022-04-29 13:32:03 +01:00
Joe Rickerby acc079675b Merge remote-tracking branch 'origin/main' into abi3 2022-04-29 11:57:20 +01:00
Joe Rickerby f324c9ad61 Merge pull request #1096 from henryiii/henryiii/feat/sdist
feat: SDist builds
2022-04-29 11:52:08 +01:00
Henry Schreiner de44c88c75 docs: add some projects (#1097)
* docs: add some projects

* chore: update docs
2022-04-28 19:18:49 -04:00
Henry Schreiner 35054666bb refactor: review comments 2022-04-27 17:18:01 -04:00
Henry Schreiner b1e8549bb1 fix: minor cleanup 2022-04-27 14:55:30 -04:00
Henry Schreiner 958a7c32c1 refactor: use single entry for SDist builds
Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>
2022-04-27 09:37:17 -04:00
Joe Rickerby 91fae8268e Add prog arguments to ArgumentParser to prevent the wrong inferred name
when calling like 'python -m cibuildwheel', we get errors like

usage: __main__.py [-h] [--platform {auto,linux,macos,windows}] [--archs ARCHS] [--output-dir OUTPUT_DIR] [--config-file CONFIG_FILE]
                   [--print-build-identifiers] [--allow-empty] [--prerelease-pythons]
                   [package_dir]
__main__.py: error: unrecognized arguments: --sad

With this change, we get error outputs like:

usage: cibuildwheel [-h] [--platform {auto,linux,macos,windows}] [--archs ARCHS] [--output-dir OUTPUT_DIR] [--config-file CONFIG_FILE]
                    [--print-build-identifiers] [--allow-empty] [--prerelease-pythons]
                    [package_dir]
cibuildwheel: error: unrecognized arguments: --asda
2022-04-27 01:01:31 -04:00
Joe Rickerby 8c77d5ed41 Tidy ups, bug fixes 2022-04-27 01:01:31 -04:00
Joe Rickerby 898dd62022 Add test for argument passthrough 2022-04-27 01:01:31 -04:00
Joe Rickerby c6c5e6e59b Add test for cibuildwheel.from-sdist 2022-04-27 01:01:31 -04:00
Joe Rickerby e887d4bbf8 Add entrypoint 2022-04-27 01:01:31 -04:00
Joe Rickerby 763cd15ae2 Add from_sdist script 2022-04-27 01:01:31 -04:00
mayeut e3ff027131 feature: add support for ABI3 wheels 2022-04-26 22:38:17 +02:00
Matthieu Darbois de07370930 fix: extract project as current user on linux (#1095)
This allows git to work properly, e.g., `versioneer`/`setuptools_scm` with latest git versions.
c.f. https://github.com/pypa/manylinux/issues/1309
2022-04-26 13:29:00 -04:00
Henry Schreiner 986a50f8a0 docs: two minor additions (#1093)
* docs: mention when msvcd140_1.dll is included in cpython

* docs: mention maturin-action
2022-04-26 00:29:32 -04:00
Joe Rickerby dff69251ee Merge pull request #1086 from pauldmccarthy/bf/allow-empty
fix: Don't error if no new wheels were built
2022-04-22 10:47:56 +01:00
Paul McCarthy f08f08c04d style: spurious comma 2022-04-21 10:34:11 +01:00
pre-commit-ci[bot]andpre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> 496ea9bd56 [pre-commit.ci] pre-commit autoupdate (#1092)
updates:
- [github.com/hadialqattan/pycln: v1.2.5 → v1.3.1](https://github.com/hadialqattan/pycln/compare/v1.2.5...v1.3.1)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2022-04-19 13:35:44 -04:00
Paul McCarthy abedb68783 test: build_frontend_env fixture not required for --allow-empy test. Small
style tweak
2022-04-19 16:02:23 +01:00
Paul McCarthy baf3ead650 style: exit early to reduce indentation 2022-04-19 16:00:12 +01:00
pre-commit-ci[bot] 30627ae04f [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
2022-04-19 15:52:06 +01:00
Paul McCarthy 945d4f6635 test: don't modify build_frontend_env, as it appears to be global 2022-04-19 15:52:06 +01:00
pre-commit-ci[bot] d061fc7967 [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
2022-04-19 15:52:06 +01:00
Paul McCarthy be9a635f9b fix: don't assume that any configurations are active 2022-04-19 15:52:06 +01:00
Paul McCarthy bb2d5bdab6 TEST: Actually evaluate test outcome 2022-04-19 15:52:06 +01:00
pre-commit-ci[bot] 82c3d4a4b7 [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
2022-04-19 15:52:06 +01:00
Paul McCarthy 1f52f30fcf TEST: Sanity check test for --allow-empty flag 2022-04-19 15:52:06 +01:00
Paul McCarthy 1e176a021b RF: Remove unnecessary message 2022-04-19 15:52:06 +01:00
pre-commit-ci[bot] 07013d6baf [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
2022-04-19 15:52:06 +01:00
Paul McCarthy fe97589390 fix: Don't error if no new wheels were built (this may happen if --allow-empty is active) 2022-04-19 15:52:06 +01:00
Shantanuandhauntsaninja <> 6d4431306e chore: use tomllib on Python 3.11 (#1047)
* Use tomllib on Python 3.11

* delint

Co-authored-by: hauntsaninja <>
2022-04-16 00:00:57 -04:00
pre-commit-ci[bot]pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>Henry Schreiner
9ae6ae2756 [pre-commit.ci] pre-commit autoupdate (#1084)
* [pre-commit.ci] pre-commit autoupdate

updates:
- [github.com/pre-commit/pre-commit-hooks: v4.1.0 → v4.2.0](https://github.com/pre-commit/pre-commit-hooks/compare/v4.1.0...v4.2.0)
- [github.com/asottile/pyupgrade: v2.31.1 → v2.32.0](https://github.com/asottile/pyupgrade/compare/v2.31.1...v2.32.0)

* chore: fix minor style msg

Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>

* chore: use extend on flake8

Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Henry Schreiner <henryschreineriii@gmail.com>
2022-04-13 15:33:49 -04:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 00ba73bf21 chore(deps): bump actions/upload-artifact from 2 to 3 (#1082)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 2 to 3.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-12 15:15:01 -04:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 75fd65fcf7 chore(deps): bump actions/download-artifact from 2 to 3 (#1081)
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 2 to 3.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-12 15:14:45 -04:00
Joe Rickerby 68b8cd8ee5 Merge pull request #1083 from DiddiLeija/fix-docs-py-block 2022-04-12 20:13:09 +01:00
Diego Ramirez a7271b2750 Fix a badly-formatted Python block in the docs
The whole block is indented, though a code block with Python formatting is there.
2022-04-11 12:45:38 -05:00
cibuildwheel-bot[bot]andmayeut 5824aecc5c Update dependencies (#1073)
Co-authored-by: mayeut <mayeut@users.noreply.github.com>
2022-04-05 00:53:56 -04:00
pre-commit-ci[bot]andpre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> 989f21de16 [pre-commit.ci] pre-commit autoupdate (#1074)
updates:
- [github.com/asottile/setup-cfg-fmt: v1.20.0 → v1.20.1](https://github.com/asottile/setup-cfg-fmt/compare/v1.20.0...v1.20.1)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2022-04-05 00:53:33 -04:00
52 changed files with 1006 additions and 458 deletions
+2 -2
View File
@@ -16,7 +16,7 @@ jobs:
- name: Build SDist and wheel
run: pipx run build
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v3
with:
path: dist/*
@@ -29,7 +29,7 @@ jobs:
if: github.event_name == 'release' && github.event.action == 'published'
steps:
- uses: actions/download-artifact@v2
- uses: actions/download-artifact@v3
with:
name: artifact
path: dist
+1 -1
View File
@@ -61,7 +61,7 @@ jobs:
env:
CIBW_ARCHS_MACOS: x86_64 universal2 arm64
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v3
with:
name: sample_wheels
path: wheelhouse
+4 -4
View File
@@ -1,7 +1,7 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.1.0
rev: v4.2.0
hooks:
- id: check-case-conflict
- id: check-merge-conflict
@@ -14,7 +14,7 @@ repos:
- id: trailing-whitespace
- repo: https://github.com/asottile/pyupgrade
rev: v2.31.1
rev: v2.32.0
hooks:
- id: pyupgrade
name: PyUpgrade 3.6+
@@ -27,7 +27,7 @@ repos:
# Autoremoves unused imports
- repo: https://github.com/hadialqattan/pycln
rev: v1.2.5
rev: v1.3.1
hooks:
- id: pycln
args: [--all]
@@ -44,7 +44,7 @@ repos:
- id: black
- repo: https://github.com/asottile/setup-cfg-fmt
rev: v1.20.0
rev: v1.20.1
hooks:
- id: setup-cfg-fmt
+22 -19
View File
@@ -87,7 +87,7 @@ jobs:
- uses: actions/setup-python@v2
- name: Install cibuildwheel
run: python -m pip install cibuildwheel==2.4.0
run: python -m pip install cibuildwheel==2.5.0
- name: Build wheels
run: python -m cibuildwheel --output-dir wheelhouse
@@ -142,25 +142,25 @@ Here are some repos that use cibuildwheel.
|-----------------------------------|----|----|:------|
| [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. |
| [Tornado][] | ![travisci icon][] | ![apple icon][] ![linux icon][] | Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed. |
| [NumPy][] | ![github icon][] ![travisci icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | The fundamental package for scientific computing with Python. |
| [pytorch-fairseq][] | ![github icon][] | ![apple icon][] ![linux icon][] | Facebook AI Research Sequence-to-Sequence Toolkit written in Python. |
| [Matplotlib][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | The venerable Matplotlib, a Python library with C++ portions |
| [MyPy][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | MyPyC, the compiled component of MyPy. |
| [Kivy][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Open source UI framework written in Python, running on Windows, Linux, macOS, Android and iOS |
| [NCNN][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | ncnn is a high-performance neural network inference framework optimized for the mobile platform |
| [Prophet][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Tool for producing high quality forecasts for time series data that has multiple seasonality with linear or non-linear growth. |
| [MyPy][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | The compiled version of MyPy using MyPyC. |
| [pydantic][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Data parsing and validation using Python type hints |
| [uvloop][] | ![github icon][] | ![apple icon][] ![linux icon][] | Ultra fast asyncio event loop. |
| [psutil][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Cross-platform lib for process and system monitoring in Python |
| [vaex][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Out-of-Core hybrid Apache Arrow/NumPy DataFrame for Python, ML, visualization and exploration of big tabular data at a billion rows per second 🚀 |
| [Google Benchmark][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | A microbenchmark support library |
[scikit-learn]: https://github.com/scikit-learn/scikit-learn
[Tornado]: https://github.com/tornadoweb/tornado
[NumPy]: https://github.com/numpy/numpy
[pytorch-fairseq]: https://github.com/pytorch/fairseq
[Matplotlib]: https://github.com/matplotlib/matplotlib
[Kivy]: https://github.com/kivy/kivy
[NCNN]: https://github.com/Tencent/ncnn
[Prophet]: https://github.com/facebook/prophet
[MyPy]: https://github.com/mypyc/mypy_mypyc-wheels
[pydantic]: https://github.com/samuelcolvin/pydantic
[uvloop]: https://github.com/MagicStack/uvloop
[psutil]: https://github.com/giampaolo/psutil
[vaex]: https://github.com/vaexio/vaex
[Google Benchmark]: https://github.com/google/benchmark
[appveyor icon]: docs/data/readme_icons/appveyor.svg
[github icon]: docs/data/readme_icons/github.svg
@@ -192,6 +192,16 @@ Changelog
<!-- this section was generated by bin/update_readme_changelog.py -- do not edit manually -->
### v2.5.0
_29 April 2022_
- ✨ Added support for building ABI3 wheels. cibuildwheel will now recognise when an ABI3 wheel was produced, and skip subsequent build steps where the previously built wheel is compatible. Tests still will run on all selected versions of Python, using the ABI3 wheel. (#1091)
- ✨ You can now build wheels directly from sdist archives, in addition to source directories. Just call cibuildwheel with an sdist argument on the command line, like `cibuildwheel mypackage-1.0.0.tar.gz` (#1096)
- 🐛 Fix a bug where cibuildwheel would crash when no builds are selected and `--allow-empty` is passed (#1086)
- 🐛 Workaround a permissions issue on Linux relating to newer versions of git and setuptools_scm (#1095)
- 📚 Minor docs improvements
### v2.4.0
_2 April 2022_
@@ -231,13 +241,6 @@ _26 October 2021_
- 🐛 Fix bug in the GitHub Action step causing a syntax error (#895)
### v2.2.1
_26 October 2021_
- 🛠 Added a `config-file` option on the GitHub Action to specify something other than pyproject.toml in your GitHub Workflow file. (#883)
- 🐛 Fix missing resources in sdist and released wheel on PyPI. We've also made some internal changes to our release processes to make them more reliable. (#893, #894)
<!-- END bin/update_readme_changelog.py -->
---
@@ -283,6 +286,6 @@ Massive props also to-
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.
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.
If you are building Rust wheels, you can get by without some of the tricks required to make GLIBC work via manylinux; this is especially relevant for cross-compiling, which is easy with Rust. See [maturin-action](https://github.com/messense/maturin-action) for a tool that is optimized for building Rust wheels and cross-compiling.
+8 -2
View File
@@ -5,13 +5,19 @@ from __future__ import annotations
import copy
import difflib
import logging
import sys
from pathlib import Path
from typing import Any, Union
import click
import requests
import rich
import tomli
if sys.version_info >= (3, 11):
import tomllib
else:
import tomli as tomllib
from packaging.specifiers import Specifier
from packaging.version import Version
from rich.logging import RichHandler
@@ -296,7 +302,7 @@ def update_pythons(force: bool, level: str) -> None:
original_toml = toml_file_path.read_text()
with toml_file_path.open("rb") as f:
configs = tomli.load(f)
configs = tomllib.load(f)
for config in configs["windows"]["python_configurations"]:
all_versions.update_config(config)
+8 -2
View File
@@ -5,12 +5,18 @@ from __future__ import annotations
import difflib
import logging
import subprocess
import sys
from pathlib import Path
from typing import NamedTuple
import click
import rich
import tomli
if sys.version_info >= (3, 11):
import tomllib
else:
import tomli as tomllib
from packaging.version import InvalidVersion, Version
from rich.logging import RichHandler
from rich.syntax import Syntax
@@ -78,7 +84,7 @@ def update_virtualenv(force: bool, level: str) -> None:
original_toml = toml_file_path.read_text()
with toml_file_path.open("rb") as f:
loaded_file = tomli.load(f)
loaded_file = tomllib.load(f)
version = str(loaded_file["version"])
versions = git_ls_remote_versions(GET_VIRTUALENV_GITHUB)
if versions[0].version > Version(version):
+1 -1
View File
@@ -1 +1 @@
__version__ = "2.4.0"
__version__ = "2.5.0"
+50 -9
View File
@@ -2,6 +2,8 @@ import argparse
import os
import shutil
import sys
import tarfile
import tempfile
import textwrap
from pathlib import Path
from tempfile import mkdtemp
@@ -20,13 +22,12 @@ from cibuildwheel.util import (
CIBW_CACHE_PATH,
BuildSelector,
Unbuffered,
chdir,
detect_ci_provider,
)
def main() -> None:
platform: PlatformName
parser = argparse.ArgumentParser(
description="Build wheels for all the platforms.",
epilog="""
@@ -65,6 +66,8 @@ def main() -> None:
parser.add_argument(
"--output-dir",
type=Path,
default=Path(os.environ.get("CIBW_OUTPUT_DIR", "wheelhouse")),
help="Destination folder for the wheels. Default: wheelhouse.",
)
@@ -72,20 +75,26 @@ def main() -> None:
"--config-file",
default="",
help="""
TOML config file. Default: "", meaning {package}/pyproject.toml,
if it exists.
TOML config file. Default: "", meaning {package}/pyproject.toml, if
it exists. To refer to a project inside your project, use {package};
this matters if you build from an SDist.
""",
)
parser.add_argument(
"package_dir",
default=".",
metavar="PACKAGE",
default=Path("."),
type=Path,
nargs="?",
help="""
Path to the package that you want wheels for. Must be a subdirectory of
the working directory. When set, the working directory is still
considered the 'project' and is copied into the Docker container on
Linux. Default: the working directory.
Path to the package that you want wheels for. Default: the working
directory. Can be a directory inside the working directory, or an
sdist. When set to a directory, the working directory is still
considered the 'project' and is copied into the Docker container
on Linux. When set to a tar.gz sdist file, --config-file
and --output-dir are relative to the current directory, and other
paths are relative to the expanded SDist directory.
""",
)
@@ -109,6 +118,38 @@ def main() -> None:
args = parser.parse_args(namespace=CommandLineArguments())
args.package_dir = args.package_dir.resolve()
# This are always relative to the base directory, even in SDist builds
args.output_dir = args.output_dir.resolve()
# Standard builds if a directory or non-existent path is given
if not args.package_dir.is_file() and not args.package_dir.name.endswith("tar.gz"):
build_in_directory(args)
return
# Tarfile builds require extraction and changing the directory
with tempfile.TemporaryDirectory(prefix="cibw-sdist-") as temp_dir_str:
temp_dir = Path(temp_dir_str)
with tarfile.open(args.package_dir) as tar:
tar.extractall(path=temp_dir)
# The extract directory is now the project dir
try:
(project_dir,) = temp_dir.iterdir()
except ValueError:
raise SystemExit("invalid sdist: didn't contain a single dir") from None
# This is now the new package dir
args.package_dir = project_dir.resolve()
with chdir(temp_dir):
build_in_directory(args)
def build_in_directory(args: CommandLineArguments) -> None:
platform: PlatformName
if args.platform != "auto":
platform = args.platform
else:
+1 -1
View File
@@ -122,7 +122,7 @@ class DockerContainer:
if from_path.is_dir():
self.call(["mkdir", "-p", to_path])
subprocess.run(
f"tar cf - . | docker exec -i {self.name} tar -xC {shell_quote(to_path)} -f -",
f"tar cf - . | docker exec -i {self.name} tar --no-same-owner -xC {shell_quote(to_path)} -f -",
shell=True,
check=True,
cwd=from_path,
-1
View File
@@ -51,7 +51,6 @@ class EnvironmentAssignment(Protocol):
executor: Optional[bashlex_eval.EnvironmentExecutor] = None,
) -> str:
"""Returns the value of this assignment, as evaluated in the environment"""
...
class EnvironmentAssignmentRaw:
+79 -63
View File
@@ -12,6 +12,7 @@ from .typing import OrderedDict, PathOrStr, assert_never
from .util import (
BuildSelector,
NonPlatformWheelError,
find_compatible_abi3_wheel,
get_build_verbosity_extra_flags,
prepare_command,
read_python_configs,
@@ -132,6 +133,8 @@ def build_on_docker(
)
docker.call(["sh", "-c", before_all_prepared], env=env)
built_wheels: List[PurePath] = []
for config in platform_configs:
log.build_start(config.identifier)
build_options = options.build_options(config.identifier)
@@ -174,74 +177,83 @@ def build_on_docker(
)
sys.exit(1)
if build_options.before_build:
log.step("Running before_build...")
before_build_prepared = prepare_command(
build_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])
docker.call(["mkdir", "-p", built_wheel_dir])
verbosity_flags = get_build_verbosity_extra_flags(build_options.build_verbosity)
if build_options.build_frontend == "pip":
docker.call(
[
"python",
"-m",
"pip",
"wheel",
container_package_dir,
f"--wheel-dir={built_wheel_dir}",
"--no-deps",
*verbosity_flags,
],
env=env,
)
elif build_options.build_frontend == "build":
config_setting = " ".join(verbosity_flags)
docker.call(
[
"python",
"-m",
"build",
container_package_dir,
"--wheel",
f"--outdir={built_wheel_dir}",
f"--config-setting={config_setting}",
],
env=env,
abi3_wheel = find_compatible_abi3_wheel(built_wheels, config.identifier)
if abi3_wheel:
log.step_end()
print(
f"\nFound previously built wheel {abi3_wheel.name}, that's compatible with {config.identifier}. Skipping build step..."
)
repaired_wheels = [abi3_wheel]
else:
assert_never(build_options.build_frontend)
built_wheel = docker.glob(built_wheel_dir, "*.whl")[0]
if build_options.before_build:
log.step("Running before_build...")
before_build_prepared = prepare_command(
build_options.before_build,
project=container_project_path,
package=container_package_dir,
)
docker.call(["sh", "-c", before_build_prepared], env=env)
repaired_wheel_dir = temp_dir / "repaired_wheel"
docker.call(["rm", "-rf", repaired_wheel_dir])
docker.call(["mkdir", "-p", repaired_wheel_dir])
log.step("Building wheel...")
if built_wheel.name.endswith("none-any.whl"):
raise NonPlatformWheelError()
temp_dir = PurePath("/tmp/cibuildwheel")
built_wheel_dir = temp_dir / "built_wheel"
docker.call(["rm", "-rf", built_wheel_dir])
docker.call(["mkdir", "-p", built_wheel_dir])
if build_options.repair_command:
log.step("Repairing wheel...")
repair_command_prepared = prepare_command(
build_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])
verbosity_flags = get_build_verbosity_extra_flags(build_options.build_verbosity)
repaired_wheels = docker.glob(repaired_wheel_dir, "*.whl")
if build_options.build_frontend == "pip":
docker.call(
[
"python",
"-m",
"pip",
"wheel",
container_package_dir,
f"--wheel-dir={built_wheel_dir}",
"--no-deps",
*verbosity_flags,
],
env=env,
)
elif build_options.build_frontend == "build":
config_setting = " ".join(verbosity_flags)
docker.call(
[
"python",
"-m",
"build",
container_package_dir,
"--wheel",
f"--outdir={built_wheel_dir}",
f"--config-setting={config_setting}",
],
env=env,
)
else:
assert_never(build_options.build_frontend)
built_wheel = docker.glob(built_wheel_dir, "*.whl")[0]
repaired_wheel_dir = temp_dir / "repaired_wheel"
docker.call(["rm", "-rf", repaired_wheel_dir])
docker.call(["mkdir", "-p", repaired_wheel_dir])
if built_wheel.name.endswith("none-any.whl"):
raise NonPlatformWheelError()
if build_options.repair_command:
log.step("Repairing wheel...")
repair_command_prepared = prepare_command(
build_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 build_options.test_command and build_options.test_selector(config.identifier):
log.step("Testing wheel...")
@@ -292,8 +304,12 @@ def build_on_docker(
docker.call(["rm", "-rf", venv_dir])
# move repaired wheels to output
docker.call(["mkdir", "-p", container_output_dir])
docker.call(["mv", *repaired_wheels, container_output_dir])
if abi3_wheel is None:
docker.call(["mkdir", "-p", container_output_dir])
docker.call(["mv", *repaired_wheels, container_output_dir])
built_wheels.extend(
container_output_dir / repaired_wheel.name for repaired_wheel in repaired_wheels
)
log.build_end()
+88 -70
View File
@@ -23,6 +23,7 @@ from .util import (
call,
detect_ci_provider,
download,
find_compatible_abi3_wheel,
get_build_verbosity_extra_flags,
get_pip_version,
install_certifi_script,
@@ -275,6 +276,9 @@ def build(options: Options, tmp_path: Path) -> None:
options.globals.build_selector, options.globals.architectures
)
if len(python_configurations) == 0:
return
try:
before_all_options_identifier = python_configurations[0].identifier
before_all_options = options.build_options(before_all_options_identifier)
@@ -288,6 +292,8 @@ def build(options: Options, tmp_path: Path) -> None:
)
shell(before_all_prepared, env=env)
built_wheels: List[Path] = []
for config in python_configurations:
build_options = options.build_options(config.identifier)
log.build_start(config.identifier)
@@ -315,84 +321,94 @@ def build(options: Options, tmp_path: Path) -> None:
build_options.build_frontend,
)
if build_options.before_build:
log.step("Running before_build...")
before_build_prepared = prepare_command(
build_options.before_build, project=".", package=build_options.package_dir
abi3_wheel = find_compatible_abi3_wheel(built_wheels, config.identifier)
if abi3_wheel:
log.step_end()
print(
f"\nFound previously built wheel {abi3_wheel.name}, that's compatible with {config.identifier}. Skipping build step..."
)
shell(before_build_prepared, env=env)
log.step("Building wheel...")
built_wheel_dir.mkdir()
verbosity_flags = get_build_verbosity_extra_flags(build_options.build_verbosity)
if build_options.build_frontend == "pip":
# Path.resolve() is needed. Without it pip wheel may try to fetch package from pypi.org
# see https://github.com/pypa/cibuildwheel/pull/369
call(
"python",
"-m",
"pip",
"wheel",
build_options.package_dir.resolve(),
f"--wheel-dir={built_wheel_dir}",
"--no-deps",
*verbosity_flags,
env=env,
)
elif build_options.build_frontend == "build":
config_setting = " ".join(verbosity_flags)
build_env = env.copy()
if build_options.dependency_constraints:
constraint_path = build_options.dependency_constraints.get_for_python_version(
config.version
repaired_wheel = abi3_wheel
else:
if build_options.before_build:
log.step("Running before_build...")
before_build_prepared = prepare_command(
build_options.before_build, project=".", package=build_options.package_dir
)
build_env["PIP_CONSTRAINT"] = constraint_path.as_uri()
build_env["VIRTUALENV_PIP"] = get_pip_version(env)
call(
"python",
"-m",
"build",
build_options.package_dir,
"--wheel",
f"--outdir={built_wheel_dir}",
f"--config-setting={config_setting}",
env=build_env,
)
else:
assert_never(build_options.build_frontend)
shell(before_build_prepared, env=env)
built_wheel = next(built_wheel_dir.glob("*.whl"))
log.step("Building wheel...")
built_wheel_dir.mkdir()
repaired_wheel_dir.mkdir()
verbosity_flags = get_build_verbosity_extra_flags(build_options.build_verbosity)
if built_wheel.name.endswith("none-any.whl"):
raise NonPlatformWheelError()
if build_options.repair_command:
log.step("Repairing wheel...")
if config_is_universal2:
delocate_archs = "x86_64,arm64"
elif config_is_arm64:
delocate_archs = "arm64"
if build_options.build_frontend == "pip":
# Path.resolve() is needed. Without it pip wheel may try to fetch package from pypi.org
# see https://github.com/pypa/cibuildwheel/pull/369
call(
"python",
"-m",
"pip",
"wheel",
build_options.package_dir.resolve(),
f"--wheel-dir={built_wheel_dir}",
"--no-deps",
*verbosity_flags,
env=env,
)
elif build_options.build_frontend == "build":
config_setting = " ".join(verbosity_flags)
build_env = env.copy()
if build_options.dependency_constraints:
constraint_path = (
build_options.dependency_constraints.get_for_python_version(
config.version
)
)
build_env["PIP_CONSTRAINT"] = constraint_path.as_uri()
build_env["VIRTUALENV_PIP"] = get_pip_version(env)
call(
"python",
"-m",
"build",
build_options.package_dir,
"--wheel",
f"--outdir={built_wheel_dir}",
f"--config-setting={config_setting}",
env=build_env,
)
else:
delocate_archs = "x86_64"
assert_never(build_options.build_frontend)
repair_command_prepared = prepare_command(
build_options.repair_command,
wheel=built_wheel,
dest_dir=repaired_wheel_dir,
delocate_archs=delocate_archs,
)
shell(repair_command_prepared, env=env)
else:
shutil.move(str(built_wheel), repaired_wheel_dir)
built_wheel = next(built_wheel_dir.glob("*.whl"))
repaired_wheel = next(repaired_wheel_dir.glob("*.whl"))
repaired_wheel_dir.mkdir()
log.step_end()
if built_wheel.name.endswith("none-any.whl"):
raise NonPlatformWheelError()
if build_options.repair_command:
log.step("Repairing wheel...")
if config_is_universal2:
delocate_archs = "x86_64,arm64"
elif config_is_arm64:
delocate_archs = "arm64"
else:
delocate_archs = "x86_64"
repair_command_prepared = prepare_command(
build_options.repair_command,
wheel=built_wheel,
dest_dir=repaired_wheel_dir,
delocate_archs=delocate_archs,
)
shell(repair_command_prepared, env=env)
else:
shutil.move(str(built_wheel), repaired_wheel_dir)
repaired_wheel = next(repaired_wheel_dir.glob("*.whl"))
log.step_end()
if build_options.test_command and build_options.test_selector(config.identifier):
machine_arch = platform.machine()
@@ -518,7 +534,9 @@ def build(options: Options, tmp_path: Path) -> None:
)
# we're all done here; move it to output (overwrite existing)
shutil.move(str(repaired_wheel), build_options.output_dir)
if abi3_wheel is None:
shutil.move(str(repaired_wheel), build_options.output_dir)
built_wheels.append(build_options.output_dir / repaired_wheel.name)
# clean up
shutil.rmtree(identifier_tmp_dir)
+14 -13
View File
@@ -8,7 +8,7 @@ from pathlib import Path
from typing import (
Any,
Dict,
Iterator,
Generator,
List,
Mapping,
NamedTuple,
@@ -18,7 +18,11 @@ from typing import (
Union,
)
import tomli
if sys.version_info >= (3, 11):
import tomllib
else:
import tomli as tomllib
from packaging.specifiers import SpecifierSet
from .architecture import Architecture
@@ -33,6 +37,7 @@ from .util import (
DependencyConstraints,
TestSelector,
cached_property,
format_safe,
resources_dir,
selector_matches,
strtobool,
@@ -43,9 +48,9 @@ from .util import (
class CommandLineArguments:
platform: Literal["auto", "linux", "macos", "windows"]
archs: Optional[str]
output_dir: Optional[str]
output_dir: Path
config_file: str
package_dir: str
package_dir: Path
print_build_identifiers: bool
allow_empty: bool
prerelease_pythons: bool
@@ -244,7 +249,7 @@ class OptionsReader:
Load a toml file, returns global and platform as separate dicts.
"""
with filename.open("rb") as f:
config = tomli.load(f)
config = tomllib.load(f)
global_options = config.get("tool", {}).get("cibuildwheel", {})
platform_options = global_options.get(self.platform, {})
@@ -260,7 +265,7 @@ class OptionsReader:
]
@contextmanager
def identifier(self, identifier: Optional[str]) -> Iterator[None]:
def identifier(self, identifier: Optional[str]) -> Generator[None, None, None]:
self.current_identifier = identifier
try:
yield
@@ -341,7 +346,7 @@ class Options:
args = self.command_line_arguments
if args.config_file:
return Path(args.config_file.format(package=args.package_dir))
return Path(format_safe(args.config_file, package=args.package_dir))
# return pyproject.toml, if it's available
pyproject_toml_path = Path(args.package_dir) / "pyproject.toml"
@@ -358,12 +363,8 @@ class Options:
@property
def globals(self) -> GlobalOptions:
args = self.command_line_arguments
package_dir = Path(args.package_dir)
output_dir = Path(
args.output_dir
if args.output_dir is not None
else os.environ.get("CIBW_OUTPUT_DIR", "wheelhouse")
)
package_dir = args.package_dir
output_dir = args.output_dir
build_config = self.reader.get("build", env_plat=False, sep=" ") or "*"
skip_config = self.reader.get("skip", env_plat=False, sep=" ")
+5 -2
View File
@@ -4,7 +4,10 @@ from configparser import ConfigParser
from pathlib import Path
from typing import Any, Optional
import tomli
if sys.version_info >= (3, 11):
import tomllib
else:
import tomli as tomllib
if sys.version_info < (3, 8):
Constant = ast.Str
@@ -56,7 +59,7 @@ def get_requires_python_str(package_dir: Path) -> Optional[str]:
# Read in from pyproject.toml:project.requires-python
try:
with (package_dir / "pyproject.toml").open("rb") as f1:
info = tomli.load(f1)
info = tomllib.load(f1)
return str(info["project"]["requires-python"])
except (FileNotFoundError, KeyError, IndexError, TypeError):
pass
@@ -26,5 +26,5 @@ wheel==0.37.1
# The following packages are considered to be unsafe in a requirements file:
pip==22.0.4
# via -r cibuildwheel/resources/constraints.in
setuptools==61.3.0
setuptools==61.3.1
# via -r cibuildwheel/resources/constraints.in
@@ -26,11 +26,11 @@ wheel==0.37.1
# via
# -r cibuildwheel/resources/constraints.in
# delocate
zipp==3.7.0
zipp==3.8.0
# via importlib-metadata
# The following packages are considered to be unsafe in a requirements file:
pip==22.0.4
# via -r cibuildwheel/resources/constraints.in
setuptools==61.3.0
setuptools==61.3.1
# via -r cibuildwheel/resources/constraints.in
@@ -26,5 +26,5 @@ wheel==0.37.1
# The following packages are considered to be unsafe in a requirements file:
pip==22.0.4
# via -r cibuildwheel/resources/constraints.in
setuptools==61.3.0
setuptools==61.3.1
# via -r cibuildwheel/resources/constraints.in
@@ -26,5 +26,5 @@ wheel==0.37.1
# The following packages are considered to be unsafe in a requirements file:
pip==22.0.4
# via -r cibuildwheel/resources/constraints.in
setuptools==61.3.0
setuptools==61.3.1
# via -r cibuildwheel/resources/constraints.in
+1 -1
View File
@@ -26,5 +26,5 @@ wheel==0.37.1
# The following packages are considered to be unsafe in a requirements file:
pip==22.0.4
# via -r cibuildwheel/resources/constraints.in
setuptools==61.3.0
setuptools==61.3.1
# via -r cibuildwheel/resources/constraints.in
+27 -27
View File
@@ -1,43 +1,43 @@
[x86_64]
manylinux1 = quay.io/pypa/manylinux1_x86_64:2022-03-31-9afae1d
manylinux2010 = quay.io/pypa/manylinux2010_x86_64:2022-03-31-361e6b6
manylinux2014 = quay.io/pypa/manylinux2014_x86_64:2022-03-31-361e6b6
manylinux_2_24 = quay.io/pypa/manylinux_2_24_x86_64:2022-03-31-361e6b6
musllinux_1_1 = quay.io/pypa/musllinux_1_1_x86_64:2022-03-31-361e6b6
manylinux1 = quay.io/pypa/manylinux1_x86_64:2022-04-03-9524524
manylinux2010 = quay.io/pypa/manylinux2010_x86_64:2022-04-03-da6ecb3
manylinux2014 = quay.io/pypa/manylinux2014_x86_64:2022-04-03-da6ecb3
manylinux_2_24 = quay.io/pypa/manylinux_2_24_x86_64:2022-04-03-da6ecb3
musllinux_1_1 = quay.io/pypa/musllinux_1_1_x86_64:2022-04-03-da6ecb3
[i686]
manylinux1 = quay.io/pypa/manylinux1_i686:2022-03-31-9afae1d
manylinux2010 = quay.io/pypa/manylinux2010_i686:2022-03-31-361e6b6
manylinux2014 = quay.io/pypa/manylinux2014_i686:2022-03-31-361e6b6
manylinux_2_24 = quay.io/pypa/manylinux_2_24_i686:2022-03-31-361e6b6
musllinux_1_1 = quay.io/pypa/musllinux_1_1_i686:2022-03-31-361e6b6
manylinux1 = quay.io/pypa/manylinux1_i686:2022-04-03-9524524
manylinux2010 = quay.io/pypa/manylinux2010_i686:2022-04-03-da6ecb3
manylinux2014 = quay.io/pypa/manylinux2014_i686:2022-04-03-da6ecb3
manylinux_2_24 = quay.io/pypa/manylinux_2_24_i686:2022-04-03-da6ecb3
musllinux_1_1 = quay.io/pypa/musllinux_1_1_i686:2022-04-03-da6ecb3
[pypy_x86_64]
manylinux2010 = quay.io/pypa/manylinux2010_x86_64:2022-03-31-361e6b6
manylinux2014 = quay.io/pypa/manylinux2014_x86_64:2022-03-31-361e6b6
manylinux_2_24 = quay.io/pypa/manylinux_2_24_x86_64:2022-03-31-361e6b6
manylinux2010 = quay.io/pypa/manylinux2010_x86_64:2022-04-03-da6ecb3
manylinux2014 = quay.io/pypa/manylinux2014_x86_64:2022-04-03-da6ecb3
manylinux_2_24 = quay.io/pypa/manylinux_2_24_x86_64:2022-04-03-da6ecb3
[pypy_i686]
manylinux2010 = quay.io/pypa/manylinux2010_i686:2022-03-31-361e6b6
manylinux2014 = quay.io/pypa/manylinux2014_i686:2022-03-31-361e6b6
manylinux_2_24 = quay.io/pypa/manylinux_2_24_i686:2022-03-31-361e6b6
manylinux2010 = quay.io/pypa/manylinux2010_i686:2022-04-03-da6ecb3
manylinux2014 = quay.io/pypa/manylinux2014_i686:2022-04-03-da6ecb3
manylinux_2_24 = quay.io/pypa/manylinux_2_24_i686:2022-04-03-da6ecb3
[aarch64]
manylinux2014 = quay.io/pypa/manylinux2014_aarch64:2022-03-31-361e6b6
manylinux_2_24 = quay.io/pypa/manylinux_2_24_aarch64:2022-03-31-361e6b6
musllinux_1_1 = quay.io/pypa/musllinux_1_1_aarch64:2022-03-31-361e6b6
manylinux2014 = quay.io/pypa/manylinux2014_aarch64:2022-04-03-da6ecb3
manylinux_2_24 = quay.io/pypa/manylinux_2_24_aarch64:2022-04-03-da6ecb3
musllinux_1_1 = quay.io/pypa/musllinux_1_1_aarch64:2022-04-03-da6ecb3
[ppc64le]
manylinux2014 = quay.io/pypa/manylinux2014_ppc64le:2022-03-31-361e6b6
manylinux_2_24 = quay.io/pypa/manylinux_2_24_ppc64le:2022-03-31-361e6b6
musllinux_1_1 = quay.io/pypa/musllinux_1_1_ppc64le:2022-03-31-361e6b6
manylinux2014 = quay.io/pypa/manylinux2014_ppc64le:2022-04-03-da6ecb3
manylinux_2_24 = quay.io/pypa/manylinux_2_24_ppc64le:2022-04-03-da6ecb3
musllinux_1_1 = quay.io/pypa/musllinux_1_1_ppc64le:2022-04-03-da6ecb3
[s390x]
manylinux2014 = quay.io/pypa/manylinux2014_s390x:2022-03-31-361e6b6
manylinux_2_24 = quay.io/pypa/manylinux_2_24_s390x:2022-03-31-361e6b6
musllinux_1_1 = quay.io/pypa/musllinux_1_1_s390x:2022-03-31-361e6b6
manylinux2014 = quay.io/pypa/manylinux2014_s390x:2022-04-03-da6ecb3
manylinux_2_24 = quay.io/pypa/manylinux_2_24_s390x:2022-04-03-da6ecb3
musllinux_1_1 = quay.io/pypa/musllinux_1_1_s390x:2022-04-03-da6ecb3
[pypy_aarch64]
manylinux2014 = quay.io/pypa/manylinux2014_aarch64:2022-03-31-361e6b6
manylinux_2_24 = quay.io/pypa/manylinux_2_24_aarch64:2022-03-31-361e6b6
manylinux2014 = quay.io/pypa/manylinux2014_aarch64:2022-04-03-da6ecb3
manylinux_2_24 = quay.io/pypa/manylinux_2_24_aarch64:2022-04-03-da6ecb3
+69 -6
View File
@@ -13,29 +13,37 @@ import time
import urllib.request
from enum import Enum
from functools import lru_cache
from pathlib import Path
from pathlib import Path, PurePath
from time import sleep
from typing import (
Any,
ClassVar,
Dict,
Generator,
Iterable,
Iterator,
List,
NamedTuple,
Optional,
Sequence,
TextIO,
TypeVar,
Union,
cast,
overload,
)
import bracex
import certifi
import tomli
if sys.version_info >= (3, 11):
import tomllib
else:
import tomli as tomllib
from filelock import FileLock
from packaging.requirements import InvalidRequirement, Requirement
from packaging.specifiers import SpecifierSet
from packaging.utils import parse_wheel_filename
from packaging.version import Version
from platformdirs import user_cache_path
@@ -46,6 +54,7 @@ __all__ = [
"MANYLINUX_ARCHS",
"call",
"shell",
"find_compatible_abi3_wheel",
"format_safe",
"prepare_command",
"get_build_verbosity_extra_flags",
@@ -53,6 +62,7 @@ __all__ = [
"selector_matches",
"strtobool",
"cached_property",
"chdir",
]
resources_dir: Final = Path(__file__).parent / "resources"
@@ -203,7 +213,7 @@ def get_build_verbosity_extra_flags(level: int) -> List[str]:
def read_python_configs(config: PlatformName) -> List[Dict[str, str]]:
input_file = resources_dir / "build-platforms.toml"
with input_file.open("rb") as f:
loaded_file = tomli.load(f)
loaded_file = tomllib.load(f)
results: List[Dict[str, str]] = list(loaded_file[config]["python_configurations"])
return results
@@ -409,7 +419,7 @@ def unwrap(text: str) -> str:
@contextlib.contextmanager
def print_new_wheels(msg: str, output_dir: Path) -> Iterator[None]:
def print_new_wheels(msg: str, output_dir: Path) -> Generator[None, None, None]:
"""
Prints the new items in a directory upon exiting. The message to display
can include {n} for number of wheels, {s} for total number of seconds,
@@ -430,6 +440,10 @@ def print_new_wheels(msg: str, output_dir: Path) -> Iterator[None]:
FileReport(wheel.name, f"{(wheel.stat().st_size + 1023) // 1024:,d}")
for wheel in final_contents - existing_contents
]
if len(new_contents) == 0:
return
max_name_len = max(len(f.name) for f in new_contents)
max_size_len = max(len(f.size) for f in new_contents)
n = len(new_contents)
@@ -460,7 +474,7 @@ def get_pip_version(env: Dict[str, str]) -> str:
def _ensure_virtualenv() -> Path:
input_file = resources_dir / "virtualenv.toml"
with input_file.open("rb") as f:
loaded_file = tomli.load(f)
loaded_file = tomllib.load(f)
version = str(loaded_file["version"])
url = str(loaded_file["url"])
path = CIBW_CACHE_PATH / f"virtualenv-{version}.pyz"
@@ -557,7 +571,56 @@ def virtualenv(
return env
T = TypeVar("T", bound=PurePath)
def find_compatible_abi3_wheel(wheels: Sequence[T], identifier: str) -> Optional[T]:
"""
Finds an ABI3 wheel in `wheels` compatible with the Python interpreter
specified by `identifier`.
"""
interpreter, platform = identifier.split("-")
if not interpreter.startswith("cp3"):
return None
for wheel in wheels:
_, _, _, tags = parse_wheel_filename(wheel.name)
for tag in tags:
if tag.abi != "abi3":
continue
if not tag.interpreter.startswith("cp3"):
continue
if int(tag.interpreter[3:]) > int(interpreter[3:]):
continue
if platform.startswith(("manylinux", "musllinux", "macosx")):
# Linux, macOS
os_, arch = platform.split("_", 1)
if not tag.platform.startswith(os_):
continue
if not tag.platform.endswith("_" + arch):
continue
else:
# Windows
if not tag.platform == platform:
continue
return wheel
return None
if sys.version_info >= (3, 8):
from functools import cached_property
else:
from .functools_cached_property_38 import cached_property
# Can be replaced by contextlib.chdir in Python 3.11
@contextlib.contextmanager
def chdir(new_path: Union[Path, str]) -> Generator[None, None, None]:
"""Non thread-safe context manager to change the current working directory."""
cwd = os.getcwd()
try:
os.chdir(new_path)
yield
finally:
os.chdir(cwd)
+84 -66
View File
@@ -22,6 +22,7 @@ from .util import (
NonPlatformWheelError,
call,
download,
find_compatible_abi3_wheel,
get_build_verbosity_extra_flags,
get_pip_version,
prepare_command,
@@ -234,6 +235,9 @@ def build(options: Options, tmp_path: Path) -> None:
options.globals.build_selector, options.globals.architectures
)
if len(python_configurations) == 0:
return
try:
before_all_options_identifier = python_configurations[0].identifier
before_all_options = options.build_options(before_all_options_identifier)
@@ -246,6 +250,8 @@ def build(options: Options, tmp_path: Path) -> None:
)
shell(before_all_prepared, env=env)
built_wheels: List[Path] = []
for config in python_configurations:
build_options = options.build_options(config.identifier)
log.build_start(config.identifier)
@@ -271,83 +277,93 @@ def build(options: Options, tmp_path: Path) -> None:
build_options.build_frontend,
)
# run the before_build command
if build_options.before_build:
log.step("Running before_build...")
before_build_prepared = prepare_command(
build_options.before_build, project=".", package=options.globals.package_dir
abi3_wheel = find_compatible_abi3_wheel(built_wheels, config.identifier)
if abi3_wheel:
log.step_end()
print(
f"\nFound previously built wheel {abi3_wheel.name}, that's compatible with {config.identifier}. Skipping build step..."
)
shell(before_build_prepared, env=env)
log.step("Building wheel...")
built_wheel_dir.mkdir()
verbosity_flags = get_build_verbosity_extra_flags(build_options.build_verbosity)
if build_options.build_frontend == "pip":
# Path.resolve() is needed. Without it pip wheel may try to fetch package from pypi.org
# see https://github.com/pypa/cibuildwheel/pull/369
call(
"python",
"-m",
"pip",
"wheel",
options.globals.package_dir.resolve(),
f"--wheel-dir={built_wheel_dir}",
"--no-deps",
*get_build_verbosity_extra_flags(build_options.build_verbosity),
env=env,
)
elif build_options.build_frontend == "build":
config_setting = " ".join(verbosity_flags)
build_env = env.copy()
if build_options.dependency_constraints:
constraints_path = build_options.dependency_constraints.get_for_python_version(
config.version
repaired_wheel = abi3_wheel
else:
# run the before_build command
if build_options.before_build:
log.step("Running before_build...")
before_build_prepared = prepare_command(
build_options.before_build, project=".", package=options.globals.package_dir
)
# Bug in pip <= 21.1.3 - we can't have a space in the
# constraints file, and pip doesn't support drive letters
# in uhi. After probably pip 21.2, we can use uri. For
# now, use a temporary file.
if " " in str(constraints_path):
assert " " not in str(identifier_tmp_dir)
tmp_file = identifier_tmp_dir / "constraints.txt"
tmp_file.write_bytes(constraints_path.read_bytes())
constraints_path = tmp_file
shell(before_build_prepared, env=env)
build_env["PIP_CONSTRAINT"] = str(constraints_path)
build_env["VIRTUALENV_PIP"] = get_pip_version(env)
log.step("Building wheel...")
built_wheel_dir.mkdir()
verbosity_flags = get_build_verbosity_extra_flags(build_options.build_verbosity)
if build_options.build_frontend == "pip":
# Path.resolve() is needed. Without it pip wheel may try to fetch package from pypi.org
# see https://github.com/pypa/cibuildwheel/pull/369
call(
"python",
"-m",
"build",
build_options.package_dir,
"--wheel",
f"--outdir={built_wheel_dir}",
f"--config-setting={config_setting}",
env=build_env,
"pip",
"wheel",
options.globals.package_dir.resolve(),
f"--wheel-dir={built_wheel_dir}",
"--no-deps",
*get_build_verbosity_extra_flags(build_options.build_verbosity),
env=env,
)
else:
assert_never(build_options.build_frontend)
elif build_options.build_frontend == "build":
config_setting = " ".join(verbosity_flags)
build_env = env.copy()
if build_options.dependency_constraints:
constraints_path = (
build_options.dependency_constraints.get_for_python_version(
config.version
)
)
# Bug in pip <= 21.1.3 - we can't have a space in the
# constraints file, and pip doesn't support drive letters
# in uhi. After probably pip 21.2, we can use uri. For
# now, use a temporary file.
if " " in str(constraints_path):
assert " " not in str(identifier_tmp_dir)
tmp_file = identifier_tmp_dir / "constraints.txt"
tmp_file.write_bytes(constraints_path.read_bytes())
constraints_path = tmp_file
built_wheel = next(built_wheel_dir.glob("*.whl"))
build_env["PIP_CONSTRAINT"] = str(constraints_path)
build_env["VIRTUALENV_PIP"] = get_pip_version(env)
call(
"python",
"-m",
"build",
build_options.package_dir,
"--wheel",
f"--outdir={built_wheel_dir}",
f"--config-setting={config_setting}",
env=build_env,
)
else:
assert_never(build_options.build_frontend)
# repair the wheel
repaired_wheel_dir.mkdir()
built_wheel = next(built_wheel_dir.glob("*.whl"))
if built_wheel.name.endswith("none-any.whl"):
raise NonPlatformWheelError()
# repair the wheel
repaired_wheel_dir.mkdir()
if build_options.repair_command:
log.step("Repairing wheel...")
repair_command_prepared = prepare_command(
build_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)
if built_wheel.name.endswith("none-any.whl"):
raise NonPlatformWheelError()
repaired_wheel = next(repaired_wheel_dir.glob("*.whl"))
if build_options.repair_command:
log.step("Repairing wheel...")
repair_command_prepared = prepare_command(
build_options.repair_command, wheel=built_wheel, dest_dir=repaired_wheel_dir
)
shell(repair_command_prepared, env=env)
else:
shutil.move(str(built_wheel), repaired_wheel_dir)
repaired_wheel = next(repaired_wheel_dir.glob("*.whl"))
if build_options.test_command and options.globals.test_selector(config.identifier):
log.step("Testing wheel...")
@@ -402,7 +418,9 @@ def build(options: Options, tmp_path: Path) -> None:
shell(test_command_prepared, cwd="c:\\", env=virtualenv_env)
# we're all done here; move it to output (remove if already exists)
shutil.move(str(repaired_wheel), build_options.output_dir)
if abi3_wheel is None:
shutil.move(str(repaired_wheel), build_options.output_dir)
built_wheels.append(build_options.output_dir / repaired_wheel.name)
# clean up
# (we ignore errors because occasionally Windows fails to unlink a file and we
+10
View File
@@ -2,6 +2,16 @@
title: Changelog
---
### v2.5.0
_29 April 2022_
- ✨ Added support for building ABI3 wheels. cibuildwheel will now recognise when an ABI3 wheel was produced, and skip subsequent build steps where the previously built wheel is compatible. Tests still will run on all selected versions of Python, using the ABI3 wheel. (#1091)
- ✨ You can now build wheels directly from sdist archives, in addition to source directories. Just call cibuildwheel with an sdist argument on the command line, like `cibuildwheel mypackage-1.0.0.tar.gz` (#1096)
- 🐛 Fix a bug where cibuildwheel would crash when no builds are selected and `--allow-empty` is passed (#1086)
- 🐛 Workaround a permissions issue on Linux relating to newer versions of git and setuptools_scm (#1095)
- 📚 Minor docs improvements
### v2.4.0
_2 April 2022_
+1 -1
View File
@@ -14,7 +14,7 @@ The old `manylinux1` image (based on CentOS 5) contains a version of GCC and lib
OS X/macOS allows you to specify a so-called "deployment target" version that will ensure backwards compatibility with older versions of macOS. One way to do this is by setting the `MACOSX_DEPLOYMENT_TARGET` environment variable.
However, to enable modern C++ standards, the deploment target needs to be set high enough (since older OS X/macOS versions did not have the necessary modern C++ standard library).
However, to enable modern C++ standards, the deployment target needs to be set high enough (since older OS X/macOS versions did not have the necessary modern C++ standard library).
To get C++11 and C++14 support, `MACOSX_DEPLOYMENT_TARGET` needs to be set to (at least) `"10.9"`. By default, `cibuildwheel` already does this, building 64-bit-only wheels for macOS 10.9 and later.
+63 -2
View File
@@ -287,7 +287,7 @@
pypi: mypy
ci: [github]
os: [apple, linux, windows]
notes: MyPyC, the compiled component of MyPy.
notes: The compiled version of MyPy using MyPyC.
- name: Imagecodecs (fork)
gh: czaki/imagecodecs_build
@@ -521,10 +521,71 @@
gh: arbor-sim/arbor
ci: [github]
os: [apple, linux]
pypi: arbor
notes: >
Arbor is a multi-compartment neuron simulation library; compatible with
next-generation accelerators; best-practices applied to research software;
focused on community-driven development. Includes a
[small script](https://github.com/arbor-sim/arbor/blob/master/scripts/patchwheel.py)
patching `rpath` in bundled libraries.
- name: Kivy
gh: kivy/kivy
ci: [github]
os: [windows, apple, linux]
- name: NCNN
gh: Tencent/ncnn
ci: [github]
os: [windows, apple, linux]
- name: Prophet
gh: facebook/prophet
ci: [github]
os: [windows, apple, linux]
- name: MemRay
gh: bloomberg/memray
ci: [github]
os: [linux]
- name: PyGame
gh: pygame/pygame
ci: [github]
os: [apple, linux]
- name: UltraJSON
gh: ultrajson/ultrajson
ci: [github]
os: [windows, apple, linux]
- name: NumPy
gh: numpy/numpy
ci: [github, travisci]
os: [windows, apple, linux]
- name: Wrapt
gh: GrahamDumpleton/wrapt
ci: [github]
os: [windows, apple, linux]
- name: SimpleJSON
gh: simplejson/simplejson
ci: [github]
os: [windows, apple, linux]
- name: Implicit
gh: benfred/implicit
ci: [github]
os: [windows, apple, linux]
notes: Includes GPU support for linux wheels
- name: power-grid-model
gh: alliander-opensource/power-grid-model
ci: [github]
os: [windows, apple, linux]
notes: Python/C++ library for distribution power system analysis
- name: Python-WebRTC
gh: MarshalX/python-webrtc
ci: [github]
os: [windows, apple, linux]
+26 -20
View File
@@ -103,6 +103,12 @@ Linux), and the other architectures are emulated automatically.
{% include "../examples/github-with-qemu.yml" %}
```
### Building CPython ABI3 wheels (Limited API) {: #abi3}
The CPython Limited API is a subset of the Python C Extension API that's declared to be forward-compatible, meaning you can compile wheels for one version of Python, and they'll be compatible with future versions. Wheels that use the Limited API are known as ABI3 wheels.
To create a package that builds ABI3 wheels, you'll need to configure your build backend to compile libraries correctly create wheels with the right tags. [Check this repo](https://github.com/joerick/python-abi3-package-sample) for an example of how to do this with setuptools.
### Building packages with optional C extensions
`cibuildwheel` defines the environment variable `CIBUILDWHEEL` to the value `1` allowing projects for which the C extension is optional to make it mandatory when building wheels.
@@ -127,7 +133,7 @@ There are two suggested methods for keeping cibuildwheel up to date that instead
If you use GitHub Actions for builds, you can use cibuildwheel as an action:
```yaml
uses: pypa/cibuildwheel@v2.4.0
uses: pypa/cibuildwheel@v2.5.0
```
This is a composite step that just runs cibuildwheel using pipx. You can set command-line options as `with:` parameters, and use `env:` as normal.
@@ -153,7 +159,7 @@ The second option, and the only one that supports other CI systems, is using a `
```bash
# requirements-cibw.txt
cibuildwheel==2.4.0
cibuildwheel==2.5.0
```
Then your install step would have `python -m pip install -r requirements-cibw.txt` in it. Your `.github/dependabot.yml` file could look like this:
@@ -179,7 +185,7 @@ package 'sdist' will also benefit.
#### Missing build dependencies {: #cibw-options-alternatives-deps}
If your build needs Python dependencies, rather than using CIBW_BEFORE_BUILD, it's best to add these to the
If your build needs Python dependencies, rather than using `CIBW_BEFORE_BUILD`, it's best to add these to the
[`build-system.requires`](https://www.python.org/dev/peps/pep-0518/#build-system-table)
section of your pyproject.toml. For example, if your project requires Cython
to build, your pyproject.toml might include a section like this:
@@ -201,35 +207,35 @@ You might need to run some other commands before building, like running a
script that performs codegen or downloading some data that's not stored in
your source tree.
Rather than using CIBW_BEFORE_ALL or CIBW_BEFORE_BUILD, you could incorporate
Rather than using `CIBW_BEFORE_ALL` or `CIBW_BEFORE_BUILD`, you could incorporate
these steps into your package's build process. For example, if you're using
setuptools, you can add steps to your package's `setup.py` using a structure
like this:
```python
import subprocess
import setuptools
import setuptools.command.build_py
```python
import subprocess
import setuptools
import setuptools.command.build_py
class BuildPyCommand(setuptools.command.build_py.build_py):
"""Custom build command."""
class BuildPyCommand(setuptools.command.build_py.build_py):
"""Custom build command."""
def run(self):
def run(self):
# your custom build steps here
# e.g.
# subprocess.run(['python', 'scripts/my_custom_script.py'], check=True)
setuptools.command.build_py.build_py.run(self)
setuptools.setup(
cmdclass={
'build_py': BuildPyCommand,
},
# Usual setup() args.
# ...
)
```
setuptools.setup(
cmdclass={
'build_py': BuildPyCommand,
},
# Usual setup() args.
# ...
)
```
#### Compiler flags
@@ -309,7 +315,7 @@ See [#816](https://github.com/pypa/cibuildwheel/issues/816), thanks to @phoeriou
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 C extension with a newer compiler.
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/pypa/cibuildwheel/issues/423) for details and references).
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/pypa/cibuildwheel/issues/423) for details and references). CPython 3.8.3 and all versions after it have this extra DLL, so it is only needed for 3.8 and earlier.
To add the `/d2FH4-` flag to a standard `setup.py` using `setuptools`, the `extra_compile_args` option can be used:
+2 -2
View File
@@ -183,7 +183,7 @@ To build Linux, Mac, and Windows wheels using GitHub Actions, create a `.github/
- uses: actions/checkout@v2
- name: Build wheels
run: pipx run cibuildwheel==2.4.0
run: pipx run cibuildwheel==2.5.0
- uses: actions/upload-artifact@v2
with:
@@ -218,7 +218,7 @@ To build Linux, Mac, and Windows wheels using GitHub Actions, create a `.github/
- uses: actions/setup-python@v2
- name: Install cibuildwheel
run: python -m pip install cibuildwheel==2.4.0
run: python -m pip install cibuildwheel==2.5.0
- name: Build wheels
run: python -m cibuildwheel --output-dir wheelhouse
+138 -102
View File
@@ -10,22 +10,29 @@ title: Working examples
|-----------------------------------|----|----|:------|
| [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. |
| [Tornado][] | ![travisci icon][] | ![apple icon][] ![linux icon][] | Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed. |
| [NumPy][] | ![github icon][] ![travisci icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | The fundamental package for scientific computing with Python. |
| [pytorch-fairseq][] | ![github icon][] | ![apple icon][] ![linux icon][] | Facebook AI Research Sequence-to-Sequence Toolkit written in Python. |
| [Matplotlib][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | The venerable Matplotlib, a Python library with C++ portions |
| [MyPy][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | MyPyC, the compiled component of MyPy. |
| [Kivy][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Open source UI framework written in Python, running on Windows, Linux, macOS, Android and iOS |
| [NCNN][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | ncnn is a high-performance neural network inference framework optimized for the mobile platform |
| [Prophet][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Tool for producing high quality forecasts for time series data that has multiple seasonality with linear or non-linear growth. |
| [MyPy][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | The compiled version of MyPy using MyPyC. |
| [pydantic][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Data parsing and validation using Python type hints |
| [uvloop][] | ![github icon][] | ![apple icon][] ![linux icon][] | Ultra fast asyncio event loop. |
| [psutil][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Cross-platform lib for process and system monitoring in Python |
| [MemRay][] | ![github icon][] | ![linux icon][] | Memray is a memory profiler for Python |
| [vaex][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Out-of-Core hybrid Apache Arrow/NumPy DataFrame for Python, ML, visualization and exploration of big tabular data at a billion rows per second 🚀 |
| [Google Benchmark][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | A microbenchmark support library |
| [Apache Beam][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Apache Beam is a unified programming model for Batch and Streaming |
| [Apache Beam][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Apache Beam is a unified programming model for Batch and Streaming data processing. |
| [asyncpg][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | A fast PostgreSQL Database Client Library for Python/asyncio. |
| [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. |
| [cmake][] | ![github icon][] ![travisci icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Multitagged binary builds for all supported platforms, using cibw 2 config configuration. |
| [duckdb][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | DuckDB is an in-process SQL OLAP Database Management System |
| [PyGame][] | ![github icon][] | ![apple icon][] ![linux icon][] | pygame (the library) is a Free and Open Source python programming language library for making multimedia applications like games built on top of the excellent SDL library. C, Python, Native, OpenGL. |
| [cmake][] | ![github icon][] ![travisci icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Multitagged binary builds for all supported platforms, using cibw 2 config configuration. |
| [twisted-iocpsupport][] | ![github icon][] | ![windows icon][] | A submodule of Twisted that hooks into native C APIs using Cython. |
| [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. |
| [cvxpy][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | A Python-embedded modeling language for convex optimization problems. |
| [UltraJSON][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Ultra fast JSON decoder and encoder written in C with Python bindings |
| [PyOxidizer][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | A modern Python application packaging and distribution tool |
| [Triton][] | ![github icon][] | ![linux icon][] | Self hosted runners |
| [River][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | 🌊 Online machine learning in Python |
@@ -33,6 +40,7 @@ title: Working examples
| [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. |
| [vispy][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Main repository for Vispy |
| [Implicit][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Includes GPU support for linux wheels |
| [Confluent client for Kafka][] | ![travisci icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | setup in `tools/wheels/build-wheels.bat` |
| [tinyobjloader][] | ![azurepipelines icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Tiny but powerful single file wavefront obj loader |
| [Dependency Injector][] | ![travisci icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Dependency injection framework for Python, uses Windows TravisCI |
@@ -41,12 +49,14 @@ title: Working examples
| [PyYAML][] | ![github icon][] | ![apple icon][] | Canonical source repository for PyYAML |
| [numexpr][] | ![github icon][] ![travisci icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Fast numerical array expression evaluator for Python, NumPy, PyTables, pandas, bcolz and more |
| [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. |
| [Wrapt][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | A Python module for decorators, wrappers and monkey patching. |
| [PyAV][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Pythonic bindings for FFmpeg's libraries. |
| [SimpleJSON][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | simplejson is a simple, fast, extensible JSON encoder/decoder for Python |
| [OpenColorIO][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | A color management framework for visual effects and animation. |
| [Line Profiler][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Line-by-line profiling for Python |
| [PyTables][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | A Python package to manage extremely large amounts of data |
| [OpenTimelineIO][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Open Source API and interchange format for editorial timeline information. |
| [pikepdf][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | A Python library for reading and writing PDF, powered by qpdf |
| [OpenTimelineIO][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Open Source API and interchange format for editorial timeline information. |
| [ruptures][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Extensive Cython + NumPy [pyproject.toml](https://github.com/deepcharles/ruptures/blob/master/pyproject.toml) example. |
| [aioquic][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | QUIC and HTTP/3 implementation in Python |
| [DeepForest][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | An Efficient, Scalable and Optimized Python Framework for Deep Forest (2021.2.1) |
@@ -55,8 +65,8 @@ title: Working examples
| [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. |
| [AutoPy][] | ![travisci icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Includes a Windows Travis build. |
| [H3-py][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Python bindings for H3, a hierarchical hexagonal geospatial indexing system |
| [markupsafe][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Safely add untrusted strings to HTML/XML markup. |
| [Rtree][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Rtree: spatial index for Python GIS ¶ |
| [markupsafe][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Safely add untrusted strings to HTML/XML markup. |
| [python-rapidjson][] | ![travisci icon][] ![gitlab icon][] ![appveyor icon][] | ![windows icon][] ![linux icon][] | Python wrapper around rapidjson |
| [python-snappy][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Python bindings for the snappy google library |
| [pybind11 cmake_example][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Example pybind11 module built with a CMake-based build system |
@@ -65,10 +75,10 @@ title: Working examples
| [pybind11 python_example][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Example pybind11 module built with a Python-based build system |
| [dd-trace-py][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Uses custom alternate arch emulation on GitHub |
| [cyvcf2][] | ![github icon][] | ![apple icon][] ![linux icon][] | cython + htslib == fast VCF and BCF processing |
| [sourmash][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Quickly search, compare, and analyze genomic and metagenomic data sets. |
| [time-machine][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Time mocking library using only the CPython C API. |
| [abess][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | A fast best-subset selection library. It uses cibuildwheel to build a large project with C++ extensions. |
| [sourmash][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Quickly search, compare, and analyze genomic and metagenomic data sets. |
| [CTranslate2][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Includes libraries from the [Intel oneAPI toolkit](https://www.intel.com/content/www/us/en/developer/tools/oneapi/base-toolkit.html) and CUDA kernels compiled for multiple GPU architectures. |
| [abess][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | A fast best-subset selection library. It uses cibuildwheel to build a large project with C++ extensions. |
| [matrixprofile][] | ![travisci icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | A Python 3 library making time series data mining tasks, utilizing matrix profile algorithms, accessible to everyone. |
| [jq.py][] | ![travisci icon][] | ![apple icon][] ![linux icon][] | Python bindings for jq |
| [iminuit][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Jupyter-friendly Python interface for C++ MINUIT2 |
@@ -78,6 +88,7 @@ title: Working examples
| [boost-histogram][] | ![github icon][] ![travisci icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Supports full range of wheels, including PyPy and alternate archs. |
| [iDynTree][] | ![github icon][] | ![linux icon][] | Uses manylinux_2_24 |
| [TgCrypto][] | ![travisci icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Includes a Windows Travis build. |
| [Python-WebRTC][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | a Python extension that provides bindings to WebRTC M92 |
| [pybase64][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Fast Base64 encoding/decoding in Python |
| [Arbor][] | ![github icon][] | ![apple icon][] ![linux icon][] | Arbor is a multi-compartment neuron simulation library; compatible with next-generation accelerators; best-practices applied to research software; focused on community-driven development. Includes a [small script](https://github.com/arbor-sim/arbor/blob/master/scripts/patchwheel.py) patching `rpath` in bundled libraries. |
| [etebase-py][] | ![travisci icon][] | ![linux icon][] | Python bindings to a Rust library using `setuptools-rust`, and `sccache` for improved speed. |
@@ -85,10 +96,11 @@ title: Working examples
| [Imagecodecs (fork)][] | ![azurepipelines icon][] | ![apple icon][] ![linux icon][] | Over 20 external dependencies in compiled libraries, custom docker image, `libomp`, `openblas` and `install_name_tool` for macOS. |
| [polaroid][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Full range of wheels for setuptools rust, with auto release and PyPI deploy. |
| [numpythia][] | ![github icon][] | ![apple icon][] ![linux icon][] | The interface between PYTHIA and NumPy |
| [pyjet][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | The interface between FastJet and NumPy |
| [clang-format][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Scikit-build wrapper around LLVM's CMake, all platforms, generic wheels. |
| [ninja][] | ![github icon][] ![travisci icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Multitagged binary builds for all supported platforms, using cibw 2 config configuration. |
| [pyjet][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | The interface between FastJet and NumPy |
| [power-grid-model][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Python/C++ library for distribution power system analysis |
| [pybind11 scikit_build_example][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | An example combining scikit-build and pybind11 |
| [ninja][] | ![github icon][] ![travisci icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Multitagged binary builds for all supported platforms, using cibw 2 config configuration. |
| [GSD][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Cython and NumPy project with 64-bit wheels. |
| [pillow-heif][] | ![github icon][] | ![apple icon][] ![linux icon][] | Python CFFI binding to libheif library with third party dependencies like `libde265`, `x265`, `libaom` with test & publishing on PyPi. |
| [pyinstrument_cext][] | ![travisci icon][] ![appveyor icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | A simple C extension, without external dependencies |
@@ -98,22 +110,29 @@ title: Working examples
[scikit-learn]: https://github.com/scikit-learn/scikit-learn
[Tornado]: https://github.com/tornadoweb/tornado
[NumPy]: https://github.com/numpy/numpy
[pytorch-fairseq]: https://github.com/pytorch/fairseq
[Matplotlib]: https://github.com/matplotlib/matplotlib
[Kivy]: https://github.com/kivy/kivy
[NCNN]: https://github.com/Tencent/ncnn
[Prophet]: https://github.com/facebook/prophet
[MyPy]: https://github.com/mypyc/mypy_mypyc-wheels
[pydantic]: https://github.com/samuelcolvin/pydantic
[uvloop]: https://github.com/MagicStack/uvloop
[psutil]: https://github.com/giampaolo/psutil
[MemRay]: https://github.com/bloomberg/memray
[vaex]: https://github.com/vaexio/vaex
[Google Benchmark]: https://github.com/google/benchmark
[Apache Beam]: https://github.com/apache/beam
[asyncpg]: https://github.com/MagicStack/asyncpg
[scikit-image]: https://github.com/scikit-image/scikit-image
[cmake]: https://github.com/scikit-build/cmake-python-distributions
[duckdb]: https://github.com/duckdb/duckdb
[PyGame]: https://github.com/pygame/pygame
[cmake]: https://github.com/scikit-build/cmake-python-distributions
[twisted-iocpsupport]: https://github.com/twisted/twisted-iocpsupport
[websockets]: https://github.com/aaugustin/websockets
[cvxpy]: https://github.com/cvxpy/cvxpy
[UltraJSON]: https://github.com/ultrajson/ultrajson
[PyOxidizer]: https://github.com/indygreg/PyOxidizer
[Triton]: https://github.com/openai/triton
[River]: https://github.com/online-ml/river
@@ -121,6 +140,7 @@ title: Working examples
[pyzmq]: https://github.com/zeromq/pyzmq
[aiortc]: https://github.com/aiortc/aiortc
[vispy]: https://github.com/vispy/vispy
[Implicit]: https://github.com/benfred/implicit
[Confluent client for Kafka]: https://github.com/confluentinc/confluent-kafka-python
[tinyobjloader]: https://github.com/tinyobjloader/tinyobjloader
[Dependency Injector]: https://github.com/ets-labs/python-dependency-injector
@@ -129,12 +149,14 @@ title: Working examples
[PyYAML]: https://github.com/yaml/pyyaml
[numexpr]: https://github.com/pydata/numexpr
[h5py]: https://github.com/h5py/h5py
[Wrapt]: https://github.com/GrahamDumpleton/wrapt
[PyAV]: https://github.com/PyAV-Org/PyAV
[SimpleJSON]: https://github.com/simplejson/simplejson
[OpenColorIO]: https://github.com/AcademySoftwareFoundation/OpenColorIO
[Line Profiler]: https://github.com/pyutils/line_profiler
[PyTables]: https://github.com/PyTables/PyTables
[OpenTimelineIO]: https://github.com/PixarAnimationStudios/OpenTimelineIO
[pikepdf]: https://github.com/pikepdf/pikepdf
[OpenTimelineIO]: https://github.com/PixarAnimationStudios/OpenTimelineIO
[ruptures]: https://github.com/deepcharles/ruptures
[aioquic]: https://github.com/aiortc/aioquic
[DeepForest]: https://github.com/LAMDA-NJU/Deep-Forest
@@ -143,8 +165,8 @@ title: Working examples
[Parselmouth]: https://github.com/YannickJadoul/Parselmouth
[AutoPy]: https://github.com/autopilot-rs/autopy
[H3-py]: https://github.com/uber/h3-py
[markupsafe]: https://github.com/pallets/markupsafe
[Rtree]: https://github.com/Toblerity/rtree
[markupsafe]: https://github.com/pallets/markupsafe
[python-rapidjson]: https://github.com/python-rapidjson/python-rapidjson
[python-snappy]: https://github.com/andrix/python-snappy
[pybind11 cmake_example]: https://github.com/pybind/cmake_example
@@ -153,10 +175,10 @@ title: Working examples
[pybind11 python_example]: https://github.com/pybind/python_example
[dd-trace-py]: https://github.com/DataDog/dd-trace-py
[cyvcf2]: https://github.com/brentp/cyvcf2
[sourmash]: https://github.com/dib-lab/sourmash
[time-machine]: https://github.com/adamchainz/time-machine
[abess]: https://github.com/abess-team/abess
[sourmash]: https://github.com/dib-lab/sourmash
[CTranslate2]: https://github.com/OpenNMT/CTranslate2
[abess]: https://github.com/abess-team/abess
[matrixprofile]: https://github.com/matrix-profile-foundation/matrixprofile
[jq.py]: https://github.com/mwilliamson/jq.py
[iminuit]: https://github.com/scikit-hep/iminuit
@@ -166,6 +188,7 @@ title: Working examples
[boost-histogram]: https://github.com/scikit-hep/boost-histogram
[iDynTree]: https://github.com/robotology/idyntree
[TgCrypto]: https://github.com/pyrogram/tgcrypto
[Python-WebRTC]: https://github.com/MarshalX/python-webrtc
[pybase64]: https://github.com/mayeut/pybase64
[Arbor]: https://github.com/arbor-sim/arbor
[etebase-py]: https://github.com/etesync/etebase-py
@@ -173,10 +196,11 @@ title: Working examples
[Imagecodecs (fork)]: https://github.com/czaki/imagecodecs_build
[polaroid]: https://github.com/daggy1234/polaroid
[numpythia]: https://github.com/scikit-hep/numpythia
[pyjet]: https://github.com/scikit-hep/pyjet
[clang-format]: https://github.com/ssciwr/clang-format-wheel
[ninja]: https://github.com/scikit-build/ninja-python-distributions
[pyjet]: https://github.com/scikit-hep/pyjet
[power-grid-model]: https://github.com/alliander-opensource/power-grid-model
[pybind11 scikit_build_example]: https://github.com/pybind/scikit_build_example
[ninja]: https://github.com/scikit-build/ninja-python-distributions
[GSD]: https://github.com/glotzerlab/gsd
[pillow-heif]: https://github.com/bigcat88/pillow_heif
[pyinstrument_cext]: https://github.com/joerick/pyinstrument_cext
@@ -194,93 +218,105 @@ title: Working examples
[apple icon]: data/readme_icons/apple.svg
[linux icon]: data/readme_icons/linux.svg
<!-- scikit-learn: 49555, last pushed 0 days ago -->
<!-- Tornado: 20477, last pushed 1 days ago -->
<!-- pytorch-fairseq: 16526, last pushed 2 days ago -->
<!-- Matplotlib: 15257, last pushed 0 days ago -->
<!-- MyPy: 12783, last pushed 0 days ago -->
<!-- pydantic: 9538, last pushed 3 days ago -->
<!-- uvloop: 8496, last pushed 85 days ago -->
<!-- psutil: 8240, last pushed 3 days ago -->
<!-- vaex: 6968, last pushed 0 days ago -->
<!-- Google Benchmark: 6312, last pushed 0 days ago -->
<!-- Apache Beam: 5409, last pushed 0 days ago -->
<!-- asyncpg: 5394, last pushed 4 days ago -->
<!-- scikit-image: 4842, last pushed 0 days ago -->
<!-- cmake: 4616, last pushed 0 days ago -->
<!-- duckdb: 4607, last pushed 0 days ago -->
<!-- twisted-iocpsupport: 4550, last pushed 0 days ago -->
<!-- websockets: 3862, last pushed 0 days ago -->
<!-- cvxpy: 3840, last pushed 5 days ago -->
<!-- PyOxidizer: 3571, last pushed 0 days ago -->
<!-- Triton: 3552, last pushed 0 days ago -->
<!-- River: 3261, last pushed 0 days ago -->
<!-- OpenSpiel: 3129, last pushed 3 days ago -->
<!-- pyzmq: 3057, last pushed 3 days ago -->
<!-- aiortc: 2857, last pushed 2 days ago -->
<!-- vispy: 2836, last pushed 0 days ago -->
<!-- Confluent client for Kafka: 2699, last pushed 0 days ago -->
<!-- tinyobjloader: 2460, last pushed 95 days ago -->
<!-- Dependency Injector: 1986, last pushed 2 days ago -->
<!-- coverage.py: 1972, last pushed 3 days ago -->
<!-- PyCryptodome: 1961, last pushed 2 days ago -->
<!-- PyYAML: 1785, last pushed 9 days ago -->
<!-- numexpr: 1741, last pushed 2 days ago -->
<!-- h5py: 1703, last pushed 0 days ago -->
<!-- PyAV: 1503, last pushed 0 days ago -->
<!-- OpenColorIO: 1275, last pushed 0 days ago -->
<!-- Line Profiler: 1140, last pushed 0 days ago -->
<!-- PyTables: 1113, last pushed 6 days ago -->
<!-- OpenTimelineIO: 1023, last pushed 0 days ago -->
<!-- pikepdf: 982, last pushed 2 days ago -->
<!-- ruptures: 930, last pushed 3 days ago -->
<!-- aioquic: 893, last pushed 2 days ago -->
<!-- DeepForest: 737, last pushed 252 days ago -->
<!-- google neuroglancer: 725, last pushed 3 days ago -->
<!-- Psycopg 3: 638, last pushed 0 days ago -->
<!-- Parselmouth: 634, last pushed 0 days ago -->
<!-- AutoPy: 629, last pushed 97 days ago -->
<!-- H3-py: 498, last pushed 2 days ago -->
<!-- markupsafe: 459, last pushed 17 days ago -->
<!-- Rtree: 456, last pushed 1 days ago -->
<!-- python-rapidjson: 447, last pushed 23 days ago -->
<!-- python-snappy: 426, last pushed 15 days ago -->
<!-- pybind11 cmake_example: 380, last pushed 2 days ago -->
<!-- KDEpy: 356, last pushed 50 days ago -->
<!-- tgcalls: 346, last pushed 83 days ago -->
<!-- pybind11 python_example: 312, last pushed 81 days ago -->
<!-- dd-trace-py: 300, last pushed 0 days ago -->
<!-- cyvcf2: 294, last pushed 17 days ago -->
<!-- sourmash: 281, last pushed 0 days ago -->
<!-- time-machine: 274, last pushed 3 days ago -->
<!-- abess: 258, last pushed 6 days ago -->
<!-- CTranslate2: 254, last pushed 0 days ago -->
<!-- matrixprofile: 250, last pushed 279 days ago -->
<!-- jq.py: 206, last pushed 54 days ago -->
<!-- iminuit: 197, last pushed 2 days ago -->
<!-- Tokenizer: 169, last pushed 25 days ago -->
<!-- PyGLM: 133, last pushed 3 days ago -->
<!-- bx-python: 113, last pushed 86 days ago -->
<!-- boost-histogram: 107, last pushed 1 days ago -->
<!-- iDynTree: 98, last pushed 4 days ago -->
<!-- TgCrypto: 94, last pushed 28 days ago -->
<!-- scikit-learn: 49827, last pushed 0 days ago -->
<!-- Tornado: 20521, last pushed 2 days ago -->
<!-- NumPy: 20265, last pushed 0 days ago -->
<!-- pytorch-fairseq: 16785, last pushed 0 days ago -->
<!-- Matplotlib: 15401, last pushed 0 days ago -->
<!-- Kivy: 14554, last pushed 2 days ago -->
<!-- NCNN: 14371, last pushed 0 days ago -->
<!-- Prophet: 14355, last pushed 16 days ago -->
<!-- MyPy: 12962, last pushed 0 days ago -->
<!-- pydantic: 9748, last pushed 2 days ago -->
<!-- uvloop: 8562, last pushed 111 days ago -->
<!-- psutil: 8332, last pushed 2 days ago -->
<!-- MemRay: 7309, last pushed 0 days ago -->
<!-- vaex: 7014, last pushed 1 days ago -->
<!-- Google Benchmark: 6408, last pushed 16 days ago -->
<!-- Apache Beam: 5467, last pushed 0 days ago -->
<!-- asyncpg: 5434, last pushed 31 days ago -->
<!-- scikit-image: 4877, last pushed 0 days ago -->
<!-- duckdb: 4808, last pushed 0 days ago -->
<!-- PyGame: 4731, last pushed 0 days ago -->
<!-- cmake: 4701, last pushed 0 days ago -->
<!-- twisted-iocpsupport: 4574, last pushed 0 days ago -->
<!-- websockets: 3903, last pushed 3 days ago -->
<!-- cvxpy: 3881, last pushed 0 days ago -->
<!-- UltraJSON: 3662, last pushed 0 days ago -->
<!-- PyOxidizer: 3628, last pushed 0 days ago -->
<!-- Triton: 3590, last pushed 0 days ago -->
<!-- River: 3327, last pushed 0 days ago -->
<!-- OpenSpiel: 3163, last pushed 1 days ago -->
<!-- pyzmq: 3069, last pushed 2 days ago -->
<!-- aiortc: 2887, last pushed 1 days ago -->
<!-- vispy: 2858, last pushed 0 days ago -->
<!-- Implicit: 2753, last pushed 1 days ago -->
<!-- Confluent client for Kafka: 2731, last pushed 0 days ago -->
<!-- tinyobjloader: 2492, last pushed 121 days ago -->
<!-- Dependency Injector: 2061, last pushed 10 days ago -->
<!-- coverage.py: 2013, last pushed 2 days ago -->
<!-- PyCryptodome: 1981, last pushed 11 days ago -->
<!-- PyYAML: 1810, last pushed 11 days ago -->
<!-- numexpr: 1750, last pushed 7 days ago -->
<!-- h5py: 1716, last pushed 21 days ago -->
<!-- Wrapt: 1662, last pushed 40 days ago -->
<!-- PyAV: 1538, last pushed 0 days ago -->
<!-- SimpleJSON: 1481, last pushed 5 days ago -->
<!-- OpenColorIO: 1299, last pushed 0 days ago -->
<!-- Line Profiler: 1173, last pushed 0 days ago -->
<!-- PyTables: 1120, last pushed 8 days ago -->
<!-- pikepdf: 1042, last pushed 8 days ago -->
<!-- OpenTimelineIO: 1035, last pushed 5 days ago -->
<!-- ruptures: 945, last pushed 12 days ago -->
<!-- aioquic: 906, last pushed 0 days ago -->
<!-- DeepForest: 743, last pushed 278 days ago -->
<!-- google neuroglancer: 731, last pushed 7 days ago -->
<!-- Psycopg 3: 654, last pushed 0 days ago -->
<!-- Parselmouth: 649, last pushed 23 days ago -->
<!-- AutoPy: 634, last pushed 123 days ago -->
<!-- H3-py: 514, last pushed 0 days ago -->
<!-- Rtree: 473, last pushed 8 days ago -->
<!-- markupsafe: 465, last pushed 23 days ago -->
<!-- python-rapidjson: 449, last pushed 50 days ago -->
<!-- python-snappy: 430, last pushed 42 days ago -->
<!-- pybind11 cmake_example: 392, last pushed 16 days ago -->
<!-- KDEpy: 365, last pushed 76 days ago -->
<!-- tgcalls: 347, last pushed 109 days ago -->
<!-- pybind11 python_example: 320, last pushed 16 days ago -->
<!-- dd-trace-py: 315, last pushed 0 days ago -->
<!-- cyvcf2: 295, last pushed 43 days ago -->
<!-- time-machine: 292, last pushed 0 days ago -->
<!-- sourmash: 286, last pushed 0 days ago -->
<!-- CTranslate2: 263, last pushed 0 days ago -->
<!-- abess: 261, last pushed 2 days ago -->
<!-- matrixprofile: 256, last pushed 306 days ago -->
<!-- jq.py: 212, last pushed 80 days ago -->
<!-- iminuit: 199, last pushed 6 days ago -->
<!-- Tokenizer: 174, last pushed 51 days ago -->
<!-- PyGLM: 138, last pushed 30 days ago -->
<!-- bx-python: 113, last pushed 112 days ago -->
<!-- boost-histogram: 110, last pushed 9 days ago -->
<!-- iDynTree: 103, last pushed 16 days ago -->
<!-- TgCrypto: 96, last pushed 54 days ago -->
<!-- Python-WebRTC: 88, last pushed 48 days ago -->
<!-- pybase64: 82, last pushed 2 days ago -->
<!-- Arbor: 70, last pushed 0 days ago -->
<!-- etebase-py: 56, last pushed 95 days ago -->
<!-- fathon: 43, last pushed 134 days ago -->
<!-- Imagecodecs (fork): 41, last pushed 32 days ago -->
<!-- polaroid: 35, last pushed 110 days ago -->
<!-- numpythia: 33, last pushed 34 days ago -->
<!-- pyjet: 32, last pushed 34 days ago -->
<!-- clang-format: 32, last pushed 38 days ago -->
<!-- ninja: 23, last pushed 10 days ago -->
<!-- pybind11 scikit_build_example: 21, last pushed 51 days ago -->
<!-- GSD: 19, last pushed 87 days ago -->
<!-- pillow-heif: 16, last pushed 0 days ago -->
<!-- pyinstrument_cext: 10, last pushed 175 days ago -->
<!-- xmlstarlet: 8, last pushed 11 days ago -->
<!-- CorrectionLib: 8, last pushed 0 days ago -->
<!-- SiPM: 5, last pushed 1 days ago -->
<!-- Arbor: 72, last pushed 0 days ago -->
<!-- etebase-py: 56, last pushed 121 days ago -->
<!-- fathon: 44, last pushed 161 days ago -->
<!-- Imagecodecs (fork): 42, last pushed 58 days ago -->
<!-- polaroid: 35, last pushed 137 days ago -->
<!-- numpythia: 33, last pushed 23 days ago -->
<!-- clang-format: 33, last pushed 1 days ago -->
<!-- pyjet: 32, last pushed 23 days ago -->
<!-- power-grid-model: 31, last pushed 0 days ago -->
<!-- pybind11 scikit_build_example: 23, last pushed 16 days ago -->
<!-- ninja: 23, last pushed 3 days ago -->
<!-- GSD: 19, last pushed 12 days ago -->
<!-- pillow-heif: 18, last pushed 2 days ago -->
<!-- pyinstrument_cext: 10, last pushed 201 days ago -->
<!-- xmlstarlet: 9, last pushed 16 days ago -->
<!-- CorrectionLib: 8, last pushed 7 days ago -->
<!-- SiPM: 6, last pushed 8 days ago -->
<!-- END bin/projects.py -->
+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==2.4.0
install: python -m pip install cibuildwheel==2.5.0
build_script: python -m cibuildwheel --output-dir wheelhouse
+3 -3
View File
@@ -6,7 +6,7 @@ jobs:
- bash: |
set -o errexit
python3 -m pip install --upgrade pip
pip3 install cibuildwheel==2.4.0
pip3 install cibuildwheel==2.5.0
displayName: Install dependencies
- bash: cibuildwheel --output-dir wheelhouse .
displayName: Build wheels
@@ -20,7 +20,7 @@ jobs:
- bash: |
set -o errexit
python3 -m pip install --upgrade pip
python3 -m pip install cibuildwheel==2.4.0
python3 -m pip install cibuildwheel==2.5.0
displayName: Install dependencies
- bash: cibuildwheel --output-dir wheelhouse .
displayName: Build wheels
@@ -34,7 +34,7 @@ jobs:
- bash: |
set -o errexit
python -m pip install --upgrade pip
pip install cibuildwheel==2.4.0
pip install cibuildwheel==2.5.0
displayName: Install dependencies
- bash: cibuildwheel --output-dir wheelhouse .
displayName: Build wheels
+2 -2
View File
@@ -11,7 +11,7 @@ jobs:
- run:
name: Build the Linux wheels.
command: |
pip3 install --user cibuildwheel==2.4.0
pip3 install --user cibuildwheel==2.5.0
cibuildwheel --output-dir wheelhouse
- store_artifacts:
path: wheelhouse/
@@ -25,7 +25,7 @@ jobs:
- run:
name: Build the OS X wheels.
command: |
pip3 install cibuildwheel==2.4.0
pip3 install cibuildwheel==2.5.0
cibuildwheel --output-dir wheelhouse
- store_artifacts:
path: wheelhouse/
+1 -1
View File
@@ -10,7 +10,7 @@ jobs:
- uses: actions/checkout@v2
- name: Build wheels
uses: pypa/cibuildwheel@v2.4.0
uses: pypa/cibuildwheel@v2.5.0
env:
CIBW_ARCHS_MACOS: x86_64 universal2
+1 -1
View File
@@ -22,7 +22,7 @@ jobs:
- uses: actions/checkout@v2
- name: Build wheels
uses: pypa/cibuildwheel@v2.4.0
uses: pypa/cibuildwheel@v2.5.0
- uses: actions/upload-artifact@v2
with:
+1 -1
View File
@@ -14,7 +14,7 @@ jobs:
- uses: actions/checkout@v2
- name: Build wheels
uses: pypa/cibuildwheel@v2.4.0
uses: pypa/cibuildwheel@v2.5.0
# to supply options, put them in 'env', like:
# env:
# CIBW_SOME_OPTION: value
+1 -1
View File
@@ -25,7 +25,7 @@ jobs:
platforms: all
- name: Build wheels
uses: pypa/cibuildwheel@v2.4.0
uses: pypa/cibuildwheel@v2.5.0
env:
# configure cibuildwheel to build native archs ('auto'), and some
# emulated ones
+1 -1
View File
@@ -12,7 +12,7 @@ linux:
DOCKER_TLS_CERTDIR: ""
script:
- curl -sSL https://get.docker.com/ | sh
- python -m pip install cibuildwheel==2.4.0
- python -m pip install cibuildwheel==2.5.0
- cibuildwheel --output-dir wheelhouse
artifacts:
paths:
+1 -1
View File
@@ -19,7 +19,7 @@ jobs:
- ln -s /c/Python38/python.exe /c/Python38/python3.exe
install:
- python3 -m pip install cibuildwheel==2.4.0
- python3 -m pip install cibuildwheel==2.5.0
script:
# build the wheels, put them into './dist'
+1 -1
View File
@@ -25,7 +25,7 @@ jobs:
- ln -s /c/Python38/python.exe /c/Python38/python3.exe
install:
- python3 -m pip install cibuildwheel==2.4.0
- python3 -m pip install cibuildwheel==2.5.0
script:
# build the wheels, put them into './wheelhouse'
+2 -2
View File
@@ -55,7 +55,7 @@ jobs:
- stage: deploy
name: Build and deploy Linux wheels
services: docker
install: python3 -m pip install cibuildwheel==2.4.0 twine
install: python3 -m pip install cibuildwheel==2.5.0 twine
script: python3 -m cibuildwheel --output-dir wheelhouse
after_success: python3 -m twine upload --skip-existing wheelhouse/*.whl
# Deploy on windows
@@ -63,7 +63,7 @@ jobs:
name: Build and deploy Windows wheels
os: windows
language: shell
install: python3 -m pip install cibuildwheel==2.4.0 twine
install: python3 -m pip install cibuildwheel==2.5.0 twine
script: python3 -m cibuildwheel --output-dir wheelhouse
after_success: python3 -m twine upload --skip-existing wheelhouse/*.whl
+5 -5
View File
@@ -1,6 +1,6 @@
[metadata]
name = cibuildwheel
version = 2.4.0
version = 2.5.0
description = Build Python wheels on CI with minimal configuration.
long_description = file: README.md
long_description_content_type = text/markdown
@@ -35,10 +35,10 @@ install_requires =
bracex
certifi
filelock
packaging
packaging>=20.9
platformdirs
tomli
dataclasses;python_version < '3.7'
tomli;python_version < '3.11'
typing-extensions>=3.10.0.0;python_version < '3.8'
python_requires = >=3.6
include_package_data = True
@@ -56,8 +56,8 @@ console_scripts =
cibuildwheel = resources/*
[flake8]
ignore = E501,W503,E741,E226,B950,E203
select = C,E,F,W,B,B9
extend-ignore = E203,E501,B950
extend-select = B,B9
application-import-names = cibuildwheel
exclude =
cibuildwheel/resources/,
+1
View File
@@ -13,6 +13,7 @@ extras = {
"pytest>=6",
"pytest-timeout",
"pytest-xdist",
"build",
],
"bin": [
"click",
+16
View File
@@ -59,3 +59,19 @@ def test_build_identifiers(tmp_path):
assert len(expected_wheels) == len(
build_identifiers
), f"{expected_wheels} vs {build_identifiers}"
def test_allow_empty(tmp_path):
project_dir = tmp_path / "project"
basic_project.generate(project_dir)
# Sanity check - --allow-empty should cause a no-op build to complete
# without error
actual_wheels = utils.cibuildwheel_run(
project_dir,
add_env={"CIBW_BUILD": "BUILD_NOTHING_AT_ALL"},
add_args=["--allow-empty"],
)
# check that nothing was built
assert len(actual_wheels) == 0
+173
View File
@@ -0,0 +1,173 @@
import os
import subprocess
import sys
import textwrap
from pathlib import Path
from tempfile import TemporaryDirectory
from test.test_projects.base import TestProject
from . import test_projects, utils
# utilities
def make_sdist(project: TestProject, working_dir: Path) -> Path:
project_dir = working_dir / "project"
project_dir.mkdir(parents=True, exist_ok=True)
project.generate(project_dir)
sdist_dir = working_dir / "sdist"
subprocess.run(
[sys.executable, "-m", "build", "--sdist", "--outdir", str(sdist_dir), str(project_dir)],
check=True,
)
return next(sdist_dir.glob("*.tar.gz"))
def cibuildwheel_from_sdist_run(sdist_path, add_env=None, config_file=None):
env = os.environ.copy()
if add_env:
env.update(add_env)
with TemporaryDirectory() as tmp_output_dir:
subprocess.run(
[
sys.executable,
"-m",
"cibuildwheel",
*(["--config-file", config_file] if config_file else []),
"--output-dir",
str(tmp_output_dir),
str(sdist_path),
],
env=env,
check=True,
)
return os.listdir(tmp_output_dir)
# tests
def test_simple(tmp_path):
basic_project = test_projects.new_c_project()
# make an sdist of the project
sdist_dir = tmp_path / "sdist"
sdist_dir.mkdir()
sdist_path = make_sdist(basic_project, sdist_dir)
# build the wheels from sdist
actual_wheels = cibuildwheel_from_sdist_run(
sdist_path,
add_env={"CIBW_BUILD": "cp39-*"},
)
# check that the expected wheels are produced
expected_wheels = [w for w in utils.expected_wheels("spam", "0.1.0") if "cp39" in w]
assert set(actual_wheels) == set(expected_wheels)
def test_external_config_file_argument(tmp_path, capfd):
basic_project = test_projects.new_c_project()
# make an sdist of the project
sdist_dir = tmp_path / "sdist"
sdist_dir.mkdir()
sdist_path = make_sdist(basic_project, sdist_dir)
# add a config file
config_file = tmp_path / "config.toml"
config_file.write_text(
textwrap.dedent(
"""
[tool.cibuildwheel]
before-all = 'echo "test log statement from before-all"'
"""
)
)
# build the wheels from sdist
actual_wheels = cibuildwheel_from_sdist_run(
sdist_path,
add_env={"CIBW_BUILD": "cp39-*"},
config_file=str(config_file),
)
# check that the expected wheels are produced
expected_wheels = [w for w in utils.expected_wheels("spam", "0.1.0") if "cp39" in w]
assert set(actual_wheels) == set(expected_wheels)
# check that before-all was run
captured = capfd.readouterr()
assert "test log statement from before-all" in captured.out
def test_config_in_pyproject_toml(tmp_path, capfd):
# make a project with a pyproject.toml
project = test_projects.new_c_project()
project.files["pyproject.toml"] = textwrap.dedent(
"""
[tool.cibuildwheel]
before-build = 'echo "test log statement from before-build 8419"'
"""
)
# make an sdist of the project
sdist_dir = tmp_path / "sdist"
sdist_dir.mkdir()
sdist_path = make_sdist(project, sdist_dir)
# build the wheels from sdist
actual_wheels = cibuildwheel_from_sdist_run(
sdist_path,
add_env={"CIBW_BUILD": "cp39-*"},
)
# check that the expected wheels are produced
expected_wheels = [w for w in utils.expected_wheels("spam", "0.1.0") if "cp39" in w]
assert set(actual_wheels) == set(expected_wheels)
# check that before-build was run
captured = capfd.readouterr()
assert "test log statement from before-build 8419" in captured.out
def test_internal_config_file_argument(tmp_path, capfd):
# make a project with a config file inside
project = test_projects.new_c_project(
setup_cfg_add="include_package_data = True",
)
project.files["wheel_build_config.toml"] = textwrap.dedent(
"""
[tool.cibuildwheel]
before-all = 'echo "test log statement from before-all 1829"'
"""
)
project.files["MANIFEST.in"] = textwrap.dedent(
"""
include wheel_build_config.toml
"""
)
# make an sdist of the project
sdist_dir = tmp_path / "sdist"
sdist_dir.mkdir()
sdist_path = make_sdist(project, sdist_dir)
# build the wheels from sdist, referencing the config file inside
actual_wheels = cibuildwheel_from_sdist_run(
sdist_path,
add_env={"CIBW_BUILD": "cp39-*"},
config_file="{package}/wheel_build_config.toml",
)
# check that the expected wheels are produced
expected_wheels = [w for w in utils.expected_wheels("spam", "0.1.0") if "cp39" in w]
assert set(actual_wheels) == set(expected_wheels)
# check that before-all was run
captured = capfd.readouterr()
assert "test log statement from before-all 1829" in captured.out
+50
View File
@@ -0,0 +1,50 @@
import textwrap
from . import test_projects, utils
limited_api_project = test_projects.new_c_project(
setup_py_add=textwrap.dedent(
r"""
cmdclass = {}
extension_kwargs = {}
if sys.version_info[:2] >= (3, 8):
from wheel.bdist_wheel import bdist_wheel as _bdist_wheel
class bdist_wheel_abi3(_bdist_wheel):
def finalize_options(self):
_bdist_wheel.finalize_options(self)
self.root_is_pure = False
def get_tag(self):
python, abi, plat = _bdist_wheel.get_tag(self)
return python, "abi3", plat
cmdclass["bdist_wheel"] = bdist_wheel_abi3
extension_kwargs["define_macros"] = [("Py_LIMITED_API", "0x03080000")]
extension_kwargs["py_limited_api"] = True
"""
),
setup_py_extension_args_add="**extension_kwargs",
setup_py_setup_args_add="cmdclass=cmdclass",
)
def test(tmp_path):
project_dir = tmp_path / "project"
limited_api_project.generate(project_dir)
# build the wheels
actual_wheels = utils.cibuildwheel_run(
project_dir,
add_env={
"CIBW_SKIP": "pp* ", # PyPy does not have a Py_LIMITED_API equivalent
},
)
# check that the expected wheels are produced
expected_wheels = [
w.replace("cp38-cp38", "cp38-abi3")
for w in utils.expected_wheels("spam", "0.1.0")
if "-pp" not in w and "-cp39" not in w and "-cp310" not in w
]
assert set(actual_wheels) == set(expected_wheels)
+3
View File
@@ -54,6 +54,7 @@ setup(
'spam',
sources=['spam.c'],
libraries=libraries,
{{ setup_py_extension_args_add | indent(8) }}
)],
{{ setup_py_setup_args_add | indent(4) }}
)
@@ -73,6 +74,7 @@ def new_c_project(
spam_c_top_level_add="",
spam_c_function_add="",
setup_py_add="",
setup_py_extension_args_add="",
setup_py_setup_args_add="",
setup_cfg_add="",
):
@@ -91,6 +93,7 @@ def new_c_project(
"spam_c_top_level_add": spam_c_top_level_add,
"spam_c_function_add": spam_c_function_add,
"setup_py_add": setup_py_add,
"setup_py_extension_args_add": setup_py_extension_args_add,
"setup_py_setup_args_add": setup_py_setup_args_add,
"setup_cfg_add": setup_cfg_add,
}
+8 -1
View File
@@ -44,7 +44,9 @@ def cibuildwheel_get_build_identifiers(project_path, env=None, *, prerelease_pyt
return cmd_output.strip().split("\n")
def cibuildwheel_run(project_path, package_dir=".", env=None, add_env=None, output_dir=None):
def cibuildwheel_run(
project_path, package_dir=".", env=None, add_env=None, output_dir=None, add_args=None
):
"""
Runs cibuildwheel as a subprocess, building the project at project_path.
@@ -57,6 +59,7 @@ def cibuildwheel_run(project_path, package_dir=".", env=None, add_env=None, outp
:param add_env: environment used to update env
:param output_dir: directory where wheels are saved. If None, a temporary
directory will be used for the duration of the command.
:param add_args: Additional command-line arguments to pass to cibuildwheel.
:return: list of built wheels (file names).
"""
if env is None:
@@ -64,6 +67,9 @@ def cibuildwheel_run(project_path, package_dir=".", env=None, add_env=None, outp
# If present in the host environment, remove the MACOSX_DEPLOYMENT_TARGET for consistency
env.pop("MACOSX_DEPLOYMENT_TARGET", None)
if add_args is None:
add_args = []
if add_env is not None:
env.update(add_env)
@@ -77,6 +83,7 @@ def cibuildwheel_run(project_path, package_dir=".", env=None, add_env=None, outp
"--output-dir",
str(output_dir or tmp_output_dir),
str(package_dir),
*add_args,
],
env=env,
cwd=project_path,
+7 -2
View File
@@ -1,6 +1,11 @@
import sys
from typing import Dict, List
import tomli
if sys.version_info >= (3, 11):
import tomllib
else:
import tomli as tomllib
from packaging.version import Version
from cibuildwheel.extra import Printable, dump_python_configurations
@@ -12,7 +17,7 @@ def test_compare_configs():
txt = f1.read()
with open(resources_dir / "build-platforms.toml", "rb") as f2:
dict_txt = tomli.load(f2)
dict_txt = tomllib.load(f2)
new_txt = dump_python_configurations(dict_txt)
print(new_txt)
+1 -1
View File
@@ -32,7 +32,7 @@ def fake_package_dir(monkeypatch):
real_path_exists = Path.exists
def mock_path_exists(path):
if path == MOCK_PACKAGE_DIR / "setup.py":
if str(path).endswith(str(MOCK_PACKAGE_DIR / "setup.py")):
return True
else:
return real_path_exists(path)
+9 -5
View File
@@ -3,7 +3,11 @@ from fnmatch import fnmatch
from pathlib import Path
import pytest
import tomli
if sys.version_info >= (3, 11):
import tomllib
else:
import tomli as tomllib
from cibuildwheel.__main__ import main
from cibuildwheel.environment import ParsedEnvironment
@@ -20,13 +24,13 @@ def test_output_dir(platform, intercepted_build_args, monkeypatch):
main()
assert intercepted_build_args.args[0].globals.output_dir == OUTPUT_DIR
assert intercepted_build_args.args[0].globals.output_dir == OUTPUT_DIR.resolve()
def test_output_dir_default(platform, intercepted_build_args, monkeypatch):
main()
assert intercepted_build_args.args[0].globals.output_dir == Path("wheelhouse")
assert intercepted_build_args.args[0].globals.output_dir == Path("wheelhouse").resolve()
@pytest.mark.parametrize("also_set_environment", [False, True])
@@ -39,7 +43,7 @@ def test_output_dir_argument(also_set_environment, platform, intercepted_build_a
main()
assert intercepted_build_args.args[0].globals.output_dir == OUTPUT_DIR
assert intercepted_build_args.args[0].globals.output_dir == OUTPUT_DIR.resolve()
def test_build_selector(platform, intercepted_build_args, monkeypatch, allow_empty):
@@ -314,7 +318,7 @@ def test_defaults(platform, intercepted_build_args):
build_options: BuildOptions = intercepted_build_args.args[0].build_options(identifier=None)
defaults_config_path = resources_dir / "defaults.toml"
with defaults_config_path.open("rb") as f:
defaults_toml = tomli.load(f)
defaults_toml = tomllib.load(f)
root_defaults = defaults_toml["tool"]["cibuildwheel"]
platform_defaults = defaults_toml["tool"]["cibuildwheel"][platform]
+2 -2
View File
@@ -60,14 +60,14 @@ def test_platform_argument(platform, intercepted_build_args, monkeypatch):
options = intercepted_build_args.args[0]
assert options.globals.package_dir == MOCK_PACKAGE_DIR
assert options.globals.package_dir == MOCK_PACKAGE_DIR.resolve()
def test_platform_environment(platform, intercepted_build_args, monkeypatch):
main()
options = intercepted_build_args.args[0]
assert options.globals.package_dir == MOCK_PACKAGE_DIR
assert options.globals.package_dir == MOCK_PACKAGE_DIR.resolve()
def test_archs_default(platform, intercepted_build_args, monkeypatch):
+3 -3
View File
@@ -34,7 +34,7 @@ def test_options_1(tmp_path, monkeypatch):
f.write(PYPROJECT_1)
args = get_default_command_line_arguments()
args.package_dir = str(tmp_path)
args.package_dir = tmp_path
monkeypatch.setattr(platform_module, "machine", lambda: "x86_64")
@@ -77,7 +77,7 @@ def test_passthrough(tmp_path, monkeypatch):
f.write(PYPROJECT_1)
args = get_default_command_line_arguments()
args.package_dir = str(tmp_path)
args.package_dir = tmp_path
monkeypatch.setattr(platform_module, "machine", lambda: "x86_64")
monkeypatch.setenv("EXAMPLE_ENV", "ONE")
@@ -105,7 +105,7 @@ def test_passthrough(tmp_path, monkeypatch):
)
def test_passthrough_evil(tmp_path, monkeypatch, env_var_value):
args = get_default_command_line_arguments()
args.package_dir = str(tmp_path)
args.package_dir = tmp_path
monkeypatch.setattr(platform_module, "machine", lambda: "x86_64")
monkeypatch.setenv("CIBW_ENVIRONMENT_PASS_LINUX", "ENV_VAR")
+4 -2
View File
@@ -1,3 +1,5 @@
from pathlib import Path
from cibuildwheel.options import CommandLineArguments
@@ -8,8 +10,8 @@ def get_default_command_line_arguments() -> CommandLineArguments:
defaults.allow_empty = False
defaults.archs = None
defaults.config_file = ""
defaults.output_dir = None
defaults.package_dir = "."
defaults.output_dir = Path("wheelhouse")
defaults.package_dir = Path(".")
defaults.prerelease_pythons = False
defaults.print_build_identifiers = False