Skip to content

Commit

Permalink
feat: adding enable
Browse files Browse the repository at this point in the history
Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>
  • Loading branch information
henryiii committed Nov 1, 2024
1 parent 66d45de commit bbc0a19
Show file tree
Hide file tree
Showing 8 changed files with 117 additions and 34 deletions.
15 changes: 15 additions & 0 deletions bin/generate_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@
- append
default: none
description: How to inherit the parent's value.
enable:
enum:
- cpython-free-threaded
- cpython-prerelease
- pypy
description: A Python version or flavor to enable.
additionalProperties: false
description: cibuildwheel's settings.
type: object
Expand Down Expand Up @@ -99,6 +105,13 @@
default: pinned
description: Specify how cibuildwheel controls the versions of the tools it uses
type: string
enable:
description: Enable or disable certain builds.
oneOf:
- $ref: "#/$defs/enable"
- type: array
items:
$ref: "#/$defs/enable"
environment:
description: Set environment variables needed during the build.
type: string_table
Expand All @@ -110,6 +123,7 @@
type: boolean
default: false
description: The project supports free-threaded builds of Python (PEP703)
deprecated: Use the `enable` option instead.
manylinux-aarch64-image:
type: string
description: Specify alternative manylinux / musllinux container images
Expand Down Expand Up @@ -258,6 +272,7 @@
del non_global_options["skip"]
del non_global_options["test-skip"]
del non_global_options["free-threaded-support"]
del non_global_options["enable"]

overrides["items"]["properties"]["select"]["oneOf"] = string_array
overrides["items"]["properties"] |= non_global_options.copy()
Expand Down
37 changes: 29 additions & 8 deletions cibuildwheel/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
BuildFrontendConfig,
BuildSelector,
DependencyConstraints,
EnableGroups,
TestSelector,
format_safe,
resources_dir,
Expand Down Expand Up @@ -511,6 +512,7 @@ def get(
env_plat: bool = True,
option_format: OptionFormat | None = None,
ignore_empty: bool = False,
env_rule: InheritRule = InheritRule.NONE,
) -> str:
"""
Get and return the value for the named option from environment,
Expand Down Expand Up @@ -542,8 +544,8 @@ def get(
(o.options.get(name), o.inherit.get(name, InheritRule.NONE))
for o in self.active_config_overrides
],
(self.env.get(envvar), InheritRule.NONE),
(self.env.get(plat_envvar) if env_plat else None, InheritRule.NONE),
(self.env.get(envvar), env_rule),
(self.env.get(plat_envvar) if env_plat else None, env_rule),
ignore_empty=ignore_empty,
option_format=option_format,
)
Expand Down Expand Up @@ -599,16 +601,37 @@ def globals(self) -> GlobalOptions:
skip_config = self.reader.get("skip", env_plat=False, option_format=ListFormat(sep=" "))
test_skip = self.reader.get("test-skip", env_plat=False, option_format=ListFormat(sep=" "))

allow_empty = args.allow_empty or strtobool(self.env.get("CIBW_ALLOW_EMPTY", "0"))

enable_groups = self.reader.get(
"enable", env_plat=False, option_format=ListFormat(sep=" "), env_rule=InheritRule.APPEND
)
enable = {EnableGroups(group) for group in enable_groups.split()}

free_threaded_support = strtobool(
self.reader.get("free-threaded-support", env_plat=False, ignore_empty=True)
)

allow_empty = args.allow_empty or strtobool(self.env.get("CIBW_ALLOW_EMPTY", "0"))

prerelease_pythons = args.prerelease_pythons or strtobool(
self.env.get("CIBW_PRERELEASE_PYTHONS", "0")
)

if free_threaded_support or prerelease_pythons:
msg = (
"free-threaded-support and prerelease-pythons should be specified by enable instead"
)
if enable:
raise OptionsReaderError(msg)
log.warning(msg)

if free_threaded_support:
enable.add(EnableGroups.CPythonFreeThreaded)
if prerelease_pythons:
enable.add(EnableGroups.CPythonPrerelease)

# For backwards compatibility, we are adding PyPy for now
enable |= {EnableGroups.PyPy}

# This is not supported in tool.cibuildwheel, as it comes from a standard location.
# Passing this in as an environment variable will override pyproject.toml, setup.cfg, or setup.py
requires_python_str: str | None = (
Expand All @@ -624,15 +647,13 @@ def globals(self) -> GlobalOptions:
build_config = args.only
skip_config = ""
architectures = Architecture.all_archs(self.platform)
prerelease_pythons = True
free_threaded_support = True
enable = set(EnableGroups)

build_selector = BuildSelector(
build_config=build_config,
skip_config=skip_config,
requires_python=requires_python,
prerelease_pythons=prerelease_pythons,
free_threaded_support=free_threaded_support,
enable=frozenset(enable),
)
test_selector = TestSelector(skip_config=test_skip)

Expand Down
26 changes: 25 additions & 1 deletion cibuildwheel/resources/cibuildwheel.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,16 @@
],
"default": "none",
"description": "How to inherit the parent's value."
}
},
"enable": {
"enum": [
"cpython-eol",
"cpython-free-threaded",
"cpython-prerelease",
"pypy-eol"
]
},
"description": "A Python version or flavor to enable."
},
"additionalProperties": false,
"description": "cibuildwheel's settings.",
Expand Down Expand Up @@ -228,6 +237,21 @@
"type": "string",
"title": "CIBW_DEPENDENCY_VERSIONS"
},
"enable": {
"description": "Enable or disable certain builds.",
"oneOf": [
{
"$ref": "#/$defs/enable"
},
{
"type": "array",
"items": {
"$ref": "#/$defs/enable"
}
}
],
"title": "CIBW_ENABLE"
},
"environment": {
"description": "Set environment variables needed during the build.",
"oneOf": [
Expand Down
1 change: 1 addition & 0 deletions cibuildwheel/resources/defaults.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ build = "*"
skip = ""
test-skip = ""
free-threaded-support = false
enable = []

archs = ["auto"]
build-frontend = "default"
Expand Down
38 changes: 24 additions & 14 deletions cibuildwheel/util.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import annotations

import contextlib
import enum
import fnmatch
import itertools
import os
Expand All @@ -23,7 +24,7 @@
from pathlib import Path, PurePath
from tempfile import TemporaryDirectory
from time import sleep
from typing import Any, ClassVar, Final, Literal, TextIO, TypeVar
from typing import Any, Final, Literal, TextIO, TypeVar
from zipfile import ZipFile

import bracex
Expand All @@ -41,6 +42,7 @@

__all__ = [
"MANYLINUX_ARCHS",
"EnableGroups",
"call",
"chdir",
"combine_constraints",
Expand All @@ -66,6 +68,16 @@
test_fail_cwd_file: Final[Path] = resources_dir / "testing_temp_dir_file.py"


class EnableGroups(enum.Enum):
"""
Groups of build selectors that are not enabled by default.
"""

CPythonFreeThreaded = "cpython-free-threaded"
CPythonPrerelease = "cpython-prerelease"
PyPy = "pypy"


MANYLINUX_ARCHS: Final[tuple[str, ...]] = (
"x86_64",
"i686",
Expand Down Expand Up @@ -247,12 +259,7 @@ class BuildSelector:
build_config: str
skip_config: str
requires_python: SpecifierSet | None = None

# a pattern that skips prerelease versions, when include_prereleases is False.
PRERELEASE_SKIP: ClassVar[str] = ""
prerelease_pythons: bool = False

free_threaded_support: bool = False
enable: frozenset[EnableGroups] = frozenset()

def __call__(self, build_id: str) -> bool:
# Filter build selectors by python_requires if set
Expand All @@ -266,12 +273,16 @@ def __call__(self, build_id: str) -> bool:
if not self.requires_python.contains(version):
return False

# filter out the prerelease pythons if self.prerelease_pythons is False
if not self.prerelease_pythons and selector_matches(self.PRERELEASE_SKIP, build_id):
# filter out groups that are not enabled
if EnableGroups.CPythonFreeThreaded not in self.enable and selector_matches(
"cp3??t-*", build_id
):
return False

# filter out free threaded pythons if self.free_threaded_support is False
if not self.free_threaded_support and selector_matches("*t-*", build_id):
if EnableGroups.CPythonPrerelease not in self.enable and selector_matches(
"cp314*", build_id
):
return False
if EnableGroups.PyPy not in self.enable and selector_matches("pp*", build_id):
return False

should_build = selector_matches(self.build_config, build_id)
Expand All @@ -284,8 +295,7 @@ def options_summary(self) -> Any:
"build_config": self.build_config,
"skip_config": self.skip_config,
"requires_python": str(self.requires_python),
"prerelease_pythons": self.prerelease_pythons,
"free_threaded_support": self.free_threaded_support,
"enable": sorted(group.value for group in self.enable),
}


Expand Down
25 changes: 16 additions & 9 deletions unit_test/build_selector_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@

from packaging.specifiers import SpecifierSet

from cibuildwheel.util import BuildSelector
from cibuildwheel.util import BuildSelector, EnableGroups


def test_build():
build_selector = BuildSelector(build_config="cp3*-* *-manylinux*", skip_config="")
build_selector = BuildSelector(
build_config="cp3*-* *-manylinux*", skip_config="", enable=frozenset([EnableGroups.PyPy])
)

assert build_selector("cp36-manylinux_x86_64")
assert build_selector("cp37-manylinux_x86_64")
Expand Down Expand Up @@ -43,7 +45,7 @@ def test_build_filter_pre():
build_selector = BuildSelector(
build_config="cp3*-* *-manylinux*",
skip_config="",
prerelease_pythons=True,
enable=frozenset([EnableGroups.CPythonPrerelease, EnableGroups.PyPy]),
)

assert build_selector("cp37-manylinux_x86_64")
Expand All @@ -55,7 +57,9 @@ def test_build_filter_pre():

def test_skip():
build_selector = BuildSelector(
build_config="*", skip_config="pp36-* cp3?-manylinux_i686 cp36-win* *-win32"
build_config="*",
skip_config="pp36-* cp3?-manylinux_i686 cp36-win* *-win32",
enable=frozenset([EnableGroups.PyPy]),
)

assert not build_selector("pp36-manylinux_x86_64")
Expand All @@ -79,7 +83,9 @@ def test_skip():

def test_build_and_skip():
build_selector = BuildSelector(
build_config="cp36-* cp37-macosx* *-manylinux*", skip_config="pp37-* cp37-manylinux_i686"
build_config="cp36-* cp37-macosx* *-manylinux*",
skip_config="pp37-* cp37-manylinux_i686",
enable=frozenset([EnableGroups.PyPy]),
)

assert not build_selector("pp37-manylinux_x86_64")
Expand Down Expand Up @@ -110,7 +116,10 @@ def test_build_braces():

def test_build_limited_python():
build_selector = BuildSelector(
build_config="*", skip_config="", requires_python=SpecifierSet(">=3.7")
build_config="*",
skip_config="",
requires_python=SpecifierSet(">=3.7"),
enable=frozenset([EnableGroups.PyPy]),
)

assert not build_selector("cp36-manylinux_x86_64")
Expand Down Expand Up @@ -146,9 +155,7 @@ def test_build_limited_python_patch():


def test_build_free_threaded_python():
build_selector = BuildSelector(
build_config="*", skip_config="", prerelease_pythons=True, free_threaded_support=True
)
build_selector = BuildSelector(build_config="*", skip_config="", enable=frozenset(EnableGroups))

assert build_selector("cp313t-manylinux_x86_64")

Expand Down
3 changes: 2 additions & 1 deletion unit_test/main_tests/main_platform_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from cibuildwheel.__main__ import main
from cibuildwheel.architecture import Architecture
from cibuildwheel.util import EnableGroups

from ..conftest import MOCK_PACKAGE_DIR

Expand Down Expand Up @@ -216,7 +217,7 @@ def test_only_argument(intercepted_build_args, monkeypatch, only, plat):
assert options.globals.build_selector.skip_config == ""
assert options.platform == plat
assert options.globals.architectures == Architecture.all_archs(plat)
assert options.globals.build_selector.prerelease_pythons is True
assert EnableGroups.PyPy in options.globals.build_selector.enable


@pytest.mark.parametrize("only", ("cp311-manylxinux_x86_64", "some_linux_thing"))
Expand Down
6 changes: 5 additions & 1 deletion unit_test/options_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
Options,
_get_pinned_container_images,
)
from cibuildwheel.util import EnableGroups

PYPROJECT_1 = """
[tool.cibuildwheel]
Expand Down Expand Up @@ -454,4 +455,7 @@ def test_free_threaded_support(
)
)
options = Options(platform="linux", command_line_arguments=args, env=env)
assert options.globals.build_selector.free_threaded_support is expected_result
if expected_result:
assert EnableGroups.CPythonFreeThreaded in options.globals.build_selector.enable
else:
assert EnableGroups.CPythonFreeThreaded not in options.globals.build_selector.enable

0 comments on commit bbc0a19

Please sign in to comment.