Skip to content

Commit

Permalink
WIP: start 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 Oct 21, 2024
1 parent 4e93d91 commit a70d4b3
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 29 deletions.
16 changes: 16 additions & 0 deletions bin/generate_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@
- append
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.
type: object
Expand Down Expand Up @@ -99,6 +106,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 +124,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 +273,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
39 changes: 31 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,23 +601,46 @@ 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 enable and (free_threaded_support or prerelease_pythons):
msg = (
"free-threaded-support and prerelease-pythons should be specified by enable instead"
)
raise OptionsReaderError(msg)

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

# For backwards compatibility, we are adding EoL Python versions to the enable group for one more release.
enable |= {EnableGroups.CPythonEoL, EnableGroups.PyPyEoL}

# 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 = (
self.env.get("CIBW_PROJECT_REQUIRES_PYTHON") or self.package_requires_python_str
)
requires_python = None if requires_python_str is None else SpecifierSet(requires_python_str)

# Requires-python overrides cpython-eol
if requires_python is not None:
enable.add(EnableGroups.CPythonEoL)

archs_config_str = args.archs or self.reader.get("archs", option_format=ListFormat(sep=" "))
architectures = Architecture.parse_config(archs_config_str, platform=self.platform)

Expand All @@ -624,15 +649,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
43 changes: 29 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,17 @@
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.
"""

CPythonEoL = "cpython-eol"
CPythonFreeThreaded = "cpython-free-threaded"
CPythonPrerelease = "cpython-prerelease"
PyPyEoL = "pypy-eol"


MANYLINUX_ARCHS: Final[tuple[str, ...]] = (
"x86_64",
"i686",
Expand Down Expand Up @@ -247,12 +260,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 +274,20 @@ 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.CPythonEoL not in self.enable and selector_matches(
"cp3{6,7,8}-*", 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.CPythonFreeThreaded not in self.enable and selector_matches(
"cp3??t-*", build_id
):
return False
if EnableGroups.CPythonPrerelease not in self.enable and selector_matches(
"cp314*", build_id
):
return False
if EnableGroups.PyPyEoL not in self.enable and selector_matches("pp3{7,8,9}-*", build_id):
return False

should_build = selector_matches(self.build_config, build_id)
Expand All @@ -284,8 +300,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
10 changes: 5 additions & 5 deletions unit_test/build_selector_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from packaging.specifiers import SpecifierSet

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


def test_build():
Expand Down Expand Up @@ -43,7 +43,9 @@ def test_build_filter_pre():
build_selector = BuildSelector(
build_config="cp3*-* *-manylinux*",
skip_config="",
prerelease_pythons=True,
enable=frozenset(
[EnableGroups.CPythonPrerelease, EnableGroups.CPythonEoL, EnableGroups.PyPyEoL]
),
)

assert build_selector("cp37-manylinux_x86_64")
Expand Down Expand Up @@ -146,9 +148,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
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 @@ -448,4 +449,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 a70d4b3

Please sign in to comment.