Merge remote-tracking branch 'upstream/main' into arm64

This commit is contained in:
Steve Dower
2022-09-26 17:25:03 +01:00
64 changed files with 773 additions and 340 deletions
+2 -1
View File
@@ -6,6 +6,7 @@ run_tests: &RUN_TESTS
linux_x86_task: linux_x86_task:
timeout_in: 120m
compute_engine_instance: compute_engine_instance:
image_project: cirrus-images image_project: cirrus-images
image: family/docker-builder image: family/docker-builder
@@ -33,7 +34,7 @@ linux_aarch64_task:
windows_x86_task: windows_x86_task:
# The task takes ~55 minutes while the timeout happens # The task takes ~55 minutes while the timeout happens
# after 60 minutes by default, let's allow some wiggle room. # after 60 minutes by default, let's allow some wiggle room.
timeout_in: 90m timeout_in: 120m
windows_container: windows_container:
image: cirrusci/windowsservercore:visualstudio2022 image: cirrusci/windowsservercore:visualstudio2022
cpu: 8 cpu: 8
+1 -1
View File
@@ -14,7 +14,7 @@ repos:
- id: trailing-whitespace - id: trailing-whitespace
- repo: https://github.com/asottile/pyupgrade - repo: https://github.com/asottile/pyupgrade
rev: v2.37.3 rev: v2.38.0
hooks: hooks:
- id: pyupgrade - id: pyupgrade
args: ["--py37-plus"] args: ["--py37-plus"]
+29 -31
View File
@@ -55,10 +55,10 @@ Usage
|-----------------|-------|-------|---------|-----------|-----------| |-----------------|-------|-------|---------|-----------|-----------|
| GitHub Actions | ✅ | ✅ | ✅ | ✅¹ | ✅² | | GitHub Actions | ✅ | ✅ | ✅ | ✅¹ | ✅² |
| Azure Pipelines | ✅ | ✅ | ✅ | | ✅² | | Azure Pipelines | ✅ | ✅ | ✅ | | ✅² |
| Travis CI | ✅ | | ✅ | ✅ | ✅² | | Travis CI | ✅ | | ✅ | ✅ | |
| AppVeyor | ✅ | ✅ | ✅ | | ✅² | | AppVeyor | ✅ | ✅ | ✅ | | ✅² |
| CircleCI | ✅ | ✅ | | | ✅² | | CircleCI | ✅ | ✅ | | | ✅² |
| Gitlab CI | ✅ | | | | ✅² | | Gitlab CI | ✅ | | | | |
| Cirrus CI | ✅ | ✅³ | ✅ | ✅ | ✅ | | Cirrus CI | ✅ | ✅³ | ✅ | ✅ | ✅ |
<sup>¹ [Requires emulation](https://cibuildwheel.readthedocs.io/en/stable/faq/#emulation), distributed separately. Other services may also support Linux ARM through emulation or third-party build hosts, but these are not tested in our CI.</sup><br> <sup>¹ [Requires emulation](https://cibuildwheel.readthedocs.io/en/stable/faq/#emulation), distributed separately. Other services may also support Linux ARM through emulation or third-party build hosts, but these are not tested in our CI.</sup><br>
@@ -92,7 +92,7 @@ jobs:
- uses: actions/setup-python@v3 - uses: actions/setup-python@v3
- name: Install cibuildwheel - name: Install cibuildwheel
run: python -m pip install cibuildwheel==2.9.0 run: python -m pip install cibuildwheel==2.10.2
- name: Build wheels - name: Build wheels
run: python -m cibuildwheel --output-dir wheelhouse run: python -m cibuildwheel --output-dir wheelhouse
@@ -208,6 +208,32 @@ Changelog
<!-- this section was generated by bin/update_readme_changelog.py -- do not edit manually --> <!-- this section was generated by bin/update_readme_changelog.py -- do not edit manually -->
### v2.10.2
_25 September 2022_
- 🐛 Fix a bug that caused `win32` identifiers to fail when used with `--only`. (#1282)
- 🐛 Fix computation of `auto`/`auto64`/`auto32` archs when targeting a different platform to the one that you're running cibuildwheel on. (#1266)
- 📚 Fix an mistake in the 'how it works' diagram. (#1274)
### v2.10.1
_18 September 2022_
- 🐛 Fix a bug that stopped environment variables specified in TOML from being expanded. (#1273)
### v2.10.0
_13 September 2022_
- 🌟 Adds support for [building wheels on Cirrus CI](https://cibuildwheel.readthedocs.io/en/stable/setup/#cirrus-ci). This is exciting for us, as it's the first public CI platform that natively supports macOS Apple Silicon (aka. M1, `arm64`) runners. As such, it's the first platform that you can natively build _and test_ macOS `arm64` wheels. It also has native Linux ARM (aarch64) runners, for fast, native builds there. (#1191)
- 🌟 Adds support for running cibuildwheel on Apple Silicon machines. For a while, we've supported cross-compilation of Apple Silicon wheels on `x86_64`, but now that we have Cirrus CI we can run our test suite and officially support running cibuildwheel on `arm64`. (#1191)
- ✨ Adds the `--only` [command line option](https://cibuildwheel.readthedocs.io/en/stable/options/#command-line), to specify a single build to run. Previously, it could be cumbersome to set all the build selection options to target a specific build - for example, you might have to run something like `CIBW_BUILD=cp39-manylinux_x86_64 cibuildwheel --platform linux --archs x86_64`. The new `--only` option overrides all the build selection options to simplify running a single build, which now looks like `cibuildwheel --only cp39-manylinux_x86_64`. (#1098)
- ✨ Adds the [`CIBW_CONFIG_SETTINGS`](https://cibuildwheel.readthedocs.io/en/stable/options/#config-settings) option, so you can pass arguments to your package's build backend (#1244)
- 🛠 Updates the CPython 3.11 version to the latest release candidate - v3.11.0rc2. (#1265)
- 🐛 Fix a bug that can cause a RecursionError on Windows when building from an sdist. (#1253)
- 🛠 Add support for the s390x architecture on manylinux_2_28 (#1255)
### v2.9.0 ### v2.9.0
_11 August 2022_ _11 August 2022_
@@ -226,34 +252,6 @@ _18 July 2022_
- 🛠 The GitHub Action will ensure a compatible version of Python is installed on the runner (#1114) - 🛠 The GitHub Action will ensure a compatible version of Python is installed on the runner (#1114)
- 📚 A few docs improvements - 📚 A few docs improvements
### v2.8.0
_5 July 2022_
- ✨ You can now run cibuildwheel on Podman, as an alternate container engine to Docker (which remains the default). This is useful in environments where a Docker daemon isn't available, for example, it can be run inside a Docker container, or without root access. To use Podman, set the [`CIBW_CONTAINER_ENGINE`](https://cibuildwheel.readthedocs.io/en/stable/options/#container-engine) option. (#966)
- ✨ Adds support for building `py3-none-{platform}` wheels. This works the same as ABI3 - wheels won't be rebuilt, but tests will still be run across all selected versions of Python.
> These wheels contain native extension code, but don't use the Python APIs. Typically, they're bridged to Python using a FFI module like [ctypes](https://docs.python.org/3/library/ctypes.html) or [cffi](https://cffi.readthedocs.io/en/latest/). Because they don't use Python ABI, the wheels are more compatible - they work across many Python versions.
Check out this [example ctypes project](https://github.com/joerick/python-ctypes-package-sample) to see an example of how it works. (#1151)
- 🛠 cibuildwheel will now error if multiple builds in a single run produce the same wheel filename, as this indicates a misconfiguration. (#1152)
- 📚 A few docs improvements and updates to keep things up-to-date.
### v2.7.0
_17 June 2022_
- 🌟 Added support for the new `manylinux_2_28` images. These new images are based on AlmaLinux, the community-driven successor to CentOS, unlike manylinux_2_24, which was based on Debian. To build on these images, set your [`CIBW_MANYLINUX_*_IMAGE`](https://cibuildwheel.readthedocs.io/en/stable/options/#linux-image) option to `manylinux_2_28`. (#1026)
- 🐛 Fix a bug where tests were not being run on CPython 3.11 (when CIBW_PRERELEASE_PYTHONS was set) (#1138)
- ✨ You can now build Linux wheels on Windows, as long as you have Docker installed and set to 'Linux containers' (#1117)
- 🐛 Fix a bug on macOS that caused cibuildwheel to crash trying to overwrite a previously-built wheel of the same name. (#1129)
### v2.6.1
_7 June 2022_
- 🛠 Update the prerelease CPython 3.11 to 3.11.0b3
<!-- END bin/update_readme_changelog.py --> <!-- END bin/update_readme_changelog.py -->
--- ---
+5
View File
@@ -13,6 +13,10 @@ inputs:
description: 'File containing the config, defaults to {package}/pyproject.toml' description: 'File containing the config, defaults to {package}/pyproject.toml'
required: false required: false
default: '' default: ''
only:
description: 'Build a specific wheel only. No need for arch/platform if this is set'
required: false
default: ''
branding: branding:
icon: package icon: package
color: yellow color: yellow
@@ -36,5 +40,6 @@ runs:
${{ inputs.package-dir }} ${{ inputs.package-dir }}
--output-dir ${{ inputs.output-dir }} --output-dir ${{ inputs.output-dir }}
--config-file "${{ inputs.config-file }}" --config-file "${{ inputs.config-file }}"
--only "${{ inputs.only }}"
2>&1 2>&1
shell: bash shell: bash
+33 -15
View File
@@ -1,4 +1,17 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
"""
Check known projects for usage of requires-python.
Usage:
./bin/inspect_all_known_projects.py --online=$GITHUB_TOKEN
This will cache the results to all_known_setup.yaml; you can reprint
the results without the `--online` setting.
"""
from __future__ import annotations from __future__ import annotations
import ast import ast
@@ -7,7 +20,7 @@ from typing import Iterator
import click import click
import yaml import yaml
from ghapi.core import GhApi, HTTP404NotFoundError from github import Github, GithubException
from rich import print from rich import print
from cibuildwheel.projectfiles import Analyzer from cibuildwheel.projectfiles import Analyzer
@@ -47,33 +60,38 @@ def check_repo(name: str, contents: str) -> str:
class MaybeRemote: class MaybeRemote:
def __init__(self, cached_file: Path | str, *, online: bool) -> None: github: Github | None
self.online = online contents: dict[str, dict[str, str | None]]
if self.online:
self.contents: dict[str, dict[str, str | None]] = { def __init__(self, cached_file: Path | str, *, online: str | None) -> None:
if online is not None:
self.github = Github(online)
self.contents = {
"setup.py": {}, "setup.py": {},
"setup.cfg": {}, "setup.cfg": {},
"pyproject.toml": {}, "pyproject.toml": {},
} }
else: else:
self.github = None
with open(cached_file) as f: with open(cached_file) as f:
self.contents = yaml.safe_load(f) self.contents = yaml.safe_load(f)
def get(self, repo: str, filename: str) -> str | None: def get(self, repo: str, filename: str) -> str | None:
if self.online: if self.github:
try: try:
self.contents[filename][repo] = ( gh_file = self.github.get_repo(repo).get_contents(filename)
GhApi(*repo.split("/")).get_content(filename).decode() except GithubException:
)
except HTTP404NotFoundError:
self.contents[filename][repo] = None self.contents[filename][repo] = None
else:
assert not isinstance(gh_file, list)
self.contents[filename][repo] = gh_file.decoded_content.decode(encoding="utf-8")
return self.contents[filename][repo] return self.contents[filename][repo]
elif repo in self.contents[filename]: elif repo in self.contents[filename]:
return self.contents[filename][repo] return self.contents[filename][repo]
else: else:
raise RuntimeError( msg = f"Trying to access {repo}:{filename} and not in cache, rebuild cache"
f"Trying to access {repo}:{filename} and not in cache, rebuild cache" raise RuntimeError(msg)
)
def save(self, filename: Path | str) -> None: def save(self, filename: Path | str) -> None:
with open(filename, "w") as f: with open(filename, "w") as f:
@@ -87,8 +105,8 @@ class MaybeRemote:
@click.command() @click.command()
@click.option("--online", is_flag=True, help="Remember to set GITHUB_TOKEN") @click.option("--online", help="Set to $GITHUB_TOKEN")
def main(online: bool) -> None: def main(online: str | None) -> None:
with open(DIR / "../docs/data/projects.yml") as f: with open(DIR / "../docs/data/projects.yml") as f:
known = yaml.safe_load(f) known = yaml.safe_load(f)
+4 -2
View File
@@ -81,7 +81,8 @@ def ci_service_for_config_file(config_file):
if service.name == service_name: if service.name == service_name:
return service return service
raise ValueError(f"unknown ci service for config file {config_file}") msg = f"unknown ci service for config file {config_file}"
raise ValueError(msg)
@click.command() @click.command()
@@ -100,7 +101,8 @@ def run_example_ci_configs(config_files=None):
for config_file in config_files: for config_file in config_files:
service = ci_service_for_config_file(config_file) service = ci_service_for_config_file(config_file)
if service.name in configs_by_service: if service.name in configs_by_service:
raise Exception("You cannot specify more than one config per CI service") msg = "You cannot specify more than one config per CI service"
raise Exception(msg)
configs_by_service[service.name] = config_file configs_by_service[service.name] = config_file
if git_repo_has_changes(): if git_repo_has_changes():
+52
View File
@@ -0,0 +1,52 @@
#!/usr/bin/env python3
from __future__ import annotations
import subprocess
import sys
from pathlib import Path
try:
from html2image import Html2Image # type: ignore[import]
except ImportError:
sys.exit(
"""
html2image not found. Ensure you have Chrome (on Mac/Windows) or
Chromium (on Linux) installed, and then do:
pip install html2image
"""
)
def main():
subprocess.run(["mkdocs", "build"])
hti = Html2Image(custom_flags=["--force-device-scale-factor=2"])
html_str = Path("docs/diagram.md").read_text()
css_tags = f"""
<style>{Path("site/css/theme.css").read_text()}</style>
<style>{Path("site/css/theme_extra.css").read_text()}</style>
<style>{Path("site/extra.css").read_text()}</style>
<style>
body {{
background: white;
}}
</style>
"""
html_str = css_tags + html_str
[screenshot, *_] = hti.screenshot(
html_str=html_str,
size=(830, 405),
)
dest_path = Path("docs/data/how-it-works.png")
if dest_path.exists():
dest_path.unlink()
Path(screenshot).rename(dest_path)
if __name__ == "__main__":
main()
+6 -3
View File
@@ -141,7 +141,8 @@ class PyPyVersions:
releases = [r for r in releases if self.get_arch_file(r)] releases = [r for r in releases if self.get_arch_file(r)]
if not releases: if not releases:
raise RuntimeError(f"PyPy Win {self.arch} not found for {spec}! {self.releases}") msg = f"PyPy Win {self.arch} not found for {spec}! {self.releases}"
raise RuntimeError(msg)
version_arch = "win32" if self.arch == "32" else "win_amd64" version_arch = "win32" if self.arch == "32" else "win_amd64"
@@ -159,13 +160,15 @@ class PyPyVersions:
def update_version_macos(self, spec: Specifier) -> ConfigMacOS: def update_version_macos(self, spec: Specifier) -> ConfigMacOS:
if self.arch != "64": if self.arch != "64":
raise RuntimeError("Other archs not supported yet on macOS") msg = "Other archs not supported yet on macOS"
raise RuntimeError(msg)
releases = [r for r in self.releases if spec.contains(r["python_version"])] releases = [r for r in self.releases if spec.contains(r["python_version"])]
releases = sorted(releases, key=lambda r: r["pypy_version"]) # type: ignore[no-any-return] releases = sorted(releases, key=lambda r: r["pypy_version"]) # type: ignore[no-any-return]
if not releases: if not releases:
raise RuntimeError(f"PyPy macOS {self.arch} not found for {spec}!") msg = f"PyPy macOS {self.arch} not found for {spec}!"
raise RuntimeError(msg)
release = releases[-1] release = releases[-1]
version = release["python_version"] version = release["python_version"]
+1 -1
View File
@@ -1,3 +1,3 @@
from __future__ import annotations from __future__ import annotations
__version__ = "2.9.0" __version__ = "2.10.2"
+46 -8
View File
@@ -6,6 +6,7 @@ import shutil
import sys import sys
import tarfile import tarfile
import textwrap import textwrap
import typing
from pathlib import Path from pathlib import Path
from tempfile import mkdtemp from tempfile import mkdtemp
@@ -40,7 +41,7 @@ def main() -> None:
parser.add_argument( parser.add_argument(
"--platform", "--platform",
choices=["auto", "linux", "macos", "windows"], choices=["auto", "linux", "macos", "windows"],
default=os.environ.get("CIBW_PLATFORM", "auto"), default=None,
help=""" help="""
Platform to build for. Use this option to override the Platform to build for. Use this option to override the
auto-detected platform or to run cibuildwheel on your development auto-detected platform or to run cibuildwheel on your development
@@ -64,6 +65,16 @@ def main() -> None:
""", """,
) )
parser.add_argument(
"--only",
default=None,
help="""
Force a single wheel build when given an identifier. Overrides
CIBW_BUILD/CIBW_SKIP. --platform and --arch cannot be specified
if this is given.
""",
)
parser.add_argument( parser.add_argument(
"--output-dir", "--output-dir",
type=Path, type=Path,
@@ -138,7 +149,8 @@ def main() -> None:
try: try:
(project_dir,) = temp_dir.iterdir() (project_dir,) = temp_dir.iterdir()
except ValueError: except ValueError:
raise SystemExit("invalid sdist: didn't contain a single dir") from None msg = "invalid sdist: didn't contain a single dir"
raise SystemExit(msg) from None
# This is now the new package dir # This is now the new package dir
args.package_dir = project_dir.resolve() args.package_dir = project_dir.resolve()
@@ -154,10 +166,40 @@ def main() -> None:
def build_in_directory(args: CommandLineArguments) -> None: def build_in_directory(args: CommandLineArguments) -> None:
platform_option_value = args.platform or os.environ.get("CIBW_PLATFORM", "auto")
platform: PlatformName platform: PlatformName
if args.platform != "auto": if args.only:
platform = args.platform if "linux_" in args.only:
platform = "linux"
elif "macosx_" in args.only:
platform = "macos"
elif "win_" in args.only or "win32" in args.only:
platform = "windows"
else:
print(
f"Invalid --only='{args.only}', must be a build selector with a known platform",
file=sys.stderr,
)
sys.exit(2)
if args.platform is not None:
print(
"--platform cannot be specified with --only, it is computed from --only",
file=sys.stderr,
)
sys.exit(2)
if args.archs is not None:
print(
"--arch cannot be specified with --only, it is computed from --only",
file=sys.stderr,
)
sys.exit(2)
elif platform_option_value != "auto":
if platform_option_value not in PLATFORMS:
print(f"cibuildwheel: Unsupported platform: {platform_option_value}", file=sys.stderr)
sys.exit(2)
platform = typing.cast(PlatformName, platform_option_value)
else: else:
ci_provider = detect_ci_provider() ci_provider = detect_ci_provider()
if ci_provider is None: if ci_provider is None:
@@ -187,10 +229,6 @@ def build_in_directory(args: CommandLineArguments) -> None:
) )
sys.exit(2) sys.exit(2)
if platform not in PLATFORMS:
print(f"cibuildwheel: Unsupported platform: {platform}", file=sys.stderr)
sys.exit(2)
options = compute_options(platform=platform, command_line_arguments=args) options = compute_options(platform=platform, command_line_arguments=args)
package_dir = options.globals.package_dir package_dir = options.globals.package_dir
+33 -3
View File
@@ -3,12 +3,19 @@ from __future__ import annotations
import functools import functools
import platform as platform_module import platform as platform_module
import re import re
import sys
from enum import Enum from enum import Enum
from .typing import Final, Literal, PlatformName, assert_never from .typing import Final, Literal, PlatformName, assert_never
PRETTY_NAMES: Final = {"linux": "Linux", "macos": "macOS", "windows": "Windows"} PRETTY_NAMES: Final = {"linux": "Linux", "macos": "macOS", "windows": "Windows"}
ARCH_SYNONYMS: Final[list[dict[PlatformName, str | None]]] = [
{"linux": "x86_64", "macos": "x86_64", "windows": "AMD64"},
{"linux": "i686", "macos": None, "windows": "x86"},
{"linux": "aarch64", "macos": "arm64", "windows": "ARM64"},
]
@functools.total_ordering @functools.total_ordering
class Architecture(Enum): class Architecture(Enum):
@@ -56,14 +63,37 @@ class Architecture(Enum):
@staticmethod @staticmethod
def auto_archs(platform: PlatformName) -> set[Architecture]: def auto_archs(platform: PlatformName) -> set[Architecture]:
native_architecture = Architecture(platform_module.machine()) native_machine = platform_module.machine()
# Cross-platform support. Used for --print-build-identifiers or docker builds.
host_platform: PlatformName = (
"windows"
if sys.platform.startswith("win")
else ("macos" if sys.platform.startswith("darwin") else "linux")
)
native_architecture = Architecture(native_machine)
# we might need to rename the native arch to the machine we're running
# on, as the same arch can have different names on different platforms
if host_platform != platform:
for arch_synonym in ARCH_SYNONYMS:
if native_machine == arch_synonym.get(host_platform):
synonym = arch_synonym[platform]
if synonym is None:
# can't build anything on this platform
return set()
native_architecture = Architecture(synonym)
result = {native_architecture} result = {native_architecture}
if platform == "linux" and native_architecture == Architecture.x86_64: if platform == "linux" and Architecture.x86_64 in result:
# x86_64 machines can run i686 containers # x86_64 machines can run i686 containers
result.add(Architecture.i686) result.add(Architecture.i686)
if platform == "windows" and native_architecture == Architecture.AMD64: if platform == "windows" and Architecture.AMD64 in result:
result.add(Architecture.x86) result.add(Architecture.x86)
return result return result
+10 -8
View File
@@ -32,7 +32,8 @@ def evaluate(
command_node = bashlex.parsesingle(value) command_node = bashlex.parsesingle(value)
if len(command_node.parts) != 1: if len(command_node.parts) != 1:
raise ValueError(f'"{value}" has too many parts') msg = f"{value!r} has too many parts"
raise ValueError(msg)
value_word_node = command_node.parts[0] value_word_node = command_node.parts[0]
@@ -54,7 +55,8 @@ def evaluate_node(node: bashlex.ast.node, context: NodeExecutionContext) -> str:
elif node.kind == "parameter": elif node.kind == "parameter":
return evaluate_parameter_node(node, context=context) return evaluate_parameter_node(node, context=context)
else: else:
raise ValueError(f'Unsupported bash construct: "{node.kind}"') msg = f"Unsupported bash construct: {node.kind!r}"
raise ValueError(msg)
def evaluate_word_node(node: bashlex.ast.node, context: NodeExecutionContext) -> str: def evaluate_word_node(node: bashlex.ast.node, context: NodeExecutionContext) -> str:
@@ -65,10 +67,8 @@ def evaluate_word_node(node: bashlex.ast.node, context: NodeExecutionContext) ->
part_value = evaluate_node(part, context=context) part_value = evaluate_node(part, context=context)
if part_string not in value: if part_string not in value:
raise RuntimeError( msg = f"bash parse failed. part {part_string!r} not found in {value!r}. Word was {node.word!r}. Full input was {context.input!r}"
f'bash parse failed. part "{part_string}" not found in "{value}". ' raise RuntimeError(msg)
f'Word was "{node.word}". Full input was "{context.input}"'
)
value = value.replace(part_string, part_value, 1) value = value.replace(part_string, part_value, 1)
@@ -95,9 +95,11 @@ def evaluate_nodes_as_compound_command(
result += evaluate_command_node(node, context=context) result += evaluate_command_node(node, context=context)
elif node.kind == "operator": elif node.kind == "operator":
if node.op != ";": if node.op != ";":
raise ValueError(f'Unsupported bash operator: "{node.op}"') msg = f"Unsupported bash operator: {node.op!r}"
raise ValueError(msg)
else: else:
raise ValueError(f'Unsupported bash node in compound command: "{node.kind}"') msg = f"Unsupported bash node in compound command: {node.kind!r}"
raise ValueError(msg)
return result return result
+6 -1
View File
@@ -4,6 +4,7 @@ import dataclasses
from typing import Any, Mapping, Sequence from typing import Any, Mapping, Sequence
import bashlex import bashlex
import bashlex.errors
from cibuildwheel.typing import Protocol from cibuildwheel.typing import Protocol
@@ -33,7 +34,11 @@ def split_env_items(env_string: str) -> list[str]:
if not env_string: if not env_string:
return [] return []
command_node = bashlex.parsesingle(env_string) try:
command_node = bashlex.parsesingle(env_string)
except bashlex.errors.ParsingError as e:
raise EnvironmentParseError(env_string) from e
result = [] result = []
for word_node in command_node.parts: for word_node in command_node.parts:
+4 -7
View File
@@ -21,10 +21,8 @@ class cached_property(Generic[_T]):
if self.attrname is None: if self.attrname is None:
self.attrname = name self.attrname = name
elif name != self.attrname: elif name != self.attrname:
raise TypeError( msg = f"Cannot assign the same cached_property to two different names ({self.attrname!r} and {name!r})."
"Cannot assign the same cached_property to two different names " raise TypeError(msg)
f"({self.attrname!r} and {name!r})."
)
@overload @overload
def __get__(self, instance: None, owner: type[Any] | None = ...) -> cached_property[_T]: def __get__(self, instance: None, owner: type[Any] | None = ...) -> cached_property[_T]:
@@ -38,9 +36,8 @@ class cached_property(Generic[_T]):
if instance is None: if instance is None:
return self return self
if self.attrname is None: if self.attrname is None:
raise TypeError( msg = "Cannot use cached_property instance without calling __set_name__ on it."
"Cannot use cached_property instance without calling __set_name__ on it." raise TypeError(msg)
)
try: try:
cache = instance.__dict__ cache = instance.__dict__
except AttributeError: # not all objects have __dict__ (e.g. class defines slots) except AttributeError: # not all objects have __dict__ (e.g. class defines slots)
+2 -1
View File
@@ -367,7 +367,8 @@ def build(options: Options, tmp_path: Path) -> None: # pylint: disable=unused-a
cwd = Path.cwd() cwd = Path.cwd()
abs_package_dir = options.globals.package_dir.resolve() abs_package_dir = options.globals.package_dir.resolve()
if cwd != abs_package_dir and cwd not in abs_package_dir.parents: if cwd != abs_package_dir and cwd not in abs_package_dir.parents:
raise Exception("package_dir must be inside the working directory") msg = "package_dir must be inside the working directory"
raise Exception(msg)
container_project_path = PurePosixPath("/project") container_project_path = PurePosixPath("/project")
container_package_dir = container_project_path / abs_package_dir.relative_to(cwd) container_package_dir = container_project_path / abs_package_dir.relative_to(cwd)
+4 -2
View File
@@ -204,14 +204,16 @@ def build_description_from_identifier(identifier: str) -> str:
elif python_interpreter == "pp": elif python_interpreter == "pp":
build_description += "PyPy" build_description += "PyPy"
else: else:
raise Exception("unknown python") msg = f"unknown python {python_interpreter!r}"
raise Exception(msg)
build_description += f" {python_version[0]}.{python_version[1:]} " build_description += f" {python_version[0]}.{python_version[1:]} "
try: try:
build_description += PLATFORM_IDENTIFIER_DESCRIPTIONS[platform_identifier] build_description += PLATFORM_IDENTIFIER_DESCRIPTIONS[platform_identifier]
except KeyError as e: except KeyError as e:
raise Exception("unknown platform") from e msg = f"unknown platform {platform_identifier!r}"
raise Exception(msg) from e
return build_description return build_description
+4 -2
View File
@@ -146,7 +146,8 @@ def setup_python(
elif implementation_id.startswith("pp"): elif implementation_id.startswith("pp"):
base_python = install_pypy(tmp, python_configuration.url) base_python = install_pypy(tmp, python_configuration.url)
else: else:
raise ValueError("Unknown Python implementation") msg = "Unknown Python implementation"
raise ValueError(msg)
assert base_python.exists() assert base_python.exists()
log.step("Setting up build environment...") log.step("Setting up build environment...")
@@ -466,7 +467,8 @@ def build(options: Options, tmp_path: Path) -> None:
) )
) )
else: else:
raise RuntimeError("unreachable") msg = "unreachable"
raise RuntimeError(msg)
# skip this test # skip this test
continue continue
+2 -1
View File
@@ -58,7 +58,8 @@ class OCIContainer:
engine: ContainerEngine = "docker", engine: ContainerEngine = "docker",
): ):
if not image: if not image:
raise ValueError("Must have a non-empty image to run.") msg = "Must have a non-empty image to run."
raise ValueError(msg)
self.image = image self.image = image
self.simulate_32_bit = simulate_32_bit self.simulate_32_bit = simulate_32_bit
+38 -20
View File
@@ -10,7 +10,7 @@ from configparser import ConfigParser
from contextlib import contextmanager from contextlib import contextmanager
from dataclasses import asdict, dataclass from dataclasses import asdict, dataclass
from pathlib import Path from pathlib import Path
from typing import Any, Dict, Generator, Iterator, List, Mapping, Union, cast from typing import Any, Callable, Dict, Generator, Iterator, List, Mapping, Union, cast
if sys.version_info >= (3, 11): if sys.version_info >= (3, 11):
import tomllib import tomllib
@@ -23,7 +23,7 @@ from .architecture import Architecture
from .environment import EnvironmentParseError, ParsedEnvironment, parse_environment from .environment import EnvironmentParseError, ParsedEnvironment, parse_environment
from .oci_container import ContainerEngine from .oci_container import ContainerEngine
from .projectfiles import get_requires_python_str from .projectfiles import get_requires_python_str
from .typing import PLATFORMS, Literal, PlatformName, TypedDict from .typing import PLATFORMS, Literal, NotRequired, PlatformName, TypedDict
from .util import ( from .util import (
MANYLINUX_ARCHS, MANYLINUX_ARCHS,
MUSLLINUX_ARCHS, MUSLLINUX_ARCHS,
@@ -42,9 +42,10 @@ from .util import (
@dataclass @dataclass
class CommandLineArguments: class CommandLineArguments:
platform: Literal["auto", "linux", "macos", "windows"] platform: Literal["auto", "linux", "macos", "windows"] | None
archs: str | None archs: str | None
output_dir: Path output_dir: Path
only: str | None
config_file: str config_file: str
package_dir: Path package_dir: Path
print_build_identifiers: bool print_build_identifiers: bool
@@ -122,6 +123,7 @@ DISALLOWED_OPTIONS = {
class TableFmt(TypedDict): class TableFmt(TypedDict):
item: str item: str
sep: str sep: str
quote: NotRequired[Callable[[str], str]]
class ConfigOptionError(KeyError): class ConfigOptionError(KeyError):
@@ -136,7 +138,8 @@ def _dig_first(*pairs: tuple[Mapping[str, Setting], str], ignore_empty: bool = F
_dig_first((dict1, "key1"), (dict2, "key2"), ...) _dig_first((dict1, "key1"), (dict2, "key2"), ...)
""" """
if not pairs: if not pairs:
raise ValueError("pairs cannot be empty") msg = "pairs cannot be empty"
raise ValueError(msg)
for dict_like, key in pairs: for dict_like, key in pairs:
if key in dict_like: if key in dict_like:
@@ -206,13 +209,15 @@ class OptionsReader:
if config_overrides is not None: if config_overrides is not None:
if not isinstance(config_overrides, list): if not isinstance(config_overrides, list):
raise ConfigOptionError("'tool.cibuildwheel.overrides' must be a list") msg = "'tool.cibuildwheel.overrides' must be a list"
raise ConfigOptionError(msg)
for config_override in config_overrides: for config_override in config_overrides:
select = config_override.pop("select", None) select = config_override.pop("select", None)
if not select: if not select:
raise ConfigOptionError("'select' must be set in an override") msg = "'select' must be set in an override"
raise ConfigOptionError(msg)
if isinstance(select, list): if isinstance(select, list):
select = " ".join(select) select = " ".join(select)
@@ -326,14 +331,16 @@ class OptionsReader:
if isinstance(result, dict): if isinstance(result, dict):
if table is None: if table is None:
raise ConfigOptionError(f"{name!r} does not accept a table") msg = f"{name!r} does not accept a table"
raise ConfigOptionError(msg)
return table["sep"].join( return table["sep"].join(
item for k, v in result.items() for item in _inner_fmt(k, v, table["item"]) item for k, v in result.items() for item in _inner_fmt(k, v, table)
) )
if isinstance(result, list): if isinstance(result, list):
if sep is None: if sep is None:
raise ConfigOptionError(f"{name!r} does not accept a list") msg = f"{name!r} does not accept a list"
raise ConfigOptionError(msg)
return sep.join(result) return sep.join(result)
if isinstance(result, int): if isinstance(result, int):
@@ -342,14 +349,16 @@ class OptionsReader:
return result return result
def _inner_fmt(k: str, v: Any, table_item: str) -> Iterator[str]: def _inner_fmt(k: str, v: Any, table: TableFmt) -> Iterator[str]:
quote_function = table.get("quote", lambda a: a)
if isinstance(v, list): if isinstance(v, list):
for inner_v in v: for inner_v in v:
qv = shlex.quote(inner_v) qv = quote_function(inner_v)
yield table_item.format(k=k, v=qv) yield table["item"].format(k=k, v=qv)
else: else:
qv = shlex.quote(v) qv = quote_function(v)
yield table_item.format(k=k, v=qv) yield table["item"].format(k=k, v=qv)
class Options: class Options:
@@ -403,6 +412,15 @@ class Options:
) )
requires_python = None if requires_python_str is None else SpecifierSet(requires_python_str) requires_python = None if requires_python_str is None else SpecifierSet(requires_python_str)
archs_config_str = args.archs or self.reader.get("archs", sep=" ")
architectures = Architecture.parse_config(archs_config_str, platform=self.platform)
# Process `--only`
if args.only:
build_config = args.only
skip_config = ""
architectures = Architecture.all_archs(self.platform)
build_selector = BuildSelector( build_selector = BuildSelector(
build_config=build_config, build_config=build_config,
skip_config=skip_config, skip_config=skip_config,
@@ -411,9 +429,6 @@ class Options:
) )
test_selector = TestSelector(skip_config=test_skip) test_selector = TestSelector(skip_config=test_skip)
archs_config_str = args.archs or self.reader.get("archs", sep=" ")
architectures = Architecture.parse_config(archs_config_str, platform=self.platform)
container_engine_str = self.reader.get("container-engine") container_engine_str = self.reader.get("container-engine")
if container_engine_str not in ["docker", "podman"]: if container_engine_str not in ["docker", "podman"]:
@@ -442,13 +457,13 @@ class Options:
build_frontend_str = self.reader.get("build-frontend", env_plat=False) build_frontend_str = self.reader.get("build-frontend", env_plat=False)
environment_config = self.reader.get( environment_config = self.reader.get(
"environment", table={"item": "{k}={v}", "sep": " "} "environment", table={"item": '{k}="{v}"', "sep": " "}
) )
environment_pass = self.reader.get("environment-pass", sep=" ").split() environment_pass = self.reader.get("environment-pass", sep=" ").split()
before_build = self.reader.get("before-build", sep=" && ") before_build = self.reader.get("before-build", sep=" && ")
repair_command = self.reader.get("repair-wheel-command", sep=" && ") repair_command = self.reader.get("repair-wheel-command", sep=" && ")
config_settings = self.reader.get( config_settings = self.reader.get(
"config-settings", table={"item": "{k}={v}", "sep": " "} "config-settings", table={"item": "{k}={v}", "sep": " ", "quote": shlex.quote}
) )
dependency_versions = self.reader.get("dependency-versions") dependency_versions = self.reader.get("dependency-versions")
@@ -588,6 +603,9 @@ class Options:
] ]
build_option_defaults = self.build_options(identifier=None) build_option_defaults = self.build_options(identifier=None)
build_options_for_identifier = {
identifier: self.build_options(identifier) for identifier in identifiers
}
for option_name, default_value in sorted(asdict(build_option_defaults).items()): for option_name, default_value in sorted(asdict(build_option_defaults).items()):
if option_name == "globals": if option_name == "globals":
@@ -597,7 +615,7 @@ class Options:
# if any identifiers have an overridden value, print that too # if any identifiers have an overridden value, print that too
for identifier in identifiers: for identifier in identifiers:
option_value = getattr(self.build_options(identifier=identifier), option_name) option_value = getattr(build_options_for_identifier[identifier], option_name)
if option_value != default_value: if option_value != default_value:
lines.append(f" {identifier}: {option_value!r}") lines.append(f" {identifier}: {option_value!r}")
+12 -12
View File
@@ -81,12 +81,12 @@ python_configurations = [
{ identifier = "cp39-macosx_x86_64", version = "3.9", url = "https://www.python.org/ftp/python/3.9.13/python-3.9.13-macos11.pkg" }, { identifier = "cp39-macosx_x86_64", version = "3.9", url = "https://www.python.org/ftp/python/3.9.13/python-3.9.13-macos11.pkg" },
{ identifier = "cp39-macosx_arm64", version = "3.9", url = "https://www.python.org/ftp/python/3.9.13/python-3.9.13-macos11.pkg" }, { identifier = "cp39-macosx_arm64", version = "3.9", url = "https://www.python.org/ftp/python/3.9.13/python-3.9.13-macos11.pkg" },
{ identifier = "cp39-macosx_universal2", version = "3.9", url = "https://www.python.org/ftp/python/3.9.13/python-3.9.13-macos11.pkg" }, { identifier = "cp39-macosx_universal2", version = "3.9", url = "https://www.python.org/ftp/python/3.9.13/python-3.9.13-macos11.pkg" },
{ identifier = "cp310-macosx_x86_64", version = "3.10", url = "https://www.python.org/ftp/python/3.10.6/python-3.10.6-macos11.pkg" }, { identifier = "cp310-macosx_x86_64", version = "3.10", url = "https://www.python.org/ftp/python/3.10.7/python-3.10.7-macos11.pkg" },
{ identifier = "cp310-macosx_arm64", version = "3.10", url = "https://www.python.org/ftp/python/3.10.6/python-3.10.6-macos11.pkg" }, { identifier = "cp310-macosx_arm64", version = "3.10", url = "https://www.python.org/ftp/python/3.10.7/python-3.10.7-macos11.pkg" },
{ identifier = "cp310-macosx_universal2", version = "3.10", url = "https://www.python.org/ftp/python/3.10.6/python-3.10.6-macos11.pkg" }, { identifier = "cp310-macosx_universal2", version = "3.10", url = "https://www.python.org/ftp/python/3.10.7/python-3.10.7-macos11.pkg" },
{ identifier = "cp311-macosx_x86_64", version = "3.11", url = "https://www.python.org/ftp/python/3.11.0/python-3.11.0rc1-macos11.pkg" }, { identifier = "cp311-macosx_x86_64", version = "3.11", url = "https://www.python.org/ftp/python/3.11.0/python-3.11.0rc2-macos11.pkg" },
{ identifier = "cp311-macosx_arm64", version = "3.11", url = "https://www.python.org/ftp/python/3.11.0/python-3.11.0rc1-macos11.pkg" }, { identifier = "cp311-macosx_arm64", version = "3.11", url = "https://www.python.org/ftp/python/3.11.0/python-3.11.0rc2-macos11.pkg" },
{ identifier = "cp311-macosx_universal2", version = "3.11", url = "https://www.python.org/ftp/python/3.11.0/python-3.11.0rc1-macos11.pkg" }, { identifier = "cp311-macosx_universal2", version = "3.11", url = "https://www.python.org/ftp/python/3.11.0/python-3.11.0rc2-macos11.pkg" },
{ identifier = "pp37-macosx_x86_64", version = "3.7", url = "https://downloads.python.org/pypy/pypy3.7-v7.3.9-osx64.tar.bz2" }, { identifier = "pp37-macosx_x86_64", version = "3.7", url = "https://downloads.python.org/pypy/pypy3.7-v7.3.9-osx64.tar.bz2" },
{ identifier = "pp38-macosx_x86_64", version = "3.8", url = "https://downloads.python.org/pypy/pypy3.8-v7.3.9-osx64.tar.bz2" }, { identifier = "pp38-macosx_x86_64", version = "3.8", url = "https://downloads.python.org/pypy/pypy3.8-v7.3.9-osx64.tar.bz2" },
{ identifier = "pp39-macosx_x86_64", version = "3.9", url = "https://downloads.python.org/pypy/pypy3.9-v7.3.9-osx64.tar.bz2" }, { identifier = "pp39-macosx_x86_64", version = "3.9", url = "https://downloads.python.org/pypy/pypy3.9-v7.3.9-osx64.tar.bz2" },
@@ -102,13 +102,13 @@ python_configurations = [
{ identifier = "cp38-win_amd64", version = "3.8.10", arch = "64" }, { identifier = "cp38-win_amd64", version = "3.8.10", arch = "64" },
{ identifier = "cp39-win32", version = "3.9.13", arch = "32" }, { identifier = "cp39-win32", version = "3.9.13", arch = "32" },
{ identifier = "cp39-win_amd64", version = "3.9.13", arch = "64" }, { identifier = "cp39-win_amd64", version = "3.9.13", arch = "64" },
{ identifier = "cp310-win32", version = "3.10.6", arch = "32" }, { identifier = "cp310-win32", version = "3.10.7", arch = "32" },
{ identifier = "cp310-win_amd64", version = "3.10.6", arch = "64" }, { identifier = "cp310-win_amd64", version = "3.10.7", arch = "64" },
{ identifier = "cp311-win32", version = "3.11.0-rc1", arch = "32" }, { identifier = "cp311-win32", version = "3.11.0-rc2", arch = "32" },
{ identifier = "cp311-win_amd64", version = "3.11.0-rc1", arch = "64" }, { identifier = "cp311-win_amd64", version = "3.11.0-rc2", arch = "64" },
{ identifier = "cp39-win_arm64", version = "3.9.10", arch = "ARM64" }, { identifier = "cp39-win_arm64", version = "3.9.10", arch = "ARM64" },
{ identifier = "cp310-win_arm64", version = "3.10.6", arch = "ARM64" }, { identifier = "cp310-win_arm64", version = "3.10.7", arch = "ARM64" },
{ identifier = "cp311-win_arm64", version = "3.11.0-rc1", arch = "ARM64" }, { identifier = "cp311-win_arm64", version = "3.11.0-rc2", arch = "ARM64" },
{ identifier = "pp37-win_amd64", version = "3.7", arch = "64", url = "https://downloads.python.org/pypy/pypy3.7-v7.3.9-win64.zip" }, { identifier = "pp37-win_amd64", version = "3.7", arch = "64", url = "https://downloads.python.org/pypy/pypy3.7-v7.3.9-win64.zip" },
{ identifier = "pp38-win_amd64", version = "3.8", arch = "64", url = "https://downloads.python.org/pypy/pypy3.8-v7.3.9-win64.zip" }, { identifier = "pp38-win_amd64", version = "3.8", arch = "64", url = "https://downloads.python.org/pypy/pypy3.8-v7.3.9-win64.zip" },
{ identifier = "pp39-win_amd64", version = "3.9", arch = "64", url = "https://downloads.python.org/pypy/pypy3.9-v7.3.9-win64.zip" }, { identifier = "pp39-win_amd64", version = "3.9", arch = "64", url = "https://downloads.python.org/pypy/pypy3.9-v7.3.9-win64.zip" },
@@ -14,7 +14,7 @@ platformdirs==2.5.2
# via virtualenv # via virtualenv
typing-extensions==4.3.0 typing-extensions==4.3.0
# via delocate # via delocate
virtualenv==20.16.4 virtualenv==20.16.5
# via -r cibuildwheel/resources/constraints.in # via -r cibuildwheel/resources/constraints.in
wheel==0.37.1 wheel==0.37.1
# via # via
@@ -14,7 +14,7 @@ platformdirs==2.5.2
# via virtualenv # via virtualenv
typing-extensions==4.3.0 typing-extensions==4.3.0
# via delocate # via delocate
virtualenv==20.16.4 virtualenv==20.16.5
# via -r cibuildwheel/resources/constraints.in # via -r cibuildwheel/resources/constraints.in
wheel==0.37.1 wheel==0.37.1
# via # via
@@ -20,7 +20,7 @@ typing-extensions==4.1.1
# via # via
# delocate # delocate
# importlib-metadata # importlib-metadata
virtualenv==20.16.4 virtualenv==20.16.5
# via -r cibuildwheel/resources/constraints.in # via -r cibuildwheel/resources/constraints.in
wheel==0.37.1 wheel==0.37.1
# via # via
@@ -18,7 +18,7 @@ typing-extensions==4.3.0
# via # via
# delocate # delocate
# importlib-metadata # importlib-metadata
virtualenv==20.16.4 virtualenv==20.16.5
# via -r cibuildwheel/resources/constraints.in # via -r cibuildwheel/resources/constraints.in
wheel==0.37.1 wheel==0.37.1
# via # via
@@ -14,7 +14,7 @@ platformdirs==2.5.2
# via virtualenv # via virtualenv
typing-extensions==4.3.0 typing-extensions==4.3.0
# via delocate # via delocate
virtualenv==20.16.4 virtualenv==20.16.5
# via -r cibuildwheel/resources/constraints.in # via -r cibuildwheel/resources/constraints.in
wheel==0.37.1 wheel==0.37.1
# via # via
@@ -14,7 +14,7 @@ platformdirs==2.5.2
# via virtualenv # via virtualenv
typing-extensions==4.3.0 typing-extensions==4.3.0
# via delocate # via delocate
virtualenv==20.16.4 virtualenv==20.16.5
# via -r cibuildwheel/resources/constraints.in # via -r cibuildwheel/resources/constraints.in
wheel==0.37.1 wheel==0.37.1
# via # via
+1 -1
View File
@@ -14,7 +14,7 @@ platformdirs==2.5.2
# via virtualenv # via virtualenv
typing-extensions==4.3.0 typing-extensions==4.3.0
# via delocate # via delocate
virtualenv==20.16.4 virtualenv==20.16.5
# via -r cibuildwheel/resources/constraints.in # via -r cibuildwheel/resources/constraints.in
wheel==0.37.1 wheel==0.37.1
# via # via
+29 -29
View File
@@ -1,49 +1,49 @@
[x86_64] [x86_64]
manylinux1 = quay.io/pypa/manylinux1_x86_64:2022-09-04-d1c2903 manylinux1 = quay.io/pypa/manylinux1_x86_64:2022-09-18-e2e56b7
manylinux2010 = quay.io/pypa/manylinux2010_x86_64:2022-08-05-4535177 manylinux2010 = quay.io/pypa/manylinux2010_x86_64:2022-08-05-4535177
manylinux2014 = quay.io/pypa/manylinux2014_x86_64:2022-09-04-870f6a2 manylinux2014 = quay.io/pypa/manylinux2014_x86_64:2022-09-18-2b8b451
manylinux_2_24 = quay.io/pypa/manylinux_2_24_x86_64:2022-09-04-870f6a2 manylinux_2_24 = quay.io/pypa/manylinux_2_24_x86_64:2022-09-18-2b8b451
manylinux_2_28 = quay.io/pypa/manylinux_2_28_x86_64:2022-09-04-870f6a2 manylinux_2_28 = quay.io/pypa/manylinux_2_28_x86_64:2022-09-18-2b8b451
musllinux_1_1 = quay.io/pypa/musllinux_1_1_x86_64:2022-09-04-870f6a2 musllinux_1_1 = quay.io/pypa/musllinux_1_1_x86_64:2022-09-18-2b8b451
[i686] [i686]
manylinux1 = quay.io/pypa/manylinux1_i686:2022-09-04-d1c2903 manylinux1 = quay.io/pypa/manylinux1_i686:2022-09-18-e2e56b7
manylinux2010 = quay.io/pypa/manylinux2010_i686:2022-08-05-4535177 manylinux2010 = quay.io/pypa/manylinux2010_i686:2022-08-05-4535177
manylinux2014 = quay.io/pypa/manylinux2014_i686:2022-09-04-870f6a2 manylinux2014 = quay.io/pypa/manylinux2014_i686:2022-09-18-2b8b451
manylinux_2_24 = quay.io/pypa/manylinux_2_24_i686:2022-09-04-870f6a2 manylinux_2_24 = quay.io/pypa/manylinux_2_24_i686:2022-09-18-2b8b451
musllinux_1_1 = quay.io/pypa/musllinux_1_1_i686:2022-09-04-870f6a2 musllinux_1_1 = quay.io/pypa/musllinux_1_1_i686:2022-09-18-2b8b451
[pypy_x86_64] [pypy_x86_64]
manylinux2010 = quay.io/pypa/manylinux2010_x86_64:2022-08-05-4535177 manylinux2010 = quay.io/pypa/manylinux2010_x86_64:2022-08-05-4535177
manylinux2014 = quay.io/pypa/manylinux2014_x86_64:2022-09-04-870f6a2 manylinux2014 = quay.io/pypa/manylinux2014_x86_64:2022-09-18-2b8b451
manylinux_2_24 = quay.io/pypa/manylinux_2_24_x86_64:2022-09-04-870f6a2 manylinux_2_24 = quay.io/pypa/manylinux_2_24_x86_64:2022-09-18-2b8b451
manylinux_2_28 = quay.io/pypa/manylinux_2_28_x86_64:2022-09-04-870f6a2 manylinux_2_28 = quay.io/pypa/manylinux_2_28_x86_64:2022-09-18-2b8b451
[pypy_i686] [pypy_i686]
manylinux2010 = quay.io/pypa/manylinux2010_i686:2022-08-05-4535177 manylinux2010 = quay.io/pypa/manylinux2010_i686:2022-08-05-4535177
manylinux2014 = quay.io/pypa/manylinux2014_i686:2022-09-04-870f6a2 manylinux2014 = quay.io/pypa/manylinux2014_i686:2022-09-18-2b8b451
manylinux_2_24 = quay.io/pypa/manylinux_2_24_i686:2022-09-04-870f6a2 manylinux_2_24 = quay.io/pypa/manylinux_2_24_i686:2022-09-18-2b8b451
[aarch64] [aarch64]
manylinux2014 = quay.io/pypa/manylinux2014_aarch64:2022-09-04-870f6a2 manylinux2014 = quay.io/pypa/manylinux2014_aarch64:2022-09-18-2b8b451
manylinux_2_24 = quay.io/pypa/manylinux_2_24_aarch64:2022-09-04-870f6a2 manylinux_2_24 = quay.io/pypa/manylinux_2_24_aarch64:2022-09-18-2b8b451
manylinux_2_28 = quay.io/pypa/manylinux_2_28_aarch64:2022-09-04-870f6a2 manylinux_2_28 = quay.io/pypa/manylinux_2_28_aarch64:2022-09-18-2b8b451
musllinux_1_1 = quay.io/pypa/musllinux_1_1_aarch64:2022-09-04-870f6a2 musllinux_1_1 = quay.io/pypa/musllinux_1_1_aarch64:2022-09-18-2b8b451
[ppc64le] [ppc64le]
manylinux2014 = quay.io/pypa/manylinux2014_ppc64le:2022-09-04-870f6a2 manylinux2014 = quay.io/pypa/manylinux2014_ppc64le:2022-09-18-2b8b451
manylinux_2_24 = quay.io/pypa/manylinux_2_24_ppc64le:2022-09-04-870f6a2 manylinux_2_24 = quay.io/pypa/manylinux_2_24_ppc64le:2022-09-18-2b8b451
manylinux_2_28 = quay.io/pypa/manylinux_2_28_ppc64le:2022-09-04-870f6a2 manylinux_2_28 = quay.io/pypa/manylinux_2_28_ppc64le:2022-09-18-2b8b451
musllinux_1_1 = quay.io/pypa/musllinux_1_1_ppc64le:2022-09-04-870f6a2 musllinux_1_1 = quay.io/pypa/musllinux_1_1_ppc64le:2022-09-18-2b8b451
[s390x] [s390x]
manylinux2014 = quay.io/pypa/manylinux2014_s390x:2022-09-04-870f6a2 manylinux2014 = quay.io/pypa/manylinux2014_s390x:2022-09-18-2b8b451
manylinux_2_24 = quay.io/pypa/manylinux_2_24_s390x:2022-09-04-870f6a2 manylinux_2_24 = quay.io/pypa/manylinux_2_24_s390x:2022-09-18-2b8b451
manylinux_2_28 = quay.io/pypa/manylinux_2_28_s390x:2022-09-04-870f6a2 manylinux_2_28 = quay.io/pypa/manylinux_2_28_s390x:2022-09-18-2b8b451
musllinux_1_1 = quay.io/pypa/musllinux_1_1_s390x:2022-09-04-870f6a2 musllinux_1_1 = quay.io/pypa/musllinux_1_1_s390x:2022-09-18-2b8b451
[pypy_aarch64] [pypy_aarch64]
manylinux2014 = quay.io/pypa/manylinux2014_aarch64:2022-09-04-870f6a2 manylinux2014 = quay.io/pypa/manylinux2014_aarch64:2022-09-18-2b8b451
manylinux_2_24 = quay.io/pypa/manylinux_2_24_aarch64:2022-09-04-870f6a2 manylinux_2_24 = quay.io/pypa/manylinux_2_24_aarch64:2022-09-18-2b8b451
manylinux_2_28 = quay.io/pypa/manylinux_2_28_aarch64:2022-09-04-870f6a2 manylinux_2_28 = quay.io/pypa/manylinux_2_28_aarch64:2022-09-18-2b8b451
+2 -2
View File
@@ -1,2 +1,2 @@
version = "20.16.4" version = "20.16.5"
url = "https://github.com/pypa/get-virtualenv/blob/20.16.4/public/virtualenv.pyz?raw=true" url = "https://github.com/pypa/get-virtualenv/blob/20.16.5/public/virtualenv.pyz?raw=true"
+5
View File
@@ -10,6 +10,10 @@ if sys.version_info < (3, 8):
else: else:
from typing import Final, Literal, OrderedDict, Protocol, TypedDict from typing import Final, Literal, OrderedDict, Protocol, TypedDict
if sys.version_info < (3, 11):
from typing_extensions import NotRequired
else:
from typing import NotRequired
__all__ = ( __all__ = (
"Final", "Final",
@@ -26,6 +30,7 @@ __all__ = (
"OrderedDict", "OrderedDict",
"Union", "Union",
"assert_never", "assert_never",
"NotRequired",
) )
+11 -11
View File
@@ -63,13 +63,13 @@ __all__ = [
"split_config_settings", "split_config_settings",
] ]
resources_dir: Final = Path(__file__).parent / "resources" resources_dir: Final[Path] = Path(__file__).parent / "resources"
install_certifi_script: Final = resources_dir / "install_certifi.py" install_certifi_script: Final[Path] = resources_dir / "install_certifi.py"
BuildFrontend = Literal["pip", "build"] BuildFrontend = Literal["pip", "build"]
MANYLINUX_ARCHS: Final = ( MANYLINUX_ARCHS: Final[tuple[str, ...]] = (
"x86_64", "x86_64",
"i686", "i686",
"pypy_x86_64", "pypy_x86_64",
@@ -80,7 +80,7 @@ MANYLINUX_ARCHS: Final = (
"pypy_i686", "pypy_i686",
) )
MUSLLINUX_ARCHS: Final = ( MUSLLINUX_ARCHS: Final[tuple[str, ...]] = (
"x86_64", "x86_64",
"i686", "i686",
"aarch64", "aarch64",
@@ -88,10 +88,12 @@ MUSLLINUX_ARCHS: Final = (
"s390x", "s390x",
) )
DEFAULT_CIBW_CACHE_PATH: Final = user_cache_path(appname="cibuildwheel", appauthor="pypa") DEFAULT_CIBW_CACHE_PATH: Final[Path] = user_cache_path(appname="cibuildwheel", appauthor="pypa")
CIBW_CACHE_PATH: Final = Path(os.environ.get("CIBW_CACHE_PATH", DEFAULT_CIBW_CACHE_PATH)).resolve() CIBW_CACHE_PATH: Final[Path] = Path(
os.environ.get("CIBW_CACHE_PATH", DEFAULT_CIBW_CACHE_PATH)
).resolve()
IS_WIN: Final = sys.platform.startswith("win") IS_WIN: Final[bool] = sys.platform.startswith("win")
@overload @overload
@@ -145,7 +147,7 @@ def shell(*commands: str, env: dict[str, str] | None = None, cwd: PathOrStr | No
subprocess.run(command, env=env, cwd=cwd, shell=True, check=True) subprocess.run(command, env=env, cwd=cwd, shell=True, check=True)
def format_safe(template: str, **kwargs: Any) -> str: def format_safe(template: str, **kwargs: str | os.PathLike[str]) -> str:
""" """
Works similarly to `template.format(**kwargs)`, except that unmatched Works similarly to `template.format(**kwargs)`, except that unmatched
fields in `template` are passed through untouched. fields in `template` are passed through untouched.
@@ -173,11 +175,9 @@ def format_safe(template: str, **kwargs: Any) -> str:
re.VERBOSE, re.VERBOSE,
) )
# we use a function for repl to prevent re.sub interpreting backslashes
# in repl as escape sequences.
result = re.sub( result = re.sub(
pattern=find_pattern, pattern=find_pattern,
repl=lambda _: str(value), # pylint: disable=cell-var-from-loop repl=str(value).replace("\\", r"\\"),
string=result, string=result,
) )
+2 -1
View File
@@ -235,7 +235,8 @@ def setup_python(
assert python_configuration.url is not None assert python_configuration.url is not None
base_python = install_pypy(tmp, python_configuration.arch, python_configuration.url) base_python = install_pypy(tmp, python_configuration.arch, python_configuration.url)
else: else:
raise ValueError("Unknown Python implementation") msg = "Unknown Python implementation"
raise ValueError(msg)
assert base_python.exists() assert base_python.exists()
log.step("Setting up build environment...") log.step("Setting up build environment...")
+41 -2
View File
@@ -4,6 +4,32 @@ title: Changelog
# Changelog # Changelog
### v2.10.2
_25 September 2022_
- 🐛 Fix a bug that caused `win32` identifiers to fail when used with `--only`. (#1282)
- 🐛 Fix computation of `auto`/`auto64`/`auto32` archs when targeting a different platform to the one that you're running cibuildwheel on. (#1266)
- 📚 Fix an mistake in the 'how it works' diagram. (#1274)
### v2.10.1
_18 September 2022_
- 🐛 Fix a bug that stopped environment variables specified in TOML from being expanded. (#1273)
### v2.10.0
_13 September 2022_
- 🌟 Adds support for [building wheels on Cirrus CI](https://cibuildwheel.readthedocs.io/en/stable/setup/#cirrus-ci). This is exciting for us, as it's the first public CI platform that natively supports macOS Apple Silicon (aka. M1, `arm64`) runners. As such, it's the first platform that you can natively build _and test_ macOS `arm64` wheels. It also has native Linux ARM (aarch64) runners, for fast, native builds there. (#1191)
- 🌟 Adds support for running cibuildwheel on Apple Silicon machines. For a while, we've supported cross-compilation of Apple Silicon wheels on `x86_64`, but now that we have Cirrus CI we can run our test suite and officially support running cibuildwheel on `arm64`. (#1191)
- ✨ Adds the `--only` [command line option](https://cibuildwheel.readthedocs.io/en/stable/options/#command-line), to specify a single build to run. Previously, it could be cumbersome to set all the build selection options to target a specific build - for example, you might have to run something like `CIBW_BUILD=cp39-manylinux_x86_64 cibuildwheel --platform linux --archs x86_64`. The new `--only` option overrides all the build selection options to simplify running a single build, which now looks like `cibuildwheel --only cp39-manylinux_x86_64`. (#1098)
- ✨ Adds the [`CIBW_CONFIG_SETTINGS`](https://cibuildwheel.readthedocs.io/en/stable/options/#config-settings) option, so you can pass arguments to your package's build backend (#1244)
- 🛠 Updates the CPython 3.11 version to the latest release candidate - v3.11.0rc2. (#1265)
- 🐛 Fix a bug that can cause a RecursionError on Windows when building from an sdist. (#1253)
- 🛠 Add support for the s390x architecture on manylinux_2_28 (#1255)
### v2.9.0 ### v2.9.0
_11 August 2022_ _11 August 2022_
@@ -29,9 +55,10 @@ _5 July 2022_
- ✨ You can now run cibuildwheel on Podman, as an alternate container engine to Docker (which remains the default). This is useful in environments where a Docker daemon isn't available, for example, it can be run inside a Docker container, or without root access. To use Podman, set the [`CIBW_CONTAINER_ENGINE`](https://cibuildwheel.readthedocs.io/en/stable/options/#container-engine) option. (#966) - ✨ You can now run cibuildwheel on Podman, as an alternate container engine to Docker (which remains the default). This is useful in environments where a Docker daemon isn't available, for example, it can be run inside a Docker container, or without root access. To use Podman, set the [`CIBW_CONTAINER_ENGINE`](https://cibuildwheel.readthedocs.io/en/stable/options/#container-engine) option. (#966)
- ✨ Adds support for building `py3-none-{platform}` wheels. This works the same as ABI3 - wheels won't be rebuilt, but tests will still be run across all selected versions of Python. - ✨ Adds support for building `py3-none-{platform}` wheels. This works the same as ABI3 - wheels won't be rebuilt, but tests will still be run across all selected versions of Python.
> These wheels contain native extension code, but don't use the Python APIs. Typically, they're bridged to Python using a FFI module like [ctypes](https://docs.python.org/3/library/ctypes.html) or [cffi](https://cffi.readthedocs.io/en/latest/). Because they don't use Python ABI, the wheels are more compatible - they work across many Python versions. These wheels contain native extension code, but don't use the Python APIs. Typically, they're bridged to Python using a FFI module like [ctypes](https://docs.python.org/3/library/ctypes.html) or [cffi](https://cffi.readthedocs.io/en/latest/). Because they don't use Python ABI, the wheels are more compatible - they work across many Python versions.
Check out this [example ctypes project](https://github.com/joerick/python-ctypes-package-sample) to see an example of how it works. (#1151)
Check out this [example ctypes project](https://github.com/joerick/python-ctypes-package-sample) to see an example of how it works. (#1151)
- 🛠 cibuildwheel will now error if multiple builds in a single run produce the same wheel filename, as this indicates a misconfiguration. (#1152) - 🛠 cibuildwheel will now error if multiple builds in a single run produce the same wheel filename, as this indicates a misconfiguration. (#1152)
- 📚 A few docs improvements and updates to keep things up-to-date. - 📚 A few docs improvements and updates to keep things up-to-date.
@@ -716,6 +743,18 @@ _31 March 2017_
- 🌟 First public release! - 🌟 First public release!
<style>
/* improve list formatting to help separate items */
.rst-content li {
margin-bottom: 12px;
}
.rst-content .section ol li>p:only-child, .rst-content .section ol li>p:only-child:last-child, .rst-content .section ul li>p:only-child, .rst-content .section ul li>p:only-child:last-child, .rst-content .toctree-wrapper ol li>p:only-child, .rst-content .toctree-wrapper ol li>p:only-child:last-child, .rst-content .toctree-wrapper ul li>p:only-child, .rst-content .toctree-wrapper ul li>p:only-child:last-child, .rst-content section ol li>p:only-child, .rst-content section ol li>p:only-child:last-child, .rst-content section ul li>p:only-child, .rst-content section ul li>p:only-child:last-child {
margin-bottom: 12px
}
</style>
<script> <script>
// undo the scrollTop that the theme did on this page, as there are loads // undo the scrollTop that the theme did on this page, as there are loads
// of toc entries and it's disorientating. // of toc entries and it's disorientating.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 67 KiB

+3 -3
View File
@@ -29,7 +29,7 @@
</div> </div>
<div class="grid-column-label" <div class="grid-column-label"
style="grid-row: 2 / span 1; style="grid-row: 2 / span 1;
grid-column: 8 / -3; grid-column: 9 / -3;
margin-bottom: 0.5em;"> margin-bottom: 0.5em;">
<div class="label">If tests are configured</div> <div class="label">If tests are configured</div>
</div> </div>
@@ -382,7 +382,7 @@
} }
.grid-column-label .label { .grid-column-label .label {
background: #fcfcfc; background: #fcfcfc;
padding: 0 2em; padding: 0 1em;
position: relative; position: relative;
} }
.grid-row-label { .grid-row-label {
@@ -420,7 +420,7 @@
grid-column: 3 / -2; grid-column: 3 / -2;
} }
.grid-outline.testVenv { .grid-outline.testVenv {
grid-column: 8 / span 4; grid-column: 9 / span 3;
} }
.grid-outline .outline { .grid-outline .outline {
position: absolute; position: absolute;
+2 -2
View File
@@ -142,7 +142,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: If you use GitHub Actions for builds, you can use cibuildwheel as an action:
```yaml ```yaml
uses: pypa/cibuildwheel@v2.9.0 uses: pypa/cibuildwheel@v2.10.2
``` ```
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. 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.
@@ -164,7 +164,7 @@ The second option, and the only one that supports other CI systems, is using a `
```bash ```bash
# requirements-cibw.txt # requirements-cibw.txt
cibuildwheel==2.9.0 cibuildwheel==2.10.2
``` ```
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: 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:
+5 -1
View File
@@ -113,7 +113,7 @@ The complete set of defaults for the current version of cibuildwheel are shown b
!!! tip !!! tip
Static configuration works across all CI systems, and can be used locally if Static configuration works across all CI systems, and can be used locally if
you run `cibuildwheel --plat linux`. This is preferred, but environment you run `cibuildwheel --platform linux`. This is preferred, but environment
variables are better if you need to change per-matrix element variables are better if you need to change per-matrix element
(`CIBW_BUILD` is often in this category, for example), or if you cannot or do (`CIBW_BUILD` is often in this category, for example), or if you cannot or do
not want to change a `pyproject.toml` file. You can specify a different file to not want to change a `pyproject.toml` file. You can specify a different file to
@@ -202,6 +202,10 @@ This option can also be set using the [command-line option](#command-line) `--pl
This is even more convenient if you store your cibuildwheel config in [`pyproject.toml`](#configuration-file). This is even more convenient if you store your cibuildwheel config in [`pyproject.toml`](#configuration-file).
You can also run a single identifier with `--only <identifier>`. This will
not require `--platform` or `--arch`, and will override any build/skip
configuration.
### `CIBW_BUILD`, `CIBW_SKIP` {: #build-skip} ### `CIBW_BUILD`, `CIBW_SKIP` {: #build-skip}
> Choose the Python versions to build > Choose the Python versions to build
+3 -3
View File
@@ -184,7 +184,7 @@ To build Linux, Mac, and Windows wheels using GitHub Actions, create a `.github/
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Build wheels - name: Build wheels
run: pipx run cibuildwheel==2.9.0 run: pipx run cibuildwheel==2.10.2
- uses: actions/upload-artifact@v3 - uses: actions/upload-artifact@v3
with: with:
@@ -219,7 +219,7 @@ To build Linux, Mac, and Windows wheels using GitHub Actions, create a `.github/
- uses: actions/setup-python@v3 - uses: actions/setup-python@v3
- name: Install cibuildwheel - name: Install cibuildwheel
run: python -m pip install cibuildwheel==2.9.0 run: python -m pip install cibuildwheel==2.10.2
- name: Build wheels - name: Build wheels
run: python -m cibuildwheel --output-dir wheelhouse run: python -m cibuildwheel --output-dir wheelhouse
@@ -314,7 +314,7 @@ Commit this file, and push to Gitlab. The pipeline should start automatically.
Gitlab will store the built wheels for you - you can access them from the Pipelines view. Check out the Gitlab [docs](https://docs.gitlab.com/ee/ci/yaml/) for more info on this config file. Gitlab will store the built wheels for you - you can access them from the Pipelines view. Check out the Gitlab [docs](https://docs.gitlab.com/ee/ci/yaml/) for more info on this config file.
## Cirrus CI [linux/mac/windows] {: #cirrus-ci} ### Cirrus CI [linux/mac/windows] {: #cirrus-ci}
To build Linux, Mac, and Windows wheels on Cirrus CI, create a `.cirrus.yml` file in your repo, To build Linux, Mac, and Windows wheels on Cirrus CI, create a `.cirrus.yml` file in your repo,
+109 -109
View File
@@ -40,8 +40,8 @@ title: Working examples
| [pyzmq][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Python bindings for zeromq, the networking library. Uses Cython and CFFI. | | [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. | | [aiortc][] | ![github icon][] | ![apple icon][] ![linux icon][] | WebRTC and ORTC implementation for Python using asyncio. |
| [Implicit][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Includes GPU support for linux wheels | | [Implicit][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Includes GPU support for linux wheels |
| [vispy][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Main repository for Vispy |
| [Confluent client for Kafka][] | ![travisci icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | setup in `tools/wheels/build-wheels.bat` | | [Confluent client for Kafka][] | ![travisci icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | setup in `tools/wheels/build-wheels.bat` |
| [vispy][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Main repository for Vispy |
| [tinyobjloader][] | ![azurepipelines icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Tiny but powerful single file wavefront obj loader | | [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 | | [Dependency Injector][] | ![travisci icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Dependency injection framework for Python, uses Windows TravisCI |
| [coverage.py][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | The coverage tool for Python | | [coverage.py][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | The coverage tool for Python |
@@ -53,15 +53,15 @@ title: Working examples
| [PyAV][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Pythonic bindings for FFmpeg's libraries. | | [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 | | [SimpleJSON][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | simplejson is a simple, fast, extensible JSON encoder/decoder for Python |
| [pikepdf][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | A Python library for reading and writing PDF, powered by qpdf | | [pikepdf][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | A Python library for reading and writing PDF, powered by qpdf |
| [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 | | [Line Profiler][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Line-by-line profiling for Python |
| [OpenColorIO][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | A color management framework for visual effects and animation. |
| [PyTables][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | A Python package to manage extremely large amounts of data | | [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. | | [OpenTimelineIO][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Open Source API and interchange format for editorial timeline information. |
| [aioquic][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | QUIC and HTTP/3 implementation in Python | | [aioquic][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | QUIC and HTTP/3 implementation in Python |
| [ruptures][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Extensive Cython + NumPy [pyproject.toml](https://github.com/deepcharles/ruptures/blob/master/pyproject.toml) example. | | [ruptures][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Extensive Cython + NumPy [pyproject.toml](https://github.com/deepcharles/ruptures/blob/master/pyproject.toml) example. |
| [envd][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | 🏕️ Development environment for AI/ML, based on buildkit |
| [Psycopg 3][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | A modern implementation of a PostgreSQL adapter for Python | | [Psycopg 3][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | A modern implementation of a PostgreSQL adapter for Python |
| [DeepForest][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | An Efficient, Scalable and Optimized Python Framework for Deep Forest (2021.2.1) | | [DeepForest][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | An Efficient, Scalable and Optimized Python Framework for Deep Forest (2021.2.1) |
| [envd][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | 🏕️ Development environment for machine learning |
| [google neuroglancer][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | WebGL-based viewer for volumetric data | | [google neuroglancer][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | WebGL-based viewer for volumetric data |
| [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. | | [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. | | [AutoPy][] | ![travisci icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Includes a Windows Travis build. |
@@ -88,8 +88,8 @@ title: Working examples
| [bx-python][] | ![travisci icon][] | ![apple icon][] ![linux icon][] | A library that includes Cython extensions. | | [bx-python][] | ![travisci icon][] | ![apple icon][] ![linux icon][] | A library that includes Cython extensions. |
| [boost-histogram][] | ![github icon][] ![travisci icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Supports full range of wheels, including PyPy and alternate archs. | | [boost-histogram][] | ![github icon][] ![travisci icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Supports full range of wheels, including PyPy and alternate archs. |
| [TgCrypto][] | ![travisci icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Includes a Windows Travis build. | | [TgCrypto][] | ![travisci icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Includes a Windows Travis build. |
| [iDynTree][] | ![github icon][] | ![linux icon][] | Uses manylinux_2_24 |
| [mosec][] | ![github icon][] | ![linux icon][] ![apple icon][] | A high-performance serving framework for ML models, offers dynamic batching and multi-stage pipeline to fully exploit your compute machine | | [mosec][] | ![github icon][] | ![linux icon][] ![apple icon][] | A high-performance serving framework for ML models, offers dynamic batching and multi-stage pipeline to fully exploit your compute machine |
| [iDynTree][] | ![github icon][] | ![linux icon][] | Uses manylinux_2_24 |
| [Python-WebRTC][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | a Python extension that provides bindings to WebRTC M92 | | [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 | | [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. | | [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. |
@@ -144,8 +144,8 @@ title: Working examples
[pyzmq]: https://github.com/zeromq/pyzmq [pyzmq]: https://github.com/zeromq/pyzmq
[aiortc]: https://github.com/aiortc/aiortc [aiortc]: https://github.com/aiortc/aiortc
[Implicit]: https://github.com/benfred/implicit [Implicit]: https://github.com/benfred/implicit
[vispy]: https://github.com/vispy/vispy
[Confluent client for Kafka]: https://github.com/confluentinc/confluent-kafka-python [Confluent client for Kafka]: https://github.com/confluentinc/confluent-kafka-python
[vispy]: https://github.com/vispy/vispy
[tinyobjloader]: https://github.com/tinyobjloader/tinyobjloader [tinyobjloader]: https://github.com/tinyobjloader/tinyobjloader
[Dependency Injector]: https://github.com/ets-labs/python-dependency-injector [Dependency Injector]: https://github.com/ets-labs/python-dependency-injector
[coverage.py]: https://github.com/nedbat/coveragepy [coverage.py]: https://github.com/nedbat/coveragepy
@@ -157,15 +157,15 @@ title: Working examples
[PyAV]: https://github.com/PyAV-Org/PyAV [PyAV]: https://github.com/PyAV-Org/PyAV
[SimpleJSON]: https://github.com/simplejson/simplejson [SimpleJSON]: https://github.com/simplejson/simplejson
[pikepdf]: https://github.com/pikepdf/pikepdf [pikepdf]: https://github.com/pikepdf/pikepdf
[OpenColorIO]: https://github.com/AcademySoftwareFoundation/OpenColorIO
[Line Profiler]: https://github.com/pyutils/line_profiler [Line Profiler]: https://github.com/pyutils/line_profiler
[OpenColorIO]: https://github.com/AcademySoftwareFoundation/OpenColorIO
[PyTables]: https://github.com/PyTables/PyTables [PyTables]: https://github.com/PyTables/PyTables
[OpenTimelineIO]: https://github.com/PixarAnimationStudios/OpenTimelineIO [OpenTimelineIO]: https://github.com/PixarAnimationStudios/OpenTimelineIO
[aioquic]: https://github.com/aiortc/aioquic [aioquic]: https://github.com/aiortc/aioquic
[ruptures]: https://github.com/deepcharles/ruptures [ruptures]: https://github.com/deepcharles/ruptures
[envd]: https://github.com/tensorchord/envd
[Psycopg 3]: https://github.com/psycopg/psycopg [Psycopg 3]: https://github.com/psycopg/psycopg
[DeepForest]: https://github.com/LAMDA-NJU/Deep-Forest [DeepForest]: https://github.com/LAMDA-NJU/Deep-Forest
[envd]: https://github.com/tensorchord/envd
[google neuroglancer]: https://github.com/google/neuroglancer [google neuroglancer]: https://github.com/google/neuroglancer
[Parselmouth]: https://github.com/YannickJadoul/Parselmouth [Parselmouth]: https://github.com/YannickJadoul/Parselmouth
[AutoPy]: https://github.com/autopilot-rs/autopy [AutoPy]: https://github.com/autopilot-rs/autopy
@@ -192,8 +192,8 @@ title: Working examples
[bx-python]: https://github.com/bxlab/bx-python [bx-python]: https://github.com/bxlab/bx-python
[boost-histogram]: https://github.com/scikit-hep/boost-histogram [boost-histogram]: https://github.com/scikit-hep/boost-histogram
[TgCrypto]: https://github.com/pyrogram/tgcrypto [TgCrypto]: https://github.com/pyrogram/tgcrypto
[iDynTree]: https://github.com/robotology/idyntree
[mosec]: https://github.com/mosecorg/mosec [mosec]: https://github.com/mosecorg/mosec
[iDynTree]: https://github.com/robotology/idyntree
[Python-WebRTC]: https://github.com/MarshalX/python-webrtc [Python-WebRTC]: https://github.com/MarshalX/python-webrtc
[pybase64]: https://github.com/mayeut/pybase64 [pybase64]: https://github.com/mayeut/pybase64
[Arbor]: https://github.com/arbor-sim/arbor [Arbor]: https://github.com/arbor-sim/arbor
@@ -227,109 +227,109 @@ title: Working examples
[apple icon]: data/readme_icons/apple.svg [apple icon]: data/readme_icons/apple.svg
[linux icon]: data/readme_icons/linux.svg [linux icon]: data/readme_icons/linux.svg
<!-- scikit-learn: 51270, last pushed 0 days ago --> <!-- scikit-learn: 51403, last pushed 0 days ago -->
<!-- NumPy: 21357, last pushed 0 days ago --> <!-- NumPy: 21474, last pushed 0 days ago -->
<!-- Tornado: 20724, last pushed 6 days ago --> <!-- Tornado: 20743, last pushed 12 days ago -->
<!-- pytorch-fairseq: 19079, last pushed 2 days ago --> <!-- pytorch-fairseq: 19191, last pushed 2 days ago -->
<!-- Matplotlib: 16066, last pushed 0 days ago --> <!-- Matplotlib: 16136, last pushed 0 days ago -->
<!-- NCNN: 15395, last pushed 0 days ago --> <!-- NCNN: 15506, last pushed 0 days ago -->
<!-- Kivy: 14970, last pushed 0 days ago --> <!-- Kivy: 15023, last pushed 6 days ago -->
<!-- Prophet: 14851, last pushed 0 days ago --> <!-- Prophet: 14915, last pushed 1 days ago -->
<!-- MyPy: 13708, last pushed 0 days ago --> <!-- MyPy: 13792, last pushed 0 days ago -->
<!-- pydantic: 10965, last pushed 1 days ago --> <!-- pydantic: 11091, last pushed 2 days ago -->
<!-- MemRay: 9186, last pushed 1 days ago --> <!-- MemRay: 9238, last pushed 0 days ago -->
<!-- uvloop: 8832, last pushed 2 days ago --> <!-- uvloop: 8881, last pushed 2 days ago -->
<!-- psutil: 8668, last pushed 0 days ago --> <!-- psutil: 8696, last pushed 0 days ago -->
<!-- vaex: 7272, last pushed 3 days ago --> <!-- vaex: 7296, last pushed 2 days ago -->
<!-- Google Benchmark: 6803, last pushed 1 days ago --> <!-- Google Benchmark: 6836, last pushed 4 days ago -->
<!-- duckdb: 6189, last pushed 0 days ago --> <!-- duckdb: 6390, last pushed 0 days ago -->
<!-- Apache Beam: 5815, last pushed 0 days ago --> <!-- Apache Beam: 5862, last pushed 0 days ago -->
<!-- asyncpg: 5616, last pushed 22 days ago --> <!-- asyncpg: 5635, last pushed 1 days ago -->
<!-- PyGame: 5173, last pushed 0 days ago --> <!-- PyGame: 5210, last pushed 0 days ago -->
<!-- cmake: 5036, last pushed 0 days ago --> <!-- cmake: 5079, last pushed 0 days ago -->
<!-- scikit-image: 5035, last pushed 0 days ago --> <!-- scikit-image: 5042, last pushed 0 days ago -->
<!-- twisted-iocpsupport: 4732, last pushed 0 days ago --> <!-- twisted-iocpsupport: 4749, last pushed 0 days ago -->
<!-- PyOxidizer: 4223, last pushed 12 days ago --> <!-- PyOxidizer: 4292, last pushed 0 days ago -->
<!-- websockets: 4147, last pushed 10 days ago --> <!-- websockets: 4163, last pushed 2 days ago -->
<!-- cvxpy: 4059, last pushed 2 days ago --> <!-- cvxpy: 4082, last pushed 0 days ago -->
<!-- Triton: 3952, last pushed 0 days ago --> <!-- Triton: 4009, last pushed 0 days ago -->
<!-- UltraJSON: 3825, last pushed 27 days ago --> <!-- UltraJSON: 3840, last pushed 3 days ago -->
<!-- River: 3571, last pushed 2 days ago --> <!-- River: 3622, last pushed 3 days ago -->
<!-- OpenSpiel: 3304, last pushed 0 days ago --> <!-- OpenSpiel: 3318, last pushed 1 days ago -->
<!-- pyzmq: 3150, last pushed 5 days ago --> <!-- pyzmq: 3156, last pushed 2 days ago -->
<!-- aiortc: 3053, last pushed 20 days ago --> <!-- aiortc: 3072, last pushed 12 days ago -->
<!-- Implicit: 2932, last pushed 4 days ago --> <!-- Implicit: 2946, last pushed 18 days ago -->
<!-- vispy: 2924, last pushed 2 days ago --> <!-- Confluent client for Kafka: 2932, last pushed 1 days ago -->
<!-- Confluent client for Kafka: 2917, last pushed 3 days ago --> <!-- vispy: 2931, last pushed 0 days ago -->
<!-- tinyobjloader: 2630, last pushed 61 days ago --> <!-- tinyobjloader: 2643, last pushed 75 days ago -->
<!-- Dependency Injector: 2334, last pushed 32 days ago --> <!-- Dependency Injector: 2361, last pushed 10 days ago -->
<!-- coverage.py: 2175, last pushed 0 days ago --> <!-- coverage.py: 2196, last pushed 1 days ago -->
<!-- PyCryptodome: 2111, last pushed 2 days ago --> <!-- PyCryptodome: 2125, last pushed 16 days ago -->
<!-- PyYAML: 1920, last pushed 7 days ago --> <!-- PyYAML: 1932, last pushed 5 days ago -->
<!-- numexpr: 1804, last pushed 16 days ago --> <!-- numexpr: 1813, last pushed 13 days ago -->
<!-- h5py: 1776, last pushed 3 days ago --> <!-- h5py: 1778, last pushed 1 days ago -->
<!-- Wrapt: 1739, last pushed 11 days ago --> <!-- Wrapt: 1743, last pushed 25 days ago -->
<!-- PyAV: 1647, last pushed 6 days ago --> <!-- PyAV: 1659, last pushed 5 days ago -->
<!-- SimpleJSON: 1513, last pushed 65 days ago --> <!-- SimpleJSON: 1519, last pushed 79 days ago -->
<!-- pikepdf: 1484, last pushed 4 days ago --> <!-- pikepdf: 1491, last pushed 0 days ago -->
<!-- OpenColorIO: 1360, last pushed 4 days ago --> <!-- Line Profiler: 1372, last pushed 2 days ago -->
<!-- Line Profiler: 1353, last pushed 18 days ago --> <!-- OpenColorIO: 1364, last pushed 8 days ago -->
<!-- PyTables: 1144, last pushed 11 days ago --> <!-- PyTables: 1148, last pushed 3 days ago -->
<!-- OpenTimelineIO: 1087, last pushed 0 days ago --> <!-- OpenTimelineIO: 1096, last pushed 0 days ago -->
<!-- aioquic: 1045, last pushed 16 days ago --> <!-- aioquic: 1055, last pushed 1 days ago -->
<!-- ruptures: 1035, last pushed 10 days ago --> <!-- ruptures: 1043, last pushed 24 days ago -->
<!-- Psycopg 3: 776, last pushed 0 days ago --> <!-- envd: 988, last pushed 0 days ago -->
<!-- DeepForest: 775, last pushed 114 days ago --> <!-- Psycopg 3: 784, last pushed 0 days ago -->
<!-- envd: 759, last pushed 0 days ago --> <!-- DeepForest: 777, last pushed 0 days ago -->
<!-- google neuroglancer: 750, last pushed 2 days ago --> <!-- google neuroglancer: 753, last pushed 10 days ago -->
<!-- Parselmouth: 684, last pushed 56 days ago --> <!-- Parselmouth: 695, last pushed 70 days ago -->
<!-- AutoPy: 672, last pushed 253 days ago --> <!-- AutoPy: 674, last pushed 267 days ago -->
<!-- H3-py: 561, last pushed 7 days ago --> <!-- H3-py: 560, last pushed 21 days ago -->
<!-- Rtree: 501, last pushed 138 days ago --> <!-- Rtree: 502, last pushed 152 days ago -->
<!-- markupsafe: 491, last pushed 3 days ago --> <!-- markupsafe: 494, last pushed 13 days ago -->
<!-- python-rapidjson: 457, last pushed 46 days ago --> <!-- python-rapidjson: 459, last pushed 60 days ago -->
<!-- python-snappy: 445, last pushed 172 days ago --> <!-- python-snappy: 443, last pushed 186 days ago -->
<!-- pybind11 cmake_example: 433, last pushed 24 days ago --> <!-- pybind11 cmake_example: 441, last pushed 2 days ago -->
<!-- KDEpy: 399, last pushed 206 days ago --> <!-- KDEpy: 404, last pushed 220 days ago -->
<!-- tgcalls: 388, last pushed 65 days ago --> <!-- tgcalls: 390, last pushed 79 days ago -->
<!-- pybind11 python_example: 358, last pushed 24 days ago --> <!-- pybind11 python_example: 363, last pushed 0 days ago -->
<!-- dd-trace-py: 356, last pushed 2 days ago --> <!-- dd-trace-py: 357, last pushed 0 days ago -->
<!-- CTranslate2: 330, last pushed 2 days ago --> <!-- CTranslate2: 334, last pushed 2 days ago -->
<!-- time-machine: 321, last pushed 8 days ago --> <!-- time-machine: 330, last pushed 6 days ago -->
<!-- sourmash: 320, last pushed 0 days ago --> <!-- sourmash: 321, last pushed 0 days ago -->
<!-- cyvcf2: 304, last pushed 20 days ago --> <!-- cyvcf2: 305, last pushed 34 days ago -->
<!-- matrixprofile: 280, last pushed 62 days ago --> <!-- matrixprofile: 285, last pushed 76 days ago -->
<!-- abess: 278, last pushed 9 days ago --> <!-- abess: 282, last pushed 7 days ago -->
<!-- jq.py: 228, last pushed 3 days ago --> <!-- jq.py: 229, last pushed 6 days ago -->
<!-- iminuit: 210, last pushed 9 days ago --> <!-- iminuit: 212, last pushed 23 days ago -->
<!-- Tokenizer: 186, last pushed 4 days ago --> <!-- Tokenizer: 187, last pushed 5 days ago -->
<!-- PyGLM: 150, last pushed 160 days ago --> <!-- PyGLM: 151, last pushed 174 days ago -->
<!-- bx-python: 116, last pushed 7 days ago --> <!-- bx-python: 118, last pushed 21 days ago -->
<!-- boost-histogram: 116, last pushed 6 days ago --> <!-- boost-histogram: 116, last pushed 1 days ago -->
<!-- TgCrypto: 110, last pushed 184 days ago --> <!-- TgCrypto: 110, last pushed 198 days ago -->
<!-- iDynTree: 108, last pushed 4 days ago --> <!-- mosec: 109, last pushed 2 days ago -->
<!-- mosec: 104, last pushed 0 days ago --> <!-- iDynTree: 108, last pushed 3 days ago -->
<!-- Python-WebRTC: 93, last pushed 178 days ago --> <!-- Python-WebRTC: 94, last pushed 192 days ago -->
<!-- pybase64: 87, last pushed 1 days ago --> <!-- pybase64: 88, last pushed 5 days ago -->
<!-- Arbor: 78, last pushed 2 days ago --> <!-- Arbor: 80, last pushed 1 days ago -->
<!-- fathon: 67, last pushed 94 days ago --> <!-- fathon: 68, last pushed 108 days ago -->
<!-- etebase-py: 58, last pushed 60 days ago --> <!-- etebase-py: 58, last pushed 74 days ago -->
<!-- polaroid: 53, last pushed 116 days ago --> <!-- polaroid: 54, last pushed 130 days ago -->
<!-- cf-units: 49, last pushed 0 days ago --> <!-- cf-units: 49, last pushed 0 days ago -->
<!-- Imagecodecs (fork): 47, last pushed 27 days ago --> <!-- Imagecodecs (fork): 48, last pushed 41 days ago -->
<!-- pillow-heif: 46, last pushed 15 days ago --> <!-- pillow-heif: 48, last pushed 6 days ago -->
<!-- power-grid-model: 46, last pushed 4 days ago --> <!-- power-grid-model: 48, last pushed 2 days ago -->
<!-- clang-format: 43, last pushed 3 days ago --> <!-- clang-format: 43, last pushed 12 days ago -->
<!-- numpythia: 34, last pushed 4 days ago --> <!-- numpythia: 34, last pushed 18 days ago -->
<!-- pybind11 scikit_build_example: 33, last pushed 24 days ago --> <!-- pybind11 scikit_build_example: 33, last pushed 0 days ago -->
<!-- pyjet: 33, last pushed 4 days ago --> <!-- pyjet: 32, last pushed 18 days ago -->
<!-- ninja: 25, last pushed 4 days ago --> <!-- ninja: 25, last pushed 0 days ago -->
<!-- GSD: 19, last pushed 3 days ago --> <!-- GSD: 19, last pushed 6 days ago -->
<!-- pyinstrument_cext: 10, last pushed 331 days ago --> <!-- pyinstrument_cext: 10, last pushed 345 days ago -->
<!-- CorrectionLib: 10, last pushed 4 days ago --> <!-- CorrectionLib: 10, last pushed 4 days ago -->
<!-- xmlstarlet: 9, last pushed 20 days ago --> <!-- xmlstarlet: 9, last pushed 34 days ago -->
<!-- SiPM: 7, last pushed 95 days ago --> <!-- SiPM: 8, last pushed 109 days ago -->
<!-- ril: 3, last pushed 16 days ago --> <!-- ril: 5, last pushed 5 days ago -->
<!-- END bin/projects.py --> <!-- END bin/projects.py -->
+1 -1
View File
@@ -12,7 +12,7 @@ stack: python 3.7
init: init:
- cmd: set PATH=C:\Python37;C:\Python37\Scripts;%PATH% - cmd: set PATH=C:\Python37;C:\Python37\Scripts;%PATH%
install: python -m pip install cibuildwheel==2.9.0 install: python -m pip install cibuildwheel==2.10.2
build_script: python -m cibuildwheel --output-dir wheelhouse build_script: python -m cibuildwheel --output-dir wheelhouse
+3 -3
View File
@@ -6,7 +6,7 @@ jobs:
- bash: | - bash: |
set -o errexit set -o errexit
python3 -m pip install --upgrade pip python3 -m pip install --upgrade pip
pip3 install cibuildwheel==2.9.0 pip3 install cibuildwheel==2.10.2
displayName: Install dependencies displayName: Install dependencies
- bash: cibuildwheel --output-dir wheelhouse . - bash: cibuildwheel --output-dir wheelhouse .
displayName: Build wheels displayName: Build wheels
@@ -20,7 +20,7 @@ jobs:
- bash: | - bash: |
set -o errexit set -o errexit
python3 -m pip install --upgrade pip python3 -m pip install --upgrade pip
python3 -m pip install cibuildwheel==2.9.0 python3 -m pip install cibuildwheel==2.10.2
displayName: Install dependencies displayName: Install dependencies
- bash: cibuildwheel --output-dir wheelhouse . - bash: cibuildwheel --output-dir wheelhouse .
displayName: Build wheels displayName: Build wheels
@@ -34,7 +34,7 @@ jobs:
- bash: | - bash: |
set -o errexit set -o errexit
python -m pip install --upgrade pip python -m pip install --upgrade pip
pip install cibuildwheel==2.9.0 pip install cibuildwheel==2.10.2
displayName: Install dependencies displayName: Install dependencies
- bash: cibuildwheel --output-dir wheelhouse . - bash: cibuildwheel --output-dir wheelhouse .
displayName: Build wheels displayName: Build wheels
+2 -2
View File
@@ -11,7 +11,7 @@ jobs:
- run: - run:
name: Build the Linux wheels. name: Build the Linux wheels.
command: | command: |
pip3 install --user cibuildwheel==2.9.0 pip3 install --user cibuildwheel==2.10.2
cibuildwheel --output-dir wheelhouse cibuildwheel --output-dir wheelhouse
- store_artifacts: - store_artifacts:
path: wheelhouse/ path: wheelhouse/
@@ -25,7 +25,7 @@ jobs:
- run: - run:
name: Build the OS X wheels. name: Build the OS X wheels.
command: | command: |
pip3 install cibuildwheel==2.9.0 pip3 install cibuildwheel==2.10.2
cibuildwheel --output-dir wheelhouse cibuildwheel --output-dir wheelhouse
- store_artifacts: - store_artifacts:
path: wheelhouse/ path: wheelhouse/
+1 -1
View File
@@ -1,6 +1,6 @@
build_and_store_wheels: &BUILD_AND_STORE_WHEELS build_and_store_wheels: &BUILD_AND_STORE_WHEELS
install_cibuildwheel_script: install_cibuildwheel_script:
- python -m pip install cibuildwheel==2.9.0 - python -m pip install cibuildwheel==2.10.2
run_cibuildwheel_script: run_cibuildwheel_script:
- cibuildwheel - cibuildwheel
wheels_artifacts: wheels_artifacts:
+1 -1
View File
@@ -1,6 +1,6 @@
build_and_store_wheels: &BUILD_AND_STORE_WHEELS build_and_store_wheels: &BUILD_AND_STORE_WHEELS
install_cibuildwheel_script: install_cibuildwheel_script:
- python -m pip install cibuildwheel==2.9.0 - python -m pip install cibuildwheel==2.10.2
run_cibuildwheel_script: run_cibuildwheel_script:
- cibuildwheel - cibuildwheel
wheels_artifacts: wheels_artifacts:
+1 -1
View File
@@ -10,7 +10,7 @@ jobs:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Build wheels - name: Build wheels
uses: pypa/cibuildwheel@v2.9.0 uses: pypa/cibuildwheel@v2.10.2
env: env:
CIBW_ARCHS_MACOS: x86_64 arm64 CIBW_ARCHS_MACOS: x86_64 arm64
+1 -1
View File
@@ -22,7 +22,7 @@ jobs:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Build wheels - name: Build wheels
uses: pypa/cibuildwheel@v2.9.0 uses: pypa/cibuildwheel@v2.10.2
- uses: actions/upload-artifact@v3 - uses: actions/upload-artifact@v3
with: with:
+1 -1
View File
@@ -14,7 +14,7 @@ jobs:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Build wheels - name: Build wheels
uses: pypa/cibuildwheel@v2.9.0 uses: pypa/cibuildwheel@v2.10.2
# env: # env:
# CIBW_SOME_OPTION: value # CIBW_SOME_OPTION: value
# ... # ...
+1 -1
View File
@@ -20,7 +20,7 @@ jobs:
platforms: all platforms: all
- name: Build wheels - name: Build wheels
uses: pypa/cibuildwheel@v2.9.0 uses: pypa/cibuildwheel@v2.10.2
env: env:
# configure cibuildwheel to build native archs ('auto'), and some # configure cibuildwheel to build native archs ('auto'), and some
# emulated ones # emulated ones
+1 -1
View File
@@ -12,7 +12,7 @@ linux:
DOCKER_TLS_CERTDIR: "" DOCKER_TLS_CERTDIR: ""
script: script:
- curl -sSL https://get.docker.com/ | sh - curl -sSL https://get.docker.com/ | sh
- python -m pip install cibuildwheel==2.9.0 - python -m pip install cibuildwheel==2.10.2
- cibuildwheel --output-dir wheelhouse - cibuildwheel --output-dir wheelhouse
artifacts: artifacts:
paths: paths:
+1 -1
View File
@@ -19,7 +19,7 @@ jobs:
- ln -s /c/Python38/python.exe /c/Python38/python3.exe - ln -s /c/Python38/python.exe /c/Python38/python3.exe
install: install:
- python3 -m pip install cibuildwheel==2.9.0 - python3 -m pip install cibuildwheel==2.10.2
script: script:
# build the wheels, put them into './dist' # 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 - ln -s /c/Python38/python.exe /c/Python38/python3.exe
install: install:
- python3 -m pip install cibuildwheel==2.9.0 - python3 -m pip install cibuildwheel==2.10.2
script: script:
# build the wheels, put them into './wheelhouse' # build the wheels, put them into './wheelhouse'
+2 -2
View File
@@ -54,7 +54,7 @@ jobs:
- stage: deploy - stage: deploy
name: Build and deploy Linux wheels name: Build and deploy Linux wheels
services: docker services: docker
install: python3 -m pip install cibuildwheel==2.9.0 twine install: python3 -m pip install cibuildwheel==2.10.2 twine
script: python3 -m cibuildwheel --output-dir wheelhouse script: python3 -m cibuildwheel --output-dir wheelhouse
after_success: python3 -m twine upload --skip-existing wheelhouse/*.whl after_success: python3 -m twine upload --skip-existing wheelhouse/*.whl
# Deploy on windows # Deploy on windows
@@ -62,7 +62,7 @@ jobs:
name: Build and deploy Windows wheels name: Build and deploy Windows wheels
os: windows os: windows
language: shell language: shell
install: python3 -m pip install cibuildwheel==2.9.0 twine install: python3 -m pip install cibuildwheel==2.10.2 twine
script: python3 -m cibuildwheel --output-dir wheelhouse script: python3 -m cibuildwheel --output-dir wheelhouse
after_success: python3 -m twine upload --skip-existing wheelhouse/*.whl after_success: python3 -m twine upload --skip-existing wheelhouse/*.whl
+1 -1
View File
@@ -66,8 +66,8 @@ module = [
"setuptools", "setuptools",
"pytest", # ignored in pre-commit to speed up check "pytest", # ignored in pre-commit to speed up check
"bashlex", "bashlex",
"bashlex.*",
"importlib_resources", "importlib_resources",
"ghapi.*",
] ]
ignore_missing_imports = true ignore_missing_imports = true
+2 -2
View File
@@ -1,6 +1,6 @@
[metadata] [metadata]
name = cibuildwheel name = cibuildwheel
version = 2.9.0 version = 2.10.2
description = Build Python wheels on CI with minimal configuration. description = Build Python wheels on CI with minimal configuration.
long_description = file: README.md long_description = file: README.md
long_description_content_type = text/markdown long_description_content_type = text/markdown
@@ -37,7 +37,7 @@ install_requires =
packaging>=20.9 packaging>=20.9
platformdirs platformdirs
tomli;python_version < '3.11' tomli;python_version < '3.11'
typing-extensions>=3.10.0.0;python_version < '3.8' typing-extensions>=4.1.0;python_version < '3.11'
python_requires = >=3.7 python_requires = >=3.7
include_package_data = True include_package_data = True
zip_safe = False zip_safe = False
-3
View File
@@ -20,7 +20,6 @@ extras = {
], ],
"bin": [ "bin": [
"click", "click",
"ghapi",
"pip-tools", "pip-tools",
"pygithub", "pygithub",
"pyyaml", "pyyaml",
@@ -46,6 +45,4 @@ extras["dev"] = [
*extras["bin"], *extras["bin"],
] ]
extras["all"] = sum(extras.values(), [])
setup(extras_require=extras) setup(extras_require=extras)
+2 -1
View File
@@ -108,7 +108,8 @@ def test_pinned_versions(tmp_path, python_version, build_frontend_env):
w for w in utils.expected_wheels("spam", "0.1.0") if "-cp39" in w or "-pp39" in w w for w in utils.expected_wheels("spam", "0.1.0") if "-cp39" in w or "-pp39" in w
] ]
else: else:
raise ValueError("unhandled python version") msg = "unhandled python version"
raise ValueError(msg)
assert set(actual_wheels) == set(expected_wheels) assert set(actual_wheels) == set(expected_wheels)
+4 -2
View File
@@ -23,7 +23,8 @@ elif sys.platform.startswith("darwin"):
elif sys.platform in ["win32", "cygwin"]: elif sys.platform in ["win32", "cygwin"]:
platform = "windows" platform = "windows"
else: else:
raise Exception("Unsupported platform") msg = f"Unsupported platform {sys.platform!r}"
raise Exception(msg)
def cibuildwheel_get_build_identifiers(project_path, env=None, *, prerelease_pythons=False): def cibuildwheel_get_build_identifiers(project_path, env=None, *, prerelease_pythons=False):
@@ -210,7 +211,8 @@ def expected_wheels(
) )
else: else:
raise Exception("unsupported platform") msg = f"Unsupported platform {platform!r}"
raise Exception(msg)
for platform_tag in platform_tags: for platform_tag in platform_tags:
wheels.append(f"{package_name}-{package_version}-{python_abi_tag}-{platform_tag}.whl") wheels.append(f"{package_name}-{package_version}-{python_abi_tag}-{platform_tag}.whl")
+82
View File
@@ -0,0 +1,82 @@
from __future__ import annotations
import platform as platform_module
import sys
import pytest
from cibuildwheel.architecture import Architecture
@pytest.fixture(
params=[
pytest.param(("linux", "linux", "x86_64", "64"), id="linux-64"),
pytest.param(("linux", "linux", "i686", "32"), id="linux-32"),
pytest.param(("linux", "linux", "aarch64", "arm"), id="linux-arm"),
pytest.param(("macos", "darwin", "x86_64", "64"), id="macos-64"),
pytest.param(("macos", "darwin", "arm64", "arm"), id="macos-arm"),
pytest.param(("windows", "win32", "x86", "32"), id="windows-32"),
pytest.param(("windows", "win32", "AMD64", "64"), id="windows-64"),
pytest.param(("windows", "win32", "ARM64", "arm"), id="windows-arm"),
]
)
def platform_machine(request, monkeypatch):
platform_name, platform_value, machine_value, machine_name = request.param
monkeypatch.setattr(sys, "platform", platform_value)
monkeypatch.setattr(platform_module, "machine", lambda: machine_value)
return platform_name, machine_name
def test_arch_auto(platform_machine):
platform_name, machine_name = platform_machine
arch_set = Architecture.auto_archs("linux")
expected = {
"32": {Architecture.i686},
"64": {Architecture.x86_64, Architecture.i686},
"arm": {Architecture.aarch64},
}
assert arch_set == expected[machine_name]
arch_set = Architecture.auto_archs("macos")
expected = {"32": set(), "64": {Architecture.x86_64}, "arm": {Architecture.arm64}}
assert arch_set == expected[machine_name]
arch_set = Architecture.auto_archs("windows")
expected = {
"32": {Architecture.x86},
"64": {Architecture.AMD64, Architecture.x86},
"arm": {Architecture.ARM64},
}
assert arch_set == expected[machine_name]
def test_arch_auto64(platform_machine):
platform_name, machine_name = platform_machine
arch_set = Architecture.parse_config("auto64", "linux")
expected = {"32": set(), "64": {Architecture.x86_64}, "arm": {Architecture.aarch64}}
assert arch_set == expected[machine_name]
arch_set = Architecture.parse_config("auto64", "macos")
expected = {"32": set(), "64": {Architecture.x86_64}, "arm": {Architecture.arm64}}
assert arch_set == expected[machine_name]
arch_set = Architecture.parse_config("auto64", "windows")
expected = {"32": set(), "64": {Architecture.AMD64}, "arm": {Architecture.ARM64}}
assert arch_set == expected[machine_name]
def test_arch_auto32(platform_machine):
platform_name, machine_name = platform_machine
arch_set = Architecture.parse_config("auto32", "linux")
expected = {"32": {Architecture.i686}, "64": {Architecture.i686}, "arm": set()}
assert arch_set == expected[machine_name]
arch_set = Architecture.parse_config("auto32", "macos")
assert arch_set == set()
arch_set = Architecture.parse_config("auto32", "windows")
expected = {"32": {Architecture.x86}, "64": {Architecture.x86}, "arm": set()}
assert arch_set == expected[machine_name]
+16 -11
View File
@@ -12,7 +12,13 @@ from cibuildwheel import linux, macos, util, windows
class ArgsInterceptor: class ArgsInterceptor:
def __init__(self):
self.call_count = 0
self.args = None
self.kwargs = None
def __call__(self, *args, **kwargs): def __call__(self, *args, **kwargs):
self.call_count += 1
self.args = args self.args = args
self.kwargs = kwargs self.kwargs = kwargs
@@ -25,7 +31,8 @@ def mock_protection(monkeypatch):
""" """
def fail_on_call(*args, **kwargs): def fail_on_call(*args, **kwargs):
raise RuntimeError("This should never be called") msg = "This should never be called"
raise RuntimeError(msg)
def ignore_call(*args, **kwargs): def ignore_call(*args, **kwargs):
pass pass
@@ -75,16 +82,14 @@ def platform(request, monkeypatch):
@pytest.fixture @pytest.fixture
def intercepted_build_args(platform, monkeypatch): def intercepted_build_args(monkeypatch):
intercepted = ArgsInterceptor() intercepted = ArgsInterceptor()
if platform == "linux": monkeypatch.setattr(linux, "build", intercepted)
monkeypatch.setattr(linux, "build", intercepted) monkeypatch.setattr(macos, "build", intercepted)
elif platform == "macos": monkeypatch.setattr(windows, "build", intercepted)
monkeypatch.setattr(macos, "build", intercepted)
elif platform == "windows":
monkeypatch.setattr(windows, "build", intercepted)
else:
raise ValueError(f"unknown platform value: {platform}")
return intercepted yield intercepted
# check that intercepted_build_args only ever had one set of args
assert intercepted.call_count <= 1
+2 -1
View File
@@ -126,7 +126,8 @@ def get_default_repair_command(platform):
elif platform == "windows": elif platform == "windows":
return "" return ""
else: else:
raise ValueError("Unknown platform", platform) msg = f"Unknown platform: {platform!r}"
raise ValueError(msg)
@pytest.mark.parametrize("repair_command", [None, "repair", "repair -w {dest_dir} {wheel}"]) @pytest.mark.parametrize("repair_command", [None, "repair", "repair -w {dest_dir} {wheel}"])
@@ -192,3 +192,74 @@ def test_archs_platform_all(platform, intercepted_build_args, monkeypatch):
Architecture.arm64, Architecture.arm64,
Architecture.universal2, Architecture.universal2,
} }
@pytest.mark.parametrize(
"only,plat",
(
("cp311-manylinux_x86_64", "linux"),
("cp310-win_amd64", "windows"),
("cp310-win32", "windows"),
("cp311-macosx_x86_64", "macos"),
),
)
def test_only_argument(intercepted_build_args, monkeypatch, only, plat):
monkeypatch.setenv("CIBW_BUILD", "unused")
monkeypatch.setenv("CIBW_SKIP", "unused")
monkeypatch.setattr(sys, "argv", sys.argv + ["--only", only])
main()
options = intercepted_build_args.args[0]
assert options.globals.build_selector.build_config == only
assert options.globals.build_selector.skip_config == ""
assert options.platform == plat
assert options.globals.architectures == Architecture.all_archs(plat)
@pytest.mark.parametrize("only", ("cp311-manylxinux_x86_64", "some_linux_thing"))
def test_only_failed(monkeypatch, only):
monkeypatch.setattr(sys, "argv", sys.argv + ["--only", only])
with pytest.raises(SystemExit):
main()
def test_only_no_platform(monkeypatch):
monkeypatch.setattr(
sys, "argv", sys.argv + ["--only", "cp311-manylinux_x86_64", "--platform", "macos"]
)
with pytest.raises(SystemExit):
main()
def test_only_no_archs(monkeypatch):
monkeypatch.setattr(
sys, "argv", sys.argv + ["--only", "cp311-manylinux_x86_64", "--archs", "x86_64"]
)
with pytest.raises(SystemExit):
main()
@pytest.mark.parametrize(
"envvar_name,envvar_value",
(
("CIBW_BUILD", "cp310-*"),
("CIBW_SKIP", "cp311-*"),
("CIBW_ARCHS", "auto32"),
("CIBW_PLATFORM", "macos"),
),
)
def test_only_overrides_env_vars(monkeypatch, intercepted_build_args, envvar_name, envvar_value):
monkeypatch.setattr(sys, "argv", sys.argv + ["--only", "cp311-manylinux_x86_64"])
monkeypatch.setenv(envvar_name, envvar_value)
main()
options = intercepted_build_args.args[0]
assert options.globals.build_selector.build_config == "cp311-manylinux_x86_64"
assert options.globals.build_selector.skip_config == ""
assert options.platform == "linux"
assert options.globals.architectures == Architecture.all_archs("linux")
+2 -1
View File
@@ -19,7 +19,8 @@ ALL_IDS = {"cp36", "cp37", "cp38", "cp39", "cp310", "cp311", "pp37", "pp38", "pp
@pytest.fixture @pytest.fixture
def mock_build_container(monkeypatch): def mock_build_container(monkeypatch):
def fail_on_call(*args, **kwargs): def fail_on_call(*args, **kwargs):
raise RuntimeError("This should never be called") msg = "This should never be called"
raise RuntimeError(msg)
def ignore_call(*args, **kwargs): def ignore_call(*args, **kwargs):
pass pass
+60 -12
View File
@@ -1,11 +1,14 @@
from __future__ import annotations from __future__ import annotations
import os
import platform as platform_module import platform as platform_module
import textwrap import textwrap
from pathlib import Path
import pytest import pytest
from cibuildwheel.__main__ import get_build_identifiers from cibuildwheel.__main__ import get_build_identifiers
from cibuildwheel.bashlex_eval import local_environment_executor
from cibuildwheel.environment import parse_environment from cibuildwheel.environment import parse_environment
from cibuildwheel.options import Options, _get_pinned_container_images from cibuildwheel.options import Options, _get_pinned_container_images
@@ -59,7 +62,7 @@ test_command: 'pyproject'
default_build_options = options.build_options(identifier=None) default_build_options = options.build_options(identifier=None)
assert default_build_options.environment == parse_environment("FOO=BAR") assert default_build_options.environment == parse_environment('FOO="BAR"')
all_pinned_container_images = _get_pinned_container_images() all_pinned_container_images = _get_pinned_container_images()
pinned_x86_64_container_image = all_pinned_container_images["x86_64"] pinned_x86_64_container_image = all_pinned_container_images["x86_64"]
@@ -119,30 +122,75 @@ def test_passthrough_evil(tmp_path, monkeypatch, env_var_value):
assert parsed_environment.as_dictionary(prev_environment={}) == {"ENV_VAR": env_var_value} assert parsed_environment.as_dictionary(prev_environment={}) == {"ENV_VAR": env_var_value}
xfail_env_parse = pytest.mark.xfail(
raises=SystemExit, reason="until we can figure out the right way to quote these values"
)
@pytest.mark.parametrize( @pytest.mark.parametrize(
"env_var_value", "env_var_value",
[ [
"normal value", "normal value",
'"value wrapped in quotes"', pytest.param('"value wrapped in quotes"', marks=[xfail_env_parse]),
'an unclosed double-quote: "', pytest.param('an unclosed double-quote: "', marks=[xfail_env_parse]),
"string\nwith\ncarriage\nreturns\n", "string\nwith\ncarriage\nreturns\n",
"a trailing backslash \\", pytest.param("a trailing backslash \\", marks=[xfail_env_parse]),
], ],
) )
def test_toml_environment_evil(tmp_path, monkeypatch, env_var_value): def test_toml_environment_evil(tmp_path, monkeypatch, env_var_value):
args = get_default_command_line_arguments() args = get_default_command_line_arguments()
args.package_dir = tmp_path args.package_dir = tmp_path
with tmp_path.joinpath("pyproject.toml").open("w") as f: tmp_path.joinpath("pyproject.toml").write_text(
f.write( textwrap.dedent(
textwrap.dedent( f"""\
f"""\ [tool.cibuildwheel.environment]
[tool.cibuildwheel.environment] EXAMPLE='''{env_var_value}'''
EXAMPLE='''{env_var_value}''' """
"""
)
) )
)
options = Options(platform="linux", command_line_arguments=args) options = Options(platform="linux", command_line_arguments=args)
parsed_environment = options.build_options(identifier=None).environment parsed_environment = options.build_options(identifier=None).environment
assert parsed_environment.as_dictionary(prev_environment={}) == {"EXAMPLE": env_var_value} assert parsed_environment.as_dictionary(prev_environment={}) == {"EXAMPLE": env_var_value}
@pytest.mark.parametrize(
"toml_assignment,result_value",
[
('TEST_VAR="simple_value"', "simple_value"),
# spaces
('TEST_VAR="simple value"', "simple value"),
# env var
('TEST_VAR="$PARAM"', "spam"),
('TEST_VAR="$PARAM $PARAM"', "spam spam"),
# env var extension
('TEST_VAR="before:$PARAM:after"', "before:spam:after"),
# env var extension with spaces
('TEST_VAR="before $PARAM after"', "before spam after"),
# literal $ - this test is just for reference, I'm not sure if this
# syntax will work if we change the TOML quoting behaviour
(r'TEST_VAR="before\\$after"', "before$after"),
],
)
def test_toml_environment_quoting(tmp_path: Path, toml_assignment, result_value):
args = get_default_command_line_arguments()
args.package_dir = tmp_path
tmp_path.joinpath("pyproject.toml").write_text(
textwrap.dedent(
f"""\
[tool.cibuildwheel.environment]
{toml_assignment}
"""
)
)
options = Options(platform="linux", command_line_arguments=args)
parsed_environment = options.build_options(identifier=None).environment
environment_values = parsed_environment.as_dictionary(
prev_environment={**os.environ, "PARAM": "spam"},
executor=local_environment_executor,
)
assert environment_values["TEST_VAR"] == result_value
+1
View File
@@ -10,6 +10,7 @@ def get_default_command_line_arguments() -> CommandLineArguments:
platform="auto", platform="auto",
allow_empty=False, allow_empty=False,
archs=None, archs=None,
only=None,
config_file="", config_file="",
output_dir=Path("wheelhouse"), output_dir=Path("wheelhouse"),
package_dir=Path("."), package_dir=Path("."),