Merge remote-tracking branch 'origin/main' into env-order
This commit is contained in:
@@ -62,6 +62,13 @@ jobs:
|
|||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get -y install podman
|
sudo apt-get -y install podman
|
||||||
|
|
||||||
|
# free some space to prevent reaching GHA disk space limits
|
||||||
|
- name: Clean docker images
|
||||||
|
if: runner.os == 'Linux'
|
||||||
|
run: |
|
||||||
|
docker system prune -a -f
|
||||||
|
df -h
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
python -m pip install ".[test]"
|
python -m pip install ".[test]"
|
||||||
@@ -103,7 +110,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
id: qemu
|
id: qemu
|
||||||
uses: docker/setup-qemu-action@v2
|
uses: docker/setup-qemu-action@v3
|
||||||
with:
|
with:
|
||||||
platforms: all
|
platforms: all
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ repos:
|
|||||||
- id: black
|
- id: black
|
||||||
|
|
||||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||||
rev: v0.0.288
|
rev: v0.0.290
|
||||||
hooks:
|
hooks:
|
||||||
- id: ruff
|
- id: ruff
|
||||||
args: ["--fix", "--show-fixes"]
|
args: ["--fix", "--show-fixes"]
|
||||||
|
|||||||
@@ -97,7 +97,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.15.0
|
run: python -m pip install cibuildwheel==2.16.0
|
||||||
|
|
||||||
- name: Build wheels
|
- name: Build wheels
|
||||||
run: python -m cibuildwheel --output-dir wheelhouse
|
run: python -m cibuildwheel --output-dir wheelhouse
|
||||||
@@ -213,6 +213,18 @@ 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.16.0
|
||||||
|
|
||||||
|
_18 September 2023_
|
||||||
|
|
||||||
|
- ✨ Add the ability to pass additional flags to a build frontend through the [CIBW_BUILD_FRONTEND](https://cibuildwheel.readthedocs.io/en/stable/options/#build-frontend) option (#1588).
|
||||||
|
- ✨ The environment variable SOURCE_DATE_EPOCH is now automatically passed through to container Linux builds (useful for [reproducible builds](https://reproducible-builds.org/docs/source-date-epoch/)!) (#1589)
|
||||||
|
- 🛠 Updates the prerelease CPython 3.12 version to 3.12.0rc2 (#1604)
|
||||||
|
- 🐛 Fix `requires_python` auto-detection from setup.py when the call to `setup()` is within an `if __name__ == "__main__" block (#1613)
|
||||||
|
- 🐛 Fix a bug that prevented building Linux wheels in Docker on a Windows host (#1573)
|
||||||
|
- 🐛 `--only` can now select prerelease-pythons (#1564)
|
||||||
|
- 📚 Docs & examples updates (#1582, #1593, #1598, #1615)
|
||||||
|
|
||||||
### v2.15.0
|
### v2.15.0
|
||||||
|
|
||||||
_8 August 2023_
|
_8 August 2023_
|
||||||
@@ -243,16 +255,6 @@ _10 June 2023_
|
|||||||
- 🛠 Updates the prerelease CPython 3.12 version to 3.12.0b2. (#1516)
|
- 🛠 Updates the prerelease CPython 3.12 version to 3.12.0b2. (#1516)
|
||||||
- 🛠 Adds a moving `v<major>.<minor>` tag for use in GitHub Actions workflow files. If you use this, you'll get the latest patch release within a minor version. Additionally, Dependabot won't send you PRs for patch releases. (#1517)
|
- 🛠 Adds a moving `v<major>.<minor>` tag for use in GitHub Actions workflow files. If you use this, you'll get the latest patch release within a minor version. Additionally, Dependabot won't send you PRs for patch releases. (#1517)
|
||||||
|
|
||||||
### v2.13.0
|
|
||||||
|
|
||||||
_28 May 2023_
|
|
||||||
|
|
||||||
- ✨ Adds CPython 3.12 support, under the prerelease flag [CIBW_PRERELEASE_PYTHONS](https://cibuildwheel.readthedocs.io/en/stable/options/#prerelease-pythons). This version of cibuildwheel uses 3.12.0b1.
|
|
||||||
|
|
||||||
While CPython is in beta, the ABI can change, so your wheels might not be compatible with the final release. For this reason, we don't recommend distributing wheels until RC1, at which point 3.12 will be available in cibuildwheel without the flag. (#1507)
|
|
||||||
|
|
||||||
- ✨ Adds the ability to pass arguments to the container engine when the container is created, using the [CIBW_CONTAINER_ENGINE](https://cibuildwheel.readthedocs.io/en/stable/options/#container-engine) option. (#1499)
|
|
||||||
|
|
||||||
<!-- END bin/update_readme_changelog.py -->
|
<!-- END bin/update_readme_changelog.py -->
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
__version__ = "2.15.0"
|
__version__ = "2.16.0"
|
||||||
|
|||||||
@@ -16,9 +16,9 @@ from .options import Options
|
|||||||
from .typing import PathOrStr
|
from .typing import PathOrStr
|
||||||
from .util import (
|
from .util import (
|
||||||
AlreadyBuiltWheelError,
|
AlreadyBuiltWheelError,
|
||||||
|
BuildFrontendConfig,
|
||||||
BuildSelector,
|
BuildSelector,
|
||||||
NonPlatformWheelError,
|
NonPlatformWheelError,
|
||||||
build_frontend_or_default,
|
|
||||||
find_compatible_wheel,
|
find_compatible_wheel,
|
||||||
get_build_verbosity_extra_flags,
|
get_build_verbosity_extra_flags,
|
||||||
prepare_command,
|
prepare_command,
|
||||||
@@ -177,7 +177,7 @@ def build_in_container(
|
|||||||
for config in platform_configs:
|
for config in platform_configs:
|
||||||
log.build_start(config.identifier)
|
log.build_start(config.identifier)
|
||||||
build_options = options.build_options(config.identifier)
|
build_options = options.build_options(config.identifier)
|
||||||
build_frontend = build_frontend_or_default(build_options.build_frontend)
|
build_frontend = build_options.build_frontend or BuildFrontendConfig("pip")
|
||||||
|
|
||||||
dependency_constraint_flags: list[PathOrStr] = []
|
dependency_constraint_flags: list[PathOrStr] = []
|
||||||
|
|
||||||
@@ -243,9 +243,10 @@ def build_in_container(
|
|||||||
container.call(["rm", "-rf", built_wheel_dir])
|
container.call(["rm", "-rf", built_wheel_dir])
|
||||||
container.call(["mkdir", "-p", built_wheel_dir])
|
container.call(["mkdir", "-p", built_wheel_dir])
|
||||||
|
|
||||||
extra_flags = split_config_settings(build_options.config_settings, build_frontend)
|
extra_flags = split_config_settings(build_options.config_settings, build_frontend.name)
|
||||||
|
extra_flags += build_frontend.args
|
||||||
|
|
||||||
if build_frontend == "pip":
|
if build_frontend.name == "pip":
|
||||||
extra_flags += get_build_verbosity_extra_flags(build_options.build_verbosity)
|
extra_flags += get_build_verbosity_extra_flags(build_options.build_verbosity)
|
||||||
container.call(
|
container.call(
|
||||||
[
|
[
|
||||||
@@ -260,7 +261,7 @@ def build_in_container(
|
|||||||
],
|
],
|
||||||
env=env,
|
env=env,
|
||||||
)
|
)
|
||||||
elif build_frontend == "build":
|
elif build_frontend.name == "build":
|
||||||
if not 0 <= build_options.build_verbosity < 2:
|
if not 0 <= build_options.build_verbosity < 2:
|
||||||
msg = f"build_verbosity {build_options.build_verbosity} is not supported for build frontend. Ignoring."
|
msg = f"build_verbosity {build_options.build_verbosity} is not supported for build frontend. Ignoring."
|
||||||
log.warning(msg)
|
log.warning(msg)
|
||||||
@@ -422,7 +423,7 @@ def build(options: Options, tmp_path: Path) -> None: # noqa: ARG001
|
|||||||
|
|
||||||
with OCIContainer(
|
with OCIContainer(
|
||||||
image=build_step.container_image,
|
image=build_step.container_image,
|
||||||
simulate_32_bit=build_step.platform_tag.endswith("i686"),
|
enforce_32_bit=build_step.platform_tag.endswith("i686"),
|
||||||
cwd=container_project_path,
|
cwd=container_project_path,
|
||||||
engine=options.globals.container_engine,
|
engine=options.globals.container_engine,
|
||||||
) as container:
|
) as container:
|
||||||
|
|||||||
+11
-8
@@ -25,10 +25,10 @@ from .typing import PathOrStr
|
|||||||
from .util import (
|
from .util import (
|
||||||
CIBW_CACHE_PATH,
|
CIBW_CACHE_PATH,
|
||||||
AlreadyBuiltWheelError,
|
AlreadyBuiltWheelError,
|
||||||
BuildFrontend,
|
BuildFrontendConfig,
|
||||||
|
BuildFrontendName,
|
||||||
BuildSelector,
|
BuildSelector,
|
||||||
NonPlatformWheelError,
|
NonPlatformWheelError,
|
||||||
build_frontend_or_default,
|
|
||||||
call,
|
call,
|
||||||
detect_ci_provider,
|
detect_ci_provider,
|
||||||
download,
|
download,
|
||||||
@@ -165,7 +165,7 @@ def setup_python(
|
|||||||
python_configuration: PythonConfiguration,
|
python_configuration: PythonConfiguration,
|
||||||
dependency_constraint_flags: Sequence[PathOrStr],
|
dependency_constraint_flags: Sequence[PathOrStr],
|
||||||
environment: ParsedEnvironment,
|
environment: ParsedEnvironment,
|
||||||
build_frontend: BuildFrontend,
|
build_frontend: BuildFrontendName,
|
||||||
) -> dict[str, str]:
|
) -> dict[str, str]:
|
||||||
tmp.mkdir()
|
tmp.mkdir()
|
||||||
implementation_id = python_configuration.identifier.split("-")[0]
|
implementation_id = python_configuration.identifier.split("-")[0]
|
||||||
@@ -334,7 +334,7 @@ def build(options: Options, tmp_path: Path) -> None:
|
|||||||
|
|
||||||
for config in python_configurations:
|
for config in python_configurations:
|
||||||
build_options = options.build_options(config.identifier)
|
build_options = options.build_options(config.identifier)
|
||||||
build_frontend = build_frontend_or_default(build_options.build_frontend)
|
build_frontend = build_options.build_frontend or BuildFrontendConfig("pip")
|
||||||
log.build_start(config.identifier)
|
log.build_start(config.identifier)
|
||||||
|
|
||||||
identifier_tmp_dir = tmp_path / config.identifier
|
identifier_tmp_dir = tmp_path / config.identifier
|
||||||
@@ -357,7 +357,7 @@ def build(options: Options, tmp_path: Path) -> None:
|
|||||||
config,
|
config,
|
||||||
dependency_constraint_flags,
|
dependency_constraint_flags,
|
||||||
build_options.environment,
|
build_options.environment,
|
||||||
build_frontend,
|
build_frontend.name,
|
||||||
)
|
)
|
||||||
|
|
||||||
compatible_wheel = find_compatible_wheel(built_wheels, config.identifier)
|
compatible_wheel = find_compatible_wheel(built_wheels, config.identifier)
|
||||||
@@ -378,9 +378,12 @@ def build(options: Options, tmp_path: Path) -> None:
|
|||||||
log.step("Building wheel...")
|
log.step("Building wheel...")
|
||||||
built_wheel_dir.mkdir()
|
built_wheel_dir.mkdir()
|
||||||
|
|
||||||
extra_flags = split_config_settings(build_options.config_settings, build_frontend)
|
extra_flags = split_config_settings(
|
||||||
|
build_options.config_settings, build_frontend.name
|
||||||
|
)
|
||||||
|
extra_flags += build_frontend.args
|
||||||
|
|
||||||
if build_frontend == "pip":
|
if build_frontend.name == "pip":
|
||||||
extra_flags += get_build_verbosity_extra_flags(build_options.build_verbosity)
|
extra_flags += get_build_verbosity_extra_flags(build_options.build_verbosity)
|
||||||
# Path.resolve() is needed. Without it pip wheel may try to fetch package from pypi.org
|
# Path.resolve() is needed. Without it pip wheel may try to fetch package from pypi.org
|
||||||
# see https://github.com/pypa/cibuildwheel/pull/369
|
# see https://github.com/pypa/cibuildwheel/pull/369
|
||||||
@@ -395,7 +398,7 @@ def build(options: Options, tmp_path: Path) -> None:
|
|||||||
*extra_flags,
|
*extra_flags,
|
||||||
env=env,
|
env=env,
|
||||||
)
|
)
|
||||||
elif build_frontend == "build":
|
elif build_frontend.name == "build":
|
||||||
if not 0 <= build_options.build_verbosity < 2:
|
if not 0 <= build_options.build_verbosity < 2:
|
||||||
msg = f"build_verbosity {build_options.build_verbosity} is not supported for build frontend. Ignoring."
|
msg = f"build_verbosity {build_options.build_verbosity} is not supported for build frontend. Ignoring."
|
||||||
log.warning(msg)
|
log.warning(msg)
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ from types import TracebackType
|
|||||||
from typing import IO, Dict, Literal
|
from typing import IO, Dict, Literal
|
||||||
|
|
||||||
from .typing import PathOrStr, PopenBytes
|
from .typing import PathOrStr, PopenBytes
|
||||||
from .util import CIProvider, detect_ci_provider, parse_key_value_string
|
from .util import CIProvider, call, detect_ci_provider, parse_key_value_string
|
||||||
|
|
||||||
ContainerEngineName = Literal["docker", "podman"]
|
ContainerEngineName = Literal["docker", "podman"]
|
||||||
|
|
||||||
@@ -29,7 +29,9 @@ class OCIContainerEngineConfig:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_config_string(config_string: str) -> OCIContainerEngineConfig:
|
def from_config_string(config_string: str) -> OCIContainerEngineConfig:
|
||||||
config_dict = parse_key_value_string(config_string, ["name"])
|
config_dict = parse_key_value_string(
|
||||||
|
config_string, ["name"], ["create_args", "create-args"]
|
||||||
|
)
|
||||||
name = " ".join(config_dict["name"])
|
name = " ".join(config_dict["name"])
|
||||||
if name not in {"docker", "podman"}:
|
if name not in {"docker", "podman"}:
|
||||||
msg = f"unknown container engine {name}"
|
msg = f"unknown container engine {name}"
|
||||||
@@ -83,7 +85,7 @@ class OCIContainer:
|
|||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
image: str,
|
image: str,
|
||||||
simulate_32_bit: bool = False,
|
enforce_32_bit: bool = False,
|
||||||
cwd: PathOrStr | None = None,
|
cwd: PathOrStr | None = None,
|
||||||
engine: OCIContainerEngineConfig = DEFAULT_ENGINE,
|
engine: OCIContainerEngineConfig = DEFAULT_ENGINE,
|
||||||
):
|
):
|
||||||
@@ -92,7 +94,7 @@ class OCIContainer:
|
|||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
||||||
self.image = image
|
self.image = image
|
||||||
self.simulate_32_bit = simulate_32_bit
|
self.enforce_32_bit = enforce_32_bit
|
||||||
self.cwd = cwd
|
self.cwd = cwd
|
||||||
self.name: str | None = None
|
self.name: str | None = None
|
||||||
self.engine = engine
|
self.engine = engine
|
||||||
@@ -108,13 +110,24 @@ class OCIContainer:
|
|||||||
if detect_ci_provider() == CIProvider.travis_ci and platform.machine() == "ppc64le":
|
if detect_ci_provider() == CIProvider.travis_ci and platform.machine() == "ppc64le":
|
||||||
network_args = ["--network=host"]
|
network_args = ["--network=host"]
|
||||||
|
|
||||||
shell_args = ["linux32", "/bin/bash"] if self.simulate_32_bit else ["/bin/bash"]
|
simulate_32_bit = False
|
||||||
|
if self.enforce_32_bit:
|
||||||
|
# If the architecture running the image is already the right one
|
||||||
|
# or the image entrypoint takes care of enforcing this, then we don't need to
|
||||||
|
# simulate this
|
||||||
|
container_machine = call(
|
||||||
|
self.engine.name, "run", "--rm", self.image, "uname", "-m", capture_stdout=True
|
||||||
|
).strip()
|
||||||
|
simulate_32_bit = container_machine != "i686"
|
||||||
|
|
||||||
|
shell_args = ["linux32", "/bin/bash"] if simulate_32_bit else ["/bin/bash"]
|
||||||
|
|
||||||
subprocess.run(
|
subprocess.run(
|
||||||
[
|
[
|
||||||
self.engine.name,
|
self.engine.name,
|
||||||
"create",
|
"create",
|
||||||
"--env=CIBUILDWHEEL",
|
"--env=CIBUILDWHEEL",
|
||||||
|
"--env=SOURCE_DATE_EPOCH",
|
||||||
f"--name={self.name}",
|
f"--name={self.name}",
|
||||||
"--interactive",
|
"--interactive",
|
||||||
"--volume=/:/host", # ignored on CircleCI
|
"--volume=/:/host", # ignored on CircleCI
|
||||||
|
|||||||
+14
-12
@@ -27,7 +27,7 @@ from .typing import PLATFORMS, PlatformName
|
|||||||
from .util import (
|
from .util import (
|
||||||
MANYLINUX_ARCHS,
|
MANYLINUX_ARCHS,
|
||||||
MUSLLINUX_ARCHS,
|
MUSLLINUX_ARCHS,
|
||||||
BuildFrontend,
|
BuildFrontendConfig,
|
||||||
BuildSelector,
|
BuildSelector,
|
||||||
DependencyConstraints,
|
DependencyConstraints,
|
||||||
TestSelector,
|
TestSelector,
|
||||||
@@ -92,7 +92,7 @@ class BuildOptions:
|
|||||||
test_requires: list[str]
|
test_requires: list[str]
|
||||||
test_extras: str
|
test_extras: str
|
||||||
build_verbosity: int
|
build_verbosity: int
|
||||||
build_frontend: BuildFrontend | Literal["default"]
|
build_frontend: BuildFrontendConfig | None
|
||||||
config_settings: str
|
config_settings: str
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -488,7 +488,6 @@ class Options:
|
|||||||
with self.reader.identifier(identifier):
|
with self.reader.identifier(identifier):
|
||||||
before_all = self.reader.get("before-all", sep=" && ")
|
before_all = self.reader.get("before-all", sep=" && ")
|
||||||
|
|
||||||
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": " "}
|
||||||
)
|
)
|
||||||
@@ -506,16 +505,19 @@ class Options:
|
|||||||
test_extras = self.reader.get("test-extras", sep=",")
|
test_extras = self.reader.get("test-extras", sep=",")
|
||||||
build_verbosity_str = self.reader.get("build-verbosity")
|
build_verbosity_str = self.reader.get("build-verbosity")
|
||||||
|
|
||||||
build_frontend: BuildFrontend | Literal["default"]
|
build_frontend_str = self.reader.get(
|
||||||
if build_frontend_str == "build":
|
"build-frontend",
|
||||||
build_frontend = "build"
|
env_plat=False,
|
||||||
elif build_frontend_str == "pip":
|
table={"item": "{k}:{v}", "sep": "; ", "quote": shlex.quote},
|
||||||
build_frontend = "pip"
|
)
|
||||||
elif build_frontend_str == "default":
|
build_frontend: BuildFrontendConfig | None
|
||||||
build_frontend = "default"
|
if not build_frontend_str or build_frontend_str == "default":
|
||||||
|
build_frontend = None
|
||||||
else:
|
else:
|
||||||
msg = f"cibuildwheel: Unrecognised build frontend {build_frontend_str!r}, only 'pip' and 'build' are supported"
|
try:
|
||||||
print(msg, file=sys.stderr)
|
build_frontend = BuildFrontendConfig.from_config_string(build_frontend_str)
|
||||||
|
except ValueError as e:
|
||||||
|
print(f"cibuildwheel: {e}", file=sys.stderr)
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -8,6 +8,43 @@ from pathlib import Path
|
|||||||
from ._compat import tomllib
|
from ._compat import tomllib
|
||||||
|
|
||||||
|
|
||||||
|
def get_parent(node: ast.AST | None, depth: int = 1) -> ast.AST | None:
|
||||||
|
for _ in range(depth):
|
||||||
|
node = getattr(node, "parent", None)
|
||||||
|
return node
|
||||||
|
|
||||||
|
|
||||||
|
def is_main(parent: ast.AST | None) -> bool:
|
||||||
|
if parent is None:
|
||||||
|
return False
|
||||||
|
|
||||||
|
# This would be much nicer with 3.10's pattern matching!
|
||||||
|
if not isinstance(parent, ast.If):
|
||||||
|
return False
|
||||||
|
if not isinstance(parent.test, ast.Compare):
|
||||||
|
return False
|
||||||
|
|
||||||
|
try:
|
||||||
|
(op,) = parent.test.ops
|
||||||
|
(comp,) = parent.test.comparators
|
||||||
|
except ValueError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if not isinstance(op, ast.Eq):
|
||||||
|
return False
|
||||||
|
|
||||||
|
values = {comp, parent.test.left}
|
||||||
|
|
||||||
|
mains = {x for x in values if isinstance(x, ast.Constant) and x.value == "__main__"}
|
||||||
|
if len(mains) != 1:
|
||||||
|
return False
|
||||||
|
consts = {x for x in values if isinstance(x, ast.Name) and x.id == "__name__"}
|
||||||
|
if len(consts) != 1:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
class Analyzer(ast.NodeVisitor):
|
class Analyzer(ast.NodeVisitor):
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.requires_python: str | None = None
|
self.requires_python: str | None = None
|
||||||
@@ -19,13 +56,22 @@ class Analyzer(ast.NodeVisitor):
|
|||||||
super().visit(node)
|
super().visit(node)
|
||||||
|
|
||||||
def visit_keyword(self, node: ast.keyword) -> None:
|
def visit_keyword(self, node: ast.keyword) -> None:
|
||||||
|
# Must not be nested except for if __name__ == "__main__"
|
||||||
|
|
||||||
self.generic_visit(node)
|
self.generic_visit(node)
|
||||||
# Must not be nested in an if or other structure
|
|
||||||
# This will be Module -> Expr -> Call -> keyword
|
# This will be Module -> Expr -> Call -> keyword
|
||||||
|
parent = get_parent(node, 4)
|
||||||
|
unnested = parent is None
|
||||||
|
|
||||||
|
# This will be Module -> If -> Expr -> Call -> keyword
|
||||||
|
name_main_unnested = (
|
||||||
|
parent is not None and get_parent(parent) is None and is_main(get_parent(node, 3))
|
||||||
|
)
|
||||||
|
|
||||||
if (
|
if (
|
||||||
node.arg == "python_requires"
|
node.arg == "python_requires"
|
||||||
and not hasattr(node.parent.parent.parent, "parent") # type: ignore[attr-defined]
|
|
||||||
and isinstance(node.value, ast.Constant)
|
and isinstance(node.value, ast.Constant)
|
||||||
|
and (unnested or name_main_unnested)
|
||||||
):
|
):
|
||||||
self.requires_python = node.value.value
|
self.requires_python = node.value.value
|
||||||
|
|
||||||
|
|||||||
+38
-11
@@ -57,16 +57,6 @@ install_certifi_script: Final[Path] = resources_dir / "install_certifi.py"
|
|||||||
|
|
||||||
test_fail_cwd_file: Final[Path] = resources_dir / "testing_temp_dir_file.py"
|
test_fail_cwd_file: Final[Path] = resources_dir / "testing_temp_dir_file.py"
|
||||||
|
|
||||||
BuildFrontend = Literal["pip", "build"]
|
|
||||||
|
|
||||||
|
|
||||||
def build_frontend_or_default(
|
|
||||||
setting: BuildFrontend | Literal["default"], default: BuildFrontend = "pip"
|
|
||||||
) -> BuildFrontend:
|
|
||||||
if setting == "default":
|
|
||||||
return default
|
|
||||||
return setting
|
|
||||||
|
|
||||||
|
|
||||||
MANYLINUX_ARCHS: Final[tuple[str, ...]] = (
|
MANYLINUX_ARCHS: Final[tuple[str, ...]] = (
|
||||||
"x86_64",
|
"x86_64",
|
||||||
@@ -376,6 +366,34 @@ class DependencyConstraints:
|
|||||||
return self.base_file_path.name
|
return self.base_file_path.name
|
||||||
|
|
||||||
|
|
||||||
|
BuildFrontendName = Literal["pip", "build"]
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class BuildFrontendConfig:
|
||||||
|
name: BuildFrontendName
|
||||||
|
args: Sequence[str] = ()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_config_string(config_string: str) -> BuildFrontendConfig:
|
||||||
|
config_dict = parse_key_value_string(config_string, ["name"], ["args"])
|
||||||
|
name = " ".join(config_dict["name"])
|
||||||
|
if name not in {"pip", "build"}:
|
||||||
|
msg = f"Unrecognised build frontend {name}, only 'pip' and 'build' are supported"
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
|
name = typing.cast(BuildFrontendName, name)
|
||||||
|
|
||||||
|
args = config_dict.get("args") or []
|
||||||
|
return BuildFrontendConfig(name=name, args=args)
|
||||||
|
|
||||||
|
def options_summary(self) -> str | dict[str, str]:
|
||||||
|
if not self.args:
|
||||||
|
return self.name
|
||||||
|
else:
|
||||||
|
return {"name": self.name, "args": repr(self.args)}
|
||||||
|
|
||||||
|
|
||||||
class NonPlatformWheelError(Exception):
|
class NonPlatformWheelError(Exception):
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
message = textwrap.dedent(
|
message = textwrap.dedent(
|
||||||
@@ -699,13 +717,19 @@ def fix_ansi_codes_for_github_actions(text: str) -> str:
|
|||||||
|
|
||||||
|
|
||||||
def parse_key_value_string(
|
def parse_key_value_string(
|
||||||
key_value_string: str, positional_arg_names: list[str] | None = None
|
key_value_string: str,
|
||||||
|
positional_arg_names: Sequence[str] | None = None,
|
||||||
|
kw_arg_names: Sequence[str] | None = None,
|
||||||
) -> dict[str, list[str]]:
|
) -> dict[str, list[str]]:
|
||||||
"""
|
"""
|
||||||
Parses a string like "docker; create_args: --some-option=value another-option"
|
Parses a string like "docker; create_args: --some-option=value another-option"
|
||||||
"""
|
"""
|
||||||
if positional_arg_names is None:
|
if positional_arg_names is None:
|
||||||
positional_arg_names = []
|
positional_arg_names = []
|
||||||
|
if kw_arg_names is None:
|
||||||
|
kw_arg_names = []
|
||||||
|
|
||||||
|
all_field_names = [*positional_arg_names, *kw_arg_names]
|
||||||
|
|
||||||
shlexer = shlex.shlex(key_value_string, posix=True, punctuation_chars=";:")
|
shlexer = shlex.shlex(key_value_string, posix=True, punctuation_chars=";:")
|
||||||
shlexer.commenters = ""
|
shlexer.commenters = ""
|
||||||
@@ -721,6 +745,9 @@ def parse_key_value_string(
|
|||||||
if len(field) > 1 and field[1] == ":":
|
if len(field) > 1 and field[1] == ":":
|
||||||
field_name = field[0]
|
field_name = field[0]
|
||||||
values = field[2:]
|
values = field[2:]
|
||||||
|
if field_name not in all_field_names:
|
||||||
|
msg = f"Failed to parse {key_value_string!r}. Unknown field name {field_name!r}"
|
||||||
|
raise ValueError(msg)
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
field_name = positional_arg_names[field_i]
|
field_name = positional_arg_names[field_i]
|
||||||
|
|||||||
+11
-8
@@ -25,10 +25,10 @@ from .typing import PathOrStr
|
|||||||
from .util import (
|
from .util import (
|
||||||
CIBW_CACHE_PATH,
|
CIBW_CACHE_PATH,
|
||||||
AlreadyBuiltWheelError,
|
AlreadyBuiltWheelError,
|
||||||
BuildFrontend,
|
BuildFrontendConfig,
|
||||||
|
BuildFrontendName,
|
||||||
BuildSelector,
|
BuildSelector,
|
||||||
NonPlatformWheelError,
|
NonPlatformWheelError,
|
||||||
build_frontend_or_default,
|
|
||||||
call,
|
call,
|
||||||
download,
|
download,
|
||||||
find_compatible_wheel,
|
find_compatible_wheel,
|
||||||
@@ -216,7 +216,7 @@ def setup_python(
|
|||||||
python_configuration: PythonConfiguration,
|
python_configuration: PythonConfiguration,
|
||||||
dependency_constraint_flags: Sequence[PathOrStr],
|
dependency_constraint_flags: Sequence[PathOrStr],
|
||||||
environment: ParsedEnvironment,
|
environment: ParsedEnvironment,
|
||||||
build_frontend: BuildFrontend,
|
build_frontend: BuildFrontendName,
|
||||||
) -> dict[str, str]:
|
) -> dict[str, str]:
|
||||||
tmp.mkdir()
|
tmp.mkdir()
|
||||||
implementation_id = python_configuration.identifier.split("-")[0]
|
implementation_id = python_configuration.identifier.split("-")[0]
|
||||||
@@ -369,7 +369,7 @@ def build(options: Options, tmp_path: Path) -> None:
|
|||||||
|
|
||||||
for config in python_configurations:
|
for config in python_configurations:
|
||||||
build_options = options.build_options(config.identifier)
|
build_options = options.build_options(config.identifier)
|
||||||
build_frontend = build_frontend_or_default(build_options.build_frontend)
|
build_frontend = build_options.build_frontend or BuildFrontendConfig("pip")
|
||||||
log.build_start(config.identifier)
|
log.build_start(config.identifier)
|
||||||
|
|
||||||
identifier_tmp_dir = tmp_path / config.identifier
|
identifier_tmp_dir = tmp_path / config.identifier
|
||||||
@@ -390,7 +390,7 @@ def build(options: Options, tmp_path: Path) -> None:
|
|||||||
config,
|
config,
|
||||||
dependency_constraint_flags,
|
dependency_constraint_flags,
|
||||||
build_options.environment,
|
build_options.environment,
|
||||||
build_frontend,
|
build_frontend.name,
|
||||||
)
|
)
|
||||||
|
|
||||||
compatible_wheel = find_compatible_wheel(built_wheels, config.identifier)
|
compatible_wheel = find_compatible_wheel(built_wheels, config.identifier)
|
||||||
@@ -414,9 +414,12 @@ def build(options: Options, tmp_path: Path) -> None:
|
|||||||
log.step("Building wheel...")
|
log.step("Building wheel...")
|
||||||
built_wheel_dir.mkdir()
|
built_wheel_dir.mkdir()
|
||||||
|
|
||||||
extra_flags = split_config_settings(build_options.config_settings, build_frontend)
|
extra_flags = split_config_settings(
|
||||||
|
build_options.config_settings, build_frontend.name
|
||||||
|
)
|
||||||
|
extra_flags += build_frontend.args
|
||||||
|
|
||||||
if build_frontend == "pip":
|
if build_frontend.name == "pip":
|
||||||
extra_flags += get_build_verbosity_extra_flags(build_options.build_verbosity)
|
extra_flags += get_build_verbosity_extra_flags(build_options.build_verbosity)
|
||||||
# Path.resolve() is needed. Without it pip wheel may try to fetch package from pypi.org
|
# Path.resolve() is needed. Without it pip wheel may try to fetch package from pypi.org
|
||||||
# see https://github.com/pypa/cibuildwheel/pull/369
|
# see https://github.com/pypa/cibuildwheel/pull/369
|
||||||
@@ -431,7 +434,7 @@ def build(options: Options, tmp_path: Path) -> None:
|
|||||||
*extra_flags,
|
*extra_flags,
|
||||||
env=env,
|
env=env,
|
||||||
)
|
)
|
||||||
elif build_frontend == "build":
|
elif build_frontend.name == "build":
|
||||||
if not 0 <= build_options.build_verbosity < 2:
|
if not 0 <= build_options.build_verbosity < 2:
|
||||||
msg = f"build_verbosity {build_options.build_verbosity} is not supported for build frontend. Ignoring."
|
msg = f"build_verbosity {build_options.build_verbosity} is not supported for build frontend. Ignoring."
|
||||||
log.warning(msg)
|
log.warning(msg)
|
||||||
|
|||||||
@@ -4,6 +4,18 @@ title: Changelog
|
|||||||
|
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
### v2.16.0
|
||||||
|
|
||||||
|
_18 September 2023_
|
||||||
|
|
||||||
|
- ✨ Add the ability to pass additional flags to a build frontend through the [CIBW_BUILD_FRONTEND](https://cibuildwheel.readthedocs.io/en/stable/options/#build-frontend) option (#1588).
|
||||||
|
- ✨ The environment variable SOURCE_DATE_EPOCH is now automatically passed through to container Linux builds (useful for [reproducible builds](https://reproducible-builds.org/docs/source-date-epoch/)!) (#1589)
|
||||||
|
- 🛠 Updates the prerelease CPython 3.12 version to 3.12.0rc2 (#1604)
|
||||||
|
- 🐛 Fix `requires_python` auto-detection from setup.py when the call to `setup()` is within an `if __name__ == "__main__" block (#1613)
|
||||||
|
- 🐛 Fix a bug that prevented building Linux wheels in Docker on a Windows host (#1573)
|
||||||
|
- 🐛 `--only` can now select prerelease-pythons (#1564)
|
||||||
|
- 📚 Docs & examples updates (#1582, #1593, #1598, #1615)
|
||||||
|
|
||||||
### v2.15.0
|
### v2.15.0
|
||||||
|
|
||||||
_8 August 2023_
|
_8 August 2023_
|
||||||
|
|||||||
+3
-3
@@ -159,7 +159,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.15.0
|
uses: pypa/cibuildwheel@v2.16.0
|
||||||
```
|
```
|
||||||
|
|
||||||
This is a composite step that just runs cibuildwheel using pipx. You can set command-line options as `with:` parameters, and use `env:` as normal.
|
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.
|
||||||
@@ -181,7 +181,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.15.0
|
cibuildwheel==2.16.0
|
||||||
```
|
```
|
||||||
|
|
||||||
Then your install step would have `python -m pip install -r requirements-cibw.txt` in it. Your `.github/dependabot.yml` file could look like this:
|
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:
|
||||||
@@ -325,7 +325,7 @@ Solutions to this vary, but the simplest is to use pipx:
|
|||||||
# most runners have pipx preinstalled, but in case you don't
|
# most runners have pipx preinstalled, but in case you don't
|
||||||
python3 -m pip install pipx
|
python3 -m pip install pipx
|
||||||
|
|
||||||
pipx run cibuildwheel==2.15.0 --output-dir wheelhouse
|
pipx run cibuildwheel==2.16.0 --output-dir wheelhouse
|
||||||
pipx run twine upload wheelhouse/*.whl
|
pipx run twine upload wheelhouse/*.whl
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
+20
-1
@@ -504,9 +504,19 @@ This option can also be set using the [command-line option](#command-line) `--pr
|
|||||||
### `CIBW_BUILD_FRONTEND` {: #build-frontend}
|
### `CIBW_BUILD_FRONTEND` {: #build-frontend}
|
||||||
> Set the tool to use to build, either "pip" (default for now) or "build"
|
> Set the tool to use to build, either "pip" (default for now) or "build"
|
||||||
|
|
||||||
Choose which build backend to use. Can either be "pip", which will run
|
Options:
|
||||||
|
|
||||||
|
- `pip[;args: ...]`
|
||||||
|
- `build[;args: ...]`
|
||||||
|
|
||||||
|
Default: `pip`
|
||||||
|
|
||||||
|
Choose which build frontend to use. Can either be "pip", which will run
|
||||||
`python -m pip wheel`, or "build", which will run `python -m build --wheel`.
|
`python -m pip wheel`, or "build", which will run `python -m build --wheel`.
|
||||||
|
|
||||||
|
You can specify extra arguments to pass to `pip wheel` or `build` using the
|
||||||
|
optional `args` option.
|
||||||
|
|
||||||
!!! tip
|
!!! tip
|
||||||
Until v2.0.0, [pip] was the only way to build wheels, and is still the
|
Until v2.0.0, [pip] was the only way to build wheels, and is still the
|
||||||
default. However, we expect that at some point in the future, cibuildwheel
|
default. However, we expect that at some point in the future, cibuildwheel
|
||||||
@@ -526,6 +536,9 @@ Choose which build backend to use. Can either be "pip", which will run
|
|||||||
|
|
||||||
# Ensure pip is used even if the default changes in the future
|
# Ensure pip is used even if the default changes in the future
|
||||||
CIBW_BUILD_FRONTEND: "pip"
|
CIBW_BUILD_FRONTEND: "pip"
|
||||||
|
|
||||||
|
# supply an extra argument to 'pip wheel'
|
||||||
|
CIBW_BUILD_FRONTEND: "pip; args: --no-build-isolation"
|
||||||
```
|
```
|
||||||
|
|
||||||
!!! tab examples "pyproject.toml"
|
!!! tab examples "pyproject.toml"
|
||||||
@@ -537,6 +550,9 @@ Choose which build backend to use. Can either be "pip", which will run
|
|||||||
|
|
||||||
# Ensure pip is used even if the default changes in the future
|
# Ensure pip is used even if the default changes in the future
|
||||||
build-frontend = "pip"
|
build-frontend = "pip"
|
||||||
|
|
||||||
|
# supply an extra argument to 'pip wheel'
|
||||||
|
build-frontend = { name = "pip", args = ["--no-build-isolation"] }
|
||||||
```
|
```
|
||||||
|
|
||||||
### `CIBW_CONFIG_SETTINGS` {: #config-settings}
|
### `CIBW_CONFIG_SETTINGS` {: #config-settings}
|
||||||
@@ -664,6 +680,9 @@ A list of environment variables to pass into the linux container during the buil
|
|||||||
|
|
||||||
To specify more than one environment variable, separate the variable names by spaces.
|
To specify more than one environment variable, separate the variable names by spaces.
|
||||||
|
|
||||||
|
!!! note
|
||||||
|
cibuildwheel automatically passes the environment variable [`SOURCE_DATE_EPOCH`](https://reproducible-builds.org/docs/source-date-epoch/) if defined.
|
||||||
|
|
||||||
#### Examples
|
#### Examples
|
||||||
|
|
||||||
!!! tab examples "Environment passthrough"
|
!!! tab examples "Environment passthrough"
|
||||||
|
|||||||
+2
-2
@@ -184,7 +184,7 @@ To build Linux, Mac, and Windows wheels using GitHub Actions, create a `.github/
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Build wheels
|
- name: Build wheels
|
||||||
run: pipx run cibuildwheel==2.15.0
|
run: pipx run cibuildwheel==2.16.0
|
||||||
|
|
||||||
- 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.15.0
|
run: python -m pip install cibuildwheel==2.16.0
|
||||||
|
|
||||||
- name: Build wheels
|
- name: Build wheels
|
||||||
run: python -m cibuildwheel --output-dir wheelhouse
|
run: python -m cibuildwheel --output-dir wheelhouse
|
||||||
|
|||||||
@@ -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.15.0
|
install: python -m pip install cibuildwheel==2.16.0
|
||||||
|
|
||||||
build_script: python -m cibuildwheel --output-dir wheelhouse
|
build_script: python -m cibuildwheel --output-dir wheelhouse
|
||||||
|
|
||||||
|
|||||||
@@ -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.15.0
|
pip3 install cibuildwheel==2.16.0
|
||||||
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.15.0
|
python3 -m pip install cibuildwheel==2.16.0
|
||||||
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.15.0
|
pip install cibuildwheel==2.16.0
|
||||||
displayName: Install dependencies
|
displayName: Install dependencies
|
||||||
- bash: cibuildwheel --output-dir wheelhouse .
|
- bash: cibuildwheel --output-dir wheelhouse .
|
||||||
displayName: Build wheels
|
displayName: Build wheels
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ jobs:
|
|||||||
- run:
|
- run:
|
||||||
name: Build the Linux wheels.
|
name: Build the Linux wheels.
|
||||||
command: |
|
command: |
|
||||||
pip3 install --user cibuildwheel==2.15.0
|
pip3 install --user cibuildwheel==2.16.0
|
||||||
cibuildwheel --output-dir wheelhouse
|
cibuildwheel --output-dir wheelhouse
|
||||||
- store_artifacts:
|
- store_artifacts:
|
||||||
path: wheelhouse/
|
path: wheelhouse/
|
||||||
@@ -28,7 +28,7 @@ jobs:
|
|||||||
- run:
|
- run:
|
||||||
name: Build the Linux aarch64 wheels.
|
name: Build the Linux aarch64 wheels.
|
||||||
command: |
|
command: |
|
||||||
python3 -m pip install --user cibuildwheel==2.15.0
|
python3 -m pip install --user cibuildwheel==2.16.0
|
||||||
python3 -m cibuildwheel --output-dir wheelhouse
|
python3 -m cibuildwheel --output-dir wheelhouse
|
||||||
- store_artifacts:
|
- store_artifacts:
|
||||||
path: wheelhouse/
|
path: wheelhouse/
|
||||||
@@ -42,7 +42,7 @@ jobs:
|
|||||||
- run:
|
- run:
|
||||||
name: Build the OS X wheels.
|
name: Build the OS X wheels.
|
||||||
command: |
|
command: |
|
||||||
pip3 install cibuildwheel==2.15.0
|
pip3 install cibuildwheel==2.16.0
|
||||||
cibuildwheel --output-dir wheelhouse
|
cibuildwheel --output-dir wheelhouse
|
||||||
- store_artifacts:
|
- store_artifacts:
|
||||||
path: wheelhouse/
|
path: wheelhouse/
|
||||||
|
|||||||
@@ -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.15.0
|
- python -m pip install cibuildwheel==2.16.0
|
||||||
run_cibuildwheel_script:
|
run_cibuildwheel_script:
|
||||||
- cibuildwheel
|
- cibuildwheel
|
||||||
wheels_artifacts:
|
wheels_artifacts:
|
||||||
|
|||||||
@@ -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.15.0
|
- python -m pip install cibuildwheel==2.16.0
|
||||||
run_cibuildwheel_script:
|
run_cibuildwheel_script:
|
||||||
- cibuildwheel
|
- cibuildwheel
|
||||||
wheels_artifacts:
|
wheels_artifacts:
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Build wheels
|
- name: Build wheels
|
||||||
uses: pypa/cibuildwheel@v2.15.0
|
uses: pypa/cibuildwheel@v2.16.0
|
||||||
env:
|
env:
|
||||||
CIBW_ARCHS_MACOS: x86_64 arm64
|
CIBW_ARCHS_MACOS: x86_64 arm64
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Build wheels
|
- name: Build wheels
|
||||||
uses: pypa/cibuildwheel@v2.15.0
|
uses: pypa/cibuildwheel@v2.16.0
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v3
|
- uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Build wheels
|
- name: Build wheels
|
||||||
uses: pypa/cibuildwheel@v2.15.0
|
uses: pypa/cibuildwheel@v2.16.0
|
||||||
# env:
|
# env:
|
||||||
# CIBW_SOME_OPTION: value
|
# CIBW_SOME_OPTION: value
|
||||||
# ...
|
# ...
|
||||||
|
|||||||
@@ -15,12 +15,12 @@ jobs:
|
|||||||
|
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
if: runner.os == 'Linux'
|
if: runner.os == 'Linux'
|
||||||
uses: docker/setup-qemu-action@v2
|
uses: docker/setup-qemu-action@v3
|
||||||
with:
|
with:
|
||||||
platforms: all
|
platforms: all
|
||||||
|
|
||||||
- name: Build wheels
|
- name: Build wheels
|
||||||
uses: pypa/cibuildwheel@v2.15.0
|
uses: pypa/cibuildwheel@v2.16.0
|
||||||
env:
|
env:
|
||||||
# configure cibuildwheel to build native archs ('auto'), and some
|
# configure cibuildwheel to build native archs ('auto'), and some
|
||||||
# emulated ones
|
# emulated ones
|
||||||
|
|||||||
@@ -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.15.0
|
- python -m pip install cibuildwheel==2.16.0
|
||||||
- cibuildwheel --output-dir wheelhouse
|
- cibuildwheel --output-dir wheelhouse
|
||||||
artifacts:
|
artifacts:
|
||||||
paths:
|
paths:
|
||||||
@@ -23,7 +23,7 @@ windows:
|
|||||||
before_script:
|
before_script:
|
||||||
- choco install python -y --version 3.8.6
|
- choco install python -y --version 3.8.6
|
||||||
- choco install git.install -y
|
- choco install git.install -y
|
||||||
- py -m pip install cibuildwheel==2.15.0
|
- py -m pip install cibuildwheel==2.16.0
|
||||||
script:
|
script:
|
||||||
- py -m cibuildwheel --output-dir wheelhouse --platform windows
|
- py -m cibuildwheel --output-dir wheelhouse --platform windows
|
||||||
artifacts:
|
artifacts:
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ linux:
|
|||||||
- curl -sSL https://get.docker.com/ | sh
|
- curl -sSL https://get.docker.com/ | sh
|
||||||
# Warning: This is extremely slow, be careful with how many wheels you build
|
# Warning: This is extremely slow, be careful with how many wheels you build
|
||||||
- docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
|
- docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
|
||||||
- python -m pip install cibuildwheel==2.15.0
|
- python -m pip install cibuildwheel==2.16.0
|
||||||
# Assuming your CI runner's default architecture is x86_64...
|
# Assuming your CI runner's default architecture is x86_64...
|
||||||
- cibuildwheel --output-dir wheelhouse --platform linux --archs aarch64
|
- cibuildwheel --output-dir wheelhouse --platform linux --archs aarch64
|
||||||
artifacts:
|
artifacts:
|
||||||
|
|||||||
@@ -20,7 +20,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.15.0
|
- python3 -m pip install cibuildwheel==2.16.0
|
||||||
|
|
||||||
script:
|
script:
|
||||||
# build the wheels, put them into './dist'
|
# build the wheels, put them into './dist'
|
||||||
|
|||||||
@@ -26,7 +26,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.15.0
|
- python3 -m pip install cibuildwheel==2.16.0
|
||||||
|
|
||||||
script:
|
script:
|
||||||
# build the wheels, put them into './wheelhouse'
|
# build the wheels, put them into './wheelhouse'
|
||||||
|
|||||||
@@ -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.15.0 twine
|
install: python3 -m pip install cibuildwheel==2.16.0 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.15.0 twine
|
install: python3 -m pip install cibuildwheel==2.16.0 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,6 +1,6 @@
|
|||||||
[metadata]
|
[metadata]
|
||||||
name = cibuildwheel
|
name = cibuildwheel
|
||||||
version = 2.15.0
|
version = 2.16.0
|
||||||
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
|
||||||
|
|||||||
+2
-6
@@ -34,6 +34,8 @@ def build_frontend_env(request) -> dict[str, str]:
|
|||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def docker_cleanup() -> Generator[None, None, None]:
|
def docker_cleanup() -> Generator[None, None, None]:
|
||||||
def get_images() -> set[str]:
|
def get_images() -> set[str]:
|
||||||
|
if detect_ci_provider() is None or platform != "linux":
|
||||||
|
return set()
|
||||||
images = subprocess.run(
|
images = subprocess.run(
|
||||||
["docker", "image", "ls", "--format", "{{json .ID}}"],
|
["docker", "image", "ls", "--format", "{{json .ID}}"],
|
||||||
text=True,
|
text=True,
|
||||||
@@ -42,12 +44,6 @@ def docker_cleanup() -> Generator[None, None, None]:
|
|||||||
).stdout
|
).stdout
|
||||||
return {json.loads(image.strip()) for image in images.splitlines() if image.strip()}
|
return {json.loads(image.strip()) for image in images.splitlines() if image.strip()}
|
||||||
|
|
||||||
if detect_ci_provider() is None or platform != "linux":
|
|
||||||
try:
|
|
||||||
yield
|
|
||||||
finally:
|
|
||||||
pass
|
|
||||||
return
|
|
||||||
images_before = get_images()
|
images_before = get_images()
|
||||||
try:
|
try:
|
||||||
yield
|
yield
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import subprocess
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from . import utils
|
||||||
|
from .test_projects.c import new_c_project
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("frontend_name", ["pip", "build"])
|
||||||
|
def test_build_frontend_args(tmp_path, capfd, frontend_name):
|
||||||
|
project = new_c_project()
|
||||||
|
project_dir = tmp_path / "project"
|
||||||
|
project.generate(project_dir)
|
||||||
|
|
||||||
|
# the build will fail because the frontend is called with '-h' - it prints the help message
|
||||||
|
with pytest.raises(subprocess.CalledProcessError):
|
||||||
|
utils.cibuildwheel_run(
|
||||||
|
project_dir,
|
||||||
|
add_env={
|
||||||
|
"CIBW_BUILD": "cp311-*",
|
||||||
|
"CIBW_BUILD_FRONTEND": f"{frontend_name}; args: -h",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
captured = capfd.readouterr()
|
||||||
|
print(captured.out)
|
||||||
|
|
||||||
|
# check that the help message was printed
|
||||||
|
if frontend_name == "pip":
|
||||||
|
assert "Usage:" in captured.out
|
||||||
|
assert "Wheel Options:" in captured.out
|
||||||
|
else:
|
||||||
|
assert "usage:" in captured.out
|
||||||
|
assert "A simple, correct Python build frontend." in captured.out
|
||||||
@@ -365,7 +365,7 @@ def test_defaults(platform, intercepted_build_args):
|
|||||||
if isinstance(repair_wheel_default, list):
|
if isinstance(repair_wheel_default, list):
|
||||||
repair_wheel_default = " && ".join(repair_wheel_default)
|
repair_wheel_default = " && ".join(repair_wheel_default)
|
||||||
assert build_options.repair_command == repair_wheel_default
|
assert build_options.repair_command == repair_wheel_default
|
||||||
assert build_options.build_frontend == defaults["build-frontend"]
|
assert build_options.build_frontend is None
|
||||||
|
|
||||||
if platform == "linux":
|
if platform == "linux":
|
||||||
assert build_options.manylinux_images
|
assert build_options.manylinux_images
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import json
|
||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
import random
|
import random
|
||||||
@@ -13,33 +14,49 @@ import tomli_w
|
|||||||
|
|
||||||
from cibuildwheel.environment import EnvironmentAssignmentBash
|
from cibuildwheel.environment import EnvironmentAssignmentBash
|
||||||
from cibuildwheel.oci_container import OCIContainer, OCIContainerEngineConfig
|
from cibuildwheel.oci_container import OCIContainer, OCIContainerEngineConfig
|
||||||
|
from cibuildwheel.util import detect_ci_provider
|
||||||
|
|
||||||
# Test utilities
|
# Test utilities
|
||||||
|
|
||||||
# for these tests we use manylinux2014 images, because they're available on
|
# for these tests we use manylinux2014 images, because they're available on
|
||||||
# multi architectures and include python3.8
|
# multi architectures and include python3.8
|
||||||
|
DEFAULT_IMAGE_TEMPLATE = "quay.io/pypa/manylinux2014_{machine}:2023-09-04-0828984"
|
||||||
pm = platform.machine()
|
pm = platform.machine()
|
||||||
if pm == "x86_64":
|
if pm in {"x86_64", "ppc64le", "s390x"}:
|
||||||
DEFAULT_IMAGE = "quay.io/pypa/manylinux2014_x86_64:2020-05-17-2f8ac3b"
|
DEFAULT_IMAGE = DEFAULT_IMAGE_TEMPLATE.format(machine=pm)
|
||||||
elif pm in {"aarch64", "arm64"}:
|
elif pm in {"aarch64", "arm64"}:
|
||||||
DEFAULT_IMAGE = "quay.io/pypa/manylinux2014_aarch64:2020-05-17-2f8ac3b"
|
DEFAULT_IMAGE = DEFAULT_IMAGE_TEMPLATE.format(machine="aarch64")
|
||||||
elif pm == "ppc64le":
|
|
||||||
DEFAULT_IMAGE = "quay.io/pypa/manylinux2014_ppc64le:2020-05-17-2f8ac3b"
|
|
||||||
elif pm == "s390x":
|
|
||||||
DEFAULT_IMAGE = "quay.io/pypa/manylinux2014_s390x:2020-05-17-2f8ac3b"
|
|
||||||
else:
|
else:
|
||||||
DEFAULT_IMAGE = ""
|
DEFAULT_IMAGE = ""
|
||||||
|
|
||||||
PODMAN = OCIContainerEngineConfig(name="podman")
|
PODMAN = OCIContainerEngineConfig(name="podman")
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(params=["docker", "podman"])
|
@pytest.fixture(params=["docker", "podman"], scope="module")
|
||||||
def container_engine(request):
|
def container_engine(request):
|
||||||
if request.param == "docker" and not request.config.getoption("--run-docker"):
|
if request.param == "docker" and not request.config.getoption("--run-docker"):
|
||||||
pytest.skip("need --run-docker option to run")
|
pytest.skip("need --run-docker option to run")
|
||||||
if request.param == "podman" and not request.config.getoption("--run-podman"):
|
if request.param == "podman" and not request.config.getoption("--run-podman"):
|
||||||
pytest.skip("need --run-podman option to run")
|
pytest.skip("need --run-podman option to run")
|
||||||
return OCIContainerEngineConfig(name=request.param)
|
|
||||||
|
def get_images() -> set[str]:
|
||||||
|
if detect_ci_provider() is None:
|
||||||
|
return set()
|
||||||
|
images = subprocess.run(
|
||||||
|
[request.param, "image", "ls", "--format", "{{json .ID}}"],
|
||||||
|
text=True,
|
||||||
|
check=True,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
).stdout
|
||||||
|
return {json.loads(image.strip()) for image in images.splitlines() if image.strip()}
|
||||||
|
|
||||||
|
images_before = get_images()
|
||||||
|
try:
|
||||||
|
yield OCIContainerEngineConfig(name=request.param)
|
||||||
|
finally:
|
||||||
|
images_after = get_images()
|
||||||
|
for image in images_after - images_before:
|
||||||
|
subprocess.run([request.param, "rmi", image], check=False)
|
||||||
|
|
||||||
|
|
||||||
# Tests
|
# Tests
|
||||||
@@ -72,6 +89,17 @@ def test_environment(container_engine):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_environment_pass(container_engine, monkeypatch):
|
||||||
|
monkeypatch.setenv("CIBUILDWHEEL", "1")
|
||||||
|
monkeypatch.setenv("SOURCE_DATE_EPOCH", "1489957071")
|
||||||
|
with OCIContainer(engine=container_engine, image=DEFAULT_IMAGE) as container:
|
||||||
|
assert container.call(["sh", "-c", "echo $CIBUILDWHEEL"], capture_output=True) == "1\n"
|
||||||
|
assert (
|
||||||
|
container.call(["sh", "-c", "echo $SOURCE_DATE_EPOCH"], capture_output=True)
|
||||||
|
== "1489957071\n"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_cwd(container_engine):
|
def test_cwd(container_engine):
|
||||||
with OCIContainer(
|
with OCIContainer(
|
||||||
engine=container_engine, image=DEFAULT_IMAGE, cwd="/cibuildwheel/working_directory"
|
engine=container_engine, image=DEFAULT_IMAGE, cwd="/cibuildwheel/working_directory"
|
||||||
@@ -221,10 +249,9 @@ def test_environment_executor(container_engine):
|
|||||||
assert assignment.evaluated_value({}, container.environment_executor) == "42"
|
assert assignment.evaluated_value({}, container.environment_executor) == "42"
|
||||||
|
|
||||||
|
|
||||||
def test_podman_vfs(tmp_path: Path, monkeypatch, request):
|
def test_podman_vfs(tmp_path: Path, monkeypatch, container_engine):
|
||||||
# Tests podman VFS, for the podman in docker use-case
|
if container_engine.name != "podman":
|
||||||
if not request.config.getoption("--run-podman"):
|
pytest.skip("only runs with podman")
|
||||||
pytest.skip("need --run-podman option to run")
|
|
||||||
|
|
||||||
# create the VFS configuration
|
# create the VFS configuration
|
||||||
vfs_path = tmp_path / "podman_vfs"
|
vfs_path = tmp_path / "podman_vfs"
|
||||||
@@ -300,9 +327,9 @@ def test_podman_vfs(tmp_path: Path, monkeypatch, request):
|
|||||||
subprocess.run(["podman", "unshare", "rm", "-rf", vfs_path], check=True)
|
subprocess.run(["podman", "unshare", "rm", "-rf", vfs_path], check=True)
|
||||||
|
|
||||||
|
|
||||||
def test_create_args_volume(tmp_path: Path, request):
|
def test_create_args_volume(tmp_path: Path, container_engine):
|
||||||
if not request.config.getoption("--run-docker"):
|
if container_engine.name != "docker":
|
||||||
pytest.skip("need --run-docker option to run")
|
pytest.skip("only runs with docker")
|
||||||
|
|
||||||
if "CIRCLECI" in os.environ or "GITLAB_CI" in os.environ:
|
if "CIRCLECI" in os.environ or "GITLAB_CI" in os.environ:
|
||||||
pytest.skip(
|
pytest.skip(
|
||||||
@@ -367,3 +394,24 @@ def test_parse_engine_config(config, name, create_args):
|
|||||||
engine_config = OCIContainerEngineConfig.from_config_string(config)
|
engine_config = OCIContainerEngineConfig.from_config_string(config)
|
||||||
assert engine_config.name == name
|
assert engine_config.name == name
|
||||||
assert engine_config.create_args == create_args
|
assert engine_config.create_args == create_args
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif(pm != "x86_64", reason="Only runs on x86_64")
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("image", "shell_args"),
|
||||||
|
[
|
||||||
|
(DEFAULT_IMAGE_TEMPLATE.format(machine="i686"), ["/bin/bash"]),
|
||||||
|
(DEFAULT_IMAGE_TEMPLATE.format(machine="x86_64"), ["linux32", "/bin/bash"]),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_enforce_32_bit(container_engine, image, shell_args):
|
||||||
|
with OCIContainer(engine=container_engine, image=image, enforce_32_bit=True) as container:
|
||||||
|
assert container.call(["uname", "-m"], capture_output=True).strip() == "i686"
|
||||||
|
container_args = subprocess.run(
|
||||||
|
f"{container.engine.name} inspect -f '{{{{json .Args }}}}' {container.name}",
|
||||||
|
shell=True,
|
||||||
|
check=True,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
text=True,
|
||||||
|
).stdout
|
||||||
|
assert json.loads(container_args) == shell_args
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ def test_build_default_launches(monkeypatch):
|
|||||||
kwargs = build_in_container.call_args_list[0][1]
|
kwargs = build_in_container.call_args_list[0][1]
|
||||||
assert "quay.io/pypa/manylinux2014_x86_64" in kwargs["container"]["image"]
|
assert "quay.io/pypa/manylinux2014_x86_64" in kwargs["container"]["image"]
|
||||||
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
||||||
assert not kwargs["container"]["simulate_32_bit"]
|
assert not kwargs["container"]["enforce_32_bit"]
|
||||||
|
|
||||||
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
||||||
assert identifiers == {f"{x}-manylinux_x86_64" for x in ALL_IDS}
|
assert identifiers == {f"{x}-manylinux_x86_64" for x in ALL_IDS}
|
||||||
@@ -80,7 +80,7 @@ def test_build_default_launches(monkeypatch):
|
|||||||
kwargs = build_in_container.call_args_list[1][1]
|
kwargs = build_in_container.call_args_list[1][1]
|
||||||
assert "quay.io/pypa/manylinux2014_i686" in kwargs["container"]["image"]
|
assert "quay.io/pypa/manylinux2014_i686" in kwargs["container"]["image"]
|
||||||
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
||||||
assert kwargs["container"]["simulate_32_bit"]
|
assert kwargs["container"]["enforce_32_bit"]
|
||||||
|
|
||||||
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
||||||
assert identifiers == {f"{x}-manylinux_i686" for x in ALL_IDS}
|
assert identifiers == {f"{x}-manylinux_i686" for x in ALL_IDS}
|
||||||
@@ -88,7 +88,7 @@ def test_build_default_launches(monkeypatch):
|
|||||||
kwargs = build_in_container.call_args_list[2][1]
|
kwargs = build_in_container.call_args_list[2][1]
|
||||||
assert "quay.io/pypa/musllinux_1_1_x86_64" in kwargs["container"]["image"]
|
assert "quay.io/pypa/musllinux_1_1_x86_64" in kwargs["container"]["image"]
|
||||||
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
||||||
assert not kwargs["container"]["simulate_32_bit"]
|
assert not kwargs["container"]["enforce_32_bit"]
|
||||||
|
|
||||||
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
||||||
assert identifiers == {
|
assert identifiers == {
|
||||||
@@ -98,7 +98,7 @@ def test_build_default_launches(monkeypatch):
|
|||||||
kwargs = build_in_container.call_args_list[3][1]
|
kwargs = build_in_container.call_args_list[3][1]
|
||||||
assert "quay.io/pypa/musllinux_1_1_i686" in kwargs["container"]["image"]
|
assert "quay.io/pypa/musllinux_1_1_i686" in kwargs["container"]["image"]
|
||||||
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
||||||
assert kwargs["container"]["simulate_32_bit"]
|
assert kwargs["container"]["enforce_32_bit"]
|
||||||
|
|
||||||
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
||||||
assert identifiers == {f"{x}-musllinux_i686" for x in ALL_IDS if "pp" not in x}
|
assert identifiers == {f"{x}-musllinux_i686" for x in ALL_IDS if "pp" not in x}
|
||||||
@@ -141,7 +141,7 @@ before-all = "true"
|
|||||||
kwargs = build_in_container.call_args_list[0][1]
|
kwargs = build_in_container.call_args_list[0][1]
|
||||||
assert "quay.io/pypa/manylinux2014_x86_64" in kwargs["container"]["image"]
|
assert "quay.io/pypa/manylinux2014_x86_64" in kwargs["container"]["image"]
|
||||||
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
||||||
assert not kwargs["container"]["simulate_32_bit"]
|
assert not kwargs["container"]["enforce_32_bit"]
|
||||||
|
|
||||||
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
||||||
assert identifiers == {"cp36-manylinux_x86_64"}
|
assert identifiers == {"cp36-manylinux_x86_64"}
|
||||||
@@ -150,7 +150,7 @@ before-all = "true"
|
|||||||
kwargs = build_in_container.call_args_list[1][1]
|
kwargs = build_in_container.call_args_list[1][1]
|
||||||
assert "quay.io/pypa/manylinux2014_x86_64" in kwargs["container"]["image"]
|
assert "quay.io/pypa/manylinux2014_x86_64" in kwargs["container"]["image"]
|
||||||
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
||||||
assert not kwargs["container"]["simulate_32_bit"]
|
assert not kwargs["container"]["enforce_32_bit"]
|
||||||
|
|
||||||
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
||||||
assert identifiers == {
|
assert identifiers == {
|
||||||
@@ -162,7 +162,7 @@ before-all = "true"
|
|||||||
kwargs = build_in_container.call_args_list[2][1]
|
kwargs = build_in_container.call_args_list[2][1]
|
||||||
assert "quay.io/pypa/manylinux_2_28_x86_64" in kwargs["container"]["image"]
|
assert "quay.io/pypa/manylinux_2_28_x86_64" in kwargs["container"]["image"]
|
||||||
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
||||||
assert not kwargs["container"]["simulate_32_bit"]
|
assert not kwargs["container"]["enforce_32_bit"]
|
||||||
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
||||||
assert identifiers == {
|
assert identifiers == {
|
||||||
f"{x}-manylinux_x86_64"
|
f"{x}-manylinux_x86_64"
|
||||||
@@ -172,7 +172,7 @@ before-all = "true"
|
|||||||
kwargs = build_in_container.call_args_list[3][1]
|
kwargs = build_in_container.call_args_list[3][1]
|
||||||
assert "quay.io/pypa/manylinux2014_i686" in kwargs["container"]["image"]
|
assert "quay.io/pypa/manylinux2014_i686" in kwargs["container"]["image"]
|
||||||
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
||||||
assert kwargs["container"]["simulate_32_bit"]
|
assert kwargs["container"]["enforce_32_bit"]
|
||||||
|
|
||||||
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
||||||
assert identifiers == {f"{x}-manylinux_i686" for x in ALL_IDS}
|
assert identifiers == {f"{x}-manylinux_i686" for x in ALL_IDS}
|
||||||
@@ -180,7 +180,7 @@ before-all = "true"
|
|||||||
kwargs = build_in_container.call_args_list[4][1]
|
kwargs = build_in_container.call_args_list[4][1]
|
||||||
assert "quay.io/pypa/musllinux_1_1_x86_64" in kwargs["container"]["image"]
|
assert "quay.io/pypa/musllinux_1_1_x86_64" in kwargs["container"]["image"]
|
||||||
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
||||||
assert not kwargs["container"]["simulate_32_bit"]
|
assert not kwargs["container"]["enforce_32_bit"]
|
||||||
|
|
||||||
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
||||||
assert identifiers == {
|
assert identifiers == {
|
||||||
@@ -190,7 +190,7 @@ before-all = "true"
|
|||||||
kwargs = build_in_container.call_args_list[5][1]
|
kwargs = build_in_container.call_args_list[5][1]
|
||||||
assert "quay.io/pypa/musllinux_1_2_x86_64" in kwargs["container"]["image"]
|
assert "quay.io/pypa/musllinux_1_2_x86_64" in kwargs["container"]["image"]
|
||||||
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
||||||
assert not kwargs["container"]["simulate_32_bit"]
|
assert not kwargs["container"]["enforce_32_bit"]
|
||||||
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
||||||
assert identifiers == {
|
assert identifiers == {
|
||||||
f"{x}-musllinux_x86_64" for x in ALL_IDS - {"cp36", "cp37", "cp38", "cp39"} if "pp" not in x
|
f"{x}-musllinux_x86_64" for x in ALL_IDS - {"cp36", "cp37", "cp38", "cp39"} if "pp" not in x
|
||||||
@@ -199,7 +199,7 @@ before-all = "true"
|
|||||||
kwargs = build_in_container.call_args_list[6][1]
|
kwargs = build_in_container.call_args_list[6][1]
|
||||||
assert "quay.io/pypa/musllinux_1_1_i686" in kwargs["container"]["image"]
|
assert "quay.io/pypa/musllinux_1_1_i686" in kwargs["container"]["image"]
|
||||||
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
||||||
assert kwargs["container"]["simulate_32_bit"]
|
assert kwargs["container"]["enforce_32_bit"]
|
||||||
|
|
||||||
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
||||||
assert identifiers == {f"{x}-musllinux_i686" for x in ALL_IDS if "pp" not in x}
|
assert identifiers == {f"{x}-musllinux_i686" for x in ALL_IDS if "pp" not in x}
|
||||||
|
|||||||
@@ -272,3 +272,57 @@ def test_environment_pass_references():
|
|||||||
"STARTER": "green eggs",
|
"STARTER": "green eggs",
|
||||||
"MAIN_COURSE": "ham",
|
"MAIN_COURSE": "ham",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("toml_assignment", "result_name", "result_args"),
|
||||||
|
[
|
||||||
|
(
|
||||||
|
"",
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'build-frontend = "build"',
|
||||||
|
"build",
|
||||||
|
[],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'build-frontend = {name = "build"}',
|
||||||
|
"build",
|
||||||
|
[],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'build-frontend = "pip; args: --some-option"',
|
||||||
|
"pip",
|
||||||
|
["--some-option"],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'build-frontend = {name = "pip", args = ["--some-option"]}',
|
||||||
|
"pip",
|
||||||
|
["--some-option"],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_build_frontend_option(tmp_path: Path, toml_assignment, result_name, result_args):
|
||||||
|
args = CommandLineArguments.defaults()
|
||||||
|
args.package_dir = tmp_path
|
||||||
|
|
||||||
|
tmp_path.joinpath("pyproject.toml").write_text(
|
||||||
|
textwrap.dedent(
|
||||||
|
f"""\
|
||||||
|
[tool.cibuildwheel]
|
||||||
|
{toml_assignment}
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
options = Options(platform="linux", command_line_arguments=args, env={})
|
||||||
|
parsed_build_frontend = options.build_options(identifier=None).build_frontend
|
||||||
|
|
||||||
|
if toml_assignment:
|
||||||
|
assert parsed_build_frontend is not None
|
||||||
|
assert parsed_build_frontend.name == result_name
|
||||||
|
assert parsed_build_frontend.args == result_args
|
||||||
|
else:
|
||||||
|
assert parsed_build_frontend is None
|
||||||
|
|||||||
@@ -26,6 +26,72 @@ def test_read_setup_py_simple(tmp_path):
|
|||||||
assert get_requires_python_str(tmp_path) == "1.23"
|
assert get_requires_python_str(tmp_path) == "1.23"
|
||||||
|
|
||||||
|
|
||||||
|
def test_read_setup_py_if_main(tmp_path):
|
||||||
|
with open(tmp_path / "setup.py", "w") as f:
|
||||||
|
f.write(
|
||||||
|
dedent(
|
||||||
|
"""
|
||||||
|
from setuptools import setup
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
setup(
|
||||||
|
name = "hello",
|
||||||
|
other = 23,
|
||||||
|
example = ["item", "other"],
|
||||||
|
python_requires = "1.23",
|
||||||
|
)
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
assert setup_py_python_requires(tmp_path.joinpath("setup.py").read_text()) == "1.23"
|
||||||
|
assert get_requires_python_str(tmp_path) == "1.23"
|
||||||
|
|
||||||
|
|
||||||
|
def test_read_setup_py_if_main_reversed(tmp_path):
|
||||||
|
with open(tmp_path / "setup.py", "w") as f:
|
||||||
|
f.write(
|
||||||
|
dedent(
|
||||||
|
"""
|
||||||
|
from setuptools import setup
|
||||||
|
|
||||||
|
if "__main__" == __name__:
|
||||||
|
setup(
|
||||||
|
name = "hello",
|
||||||
|
other = 23,
|
||||||
|
example = ["item", "other"],
|
||||||
|
python_requires = "1.23",
|
||||||
|
)
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
assert setup_py_python_requires(tmp_path.joinpath("setup.py").read_text()) == "1.23"
|
||||||
|
assert get_requires_python_str(tmp_path) == "1.23"
|
||||||
|
|
||||||
|
|
||||||
|
def test_read_setup_py_if_invalid(tmp_path):
|
||||||
|
with open(tmp_path / "setup.py", "w") as f:
|
||||||
|
f.write(
|
||||||
|
dedent(
|
||||||
|
"""
|
||||||
|
from setuptools import setup
|
||||||
|
|
||||||
|
if True:
|
||||||
|
setup(
|
||||||
|
name = "hello",
|
||||||
|
other = 23,
|
||||||
|
example = ["item", "other"],
|
||||||
|
python_requires = "1.23",
|
||||||
|
)
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
assert not setup_py_python_requires(tmp_path.joinpath("setup.py").read_text())
|
||||||
|
assert not get_requires_python_str(tmp_path)
|
||||||
|
|
||||||
|
|
||||||
def test_read_setup_py_full(tmp_path):
|
def test_read_setup_py_full(tmp_path):
|
||||||
with open(tmp_path / "setup.py", "w", encoding="utf8") as f:
|
with open(tmp_path / "setup.py", "w", encoding="utf8") as f:
|
||||||
f.write(
|
f.write(
|
||||||
|
|||||||
Reference in New Issue
Block a user