feat: Python 3.15 build by default (#2944)

This commit is contained in:
Matthieu Darbois
2026-08-04 20:26:00 -04:00
committed by GitHub
parent 3568a1cb9e
commit 92e2145d80
6 changed files with 39 additions and 31 deletions
+13 -14
View File
@@ -22,25 +22,24 @@ What does it do?
While cibuildwheel itself requires a recent Python version to run (we support the last three releases), it can target the following versions to build wheels:
| | macOS Intel | macOS Apple Silicon | Windows 64bit | Windows 32bit | Windows Arm64 | manylinux<br/>musllinux x86_64 | manylinux<br/>musllinux i686 | manylinux<br/>musllinux aarch64 | manylinux<br/>musllinux ppc64le | manylinux<br/>musllinux s390x | manylinux<br/>musllinux armv7l | Android | iOS | Pyodide |
| ------------------------ | ----------- | ------------------- | ------------- | ------------- | -------------- | ------------------------------ | ---------------------------- | ------------------------------- | ------------------------------- | ----------------------------- | ------------------------------ | ------- | --- | -------------- |
| CPython 3.9 | ✅ | ✅ | ✅ | ✅ | ✅<sup>2</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅<sup>4</sup> | N/A | N/A | N/A |
| CPython 3.10 | ✅ | ✅ | ✅ | ✅ | ✅<sup>2</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅<sup>4</sup> | N/A | N/A | N/A |
| CPython 3.11 | ✅ | ✅ | ✅ | ✅ | ✅<sup>2</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅<sup>4</sup> | N/A | N/A | N/A |
| CPython 3.12 | ✅ | ✅ | ✅ | ✅ | ✅<sup>2</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅<sup>4</sup> | N/A | N/A | ✅<sup>3</sup> |
| CPython 3.13 | ✅ | ✅ | ✅ | ✅ | ✅<sup>2</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅<sup>4</sup> | ✅ | ✅ | ✅ |
| CPython 3.14 | ✅ | ✅ | ✅ | ✅ | ✅<sup>2</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅<sup>4</sup> | ✅ | ✅ | ✅ |
| CPython 3.15<sup>5</sup> | ✅ | ✅ | ✅ | ✅ | ✅<sup>2</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅<sup>4</sup> | ✅ | ✅ | ✅ |
| PyPy 3.9 v7.3 | ✅ | ✅ | ✅ | N/A | N/A | ✅<sup>1</sup> | ✅<sup>1</sup> | ✅<sup>1</sup> | N/A | N/A | N/A | N/A | N/A | N/A |
| PyPy 3.10 v7.3 | ✅ | ✅ | ✅ | N/A | N/A | ✅<sup>1</sup> | ✅<sup>1</sup> | ✅<sup>1</sup> | N/A | N/A | N/A | N/A | N/A | N/A |
| PyPy 3.11 v7.3 | ✅ | ✅ | ✅ | N/A | N/A | ✅<sup>1</sup> | ✅<sup>1</sup> | ✅<sup>1</sup> | N/A | N/A | N/A | N/A | N/A | N/A |
| GraalPy 3.12 v25.0 | ✅ | ✅ | ✅ | N/A | N/A | ✅<sup>1</sup> | N/A | ✅<sup>1</sup> | N/A | N/A | N/A | N/A | N/A | N/A |
| | macOS Intel | macOS Apple Silicon | Windows 64bit | Windows 32bit | Windows Arm64 | manylinux<br/>musllinux x86_64 | manylinux<br/>musllinux i686 | manylinux<br/>musllinux aarch64 | manylinux<br/>musllinux ppc64le | manylinux<br/>musllinux s390x | manylinux<br/>musllinux armv7l | Android | iOS | Pyodide |
|--------------------| ----------- | ------------------- | ------------- | ------------- | -------------- | ------------------------------ | ---------------------------- | ------------------------------- | ------------------------------- | ----------------------------- | ------------------------------ | ------- | --- | -------------- |
| CPython 3.9 | ✅ | ✅ | ✅ | ✅ | ✅<sup>2</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅<sup>4</sup> | N/A | N/A | N/A |
| CPython 3.10 | ✅ | ✅ | ✅ | ✅ | ✅<sup>2</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅<sup>4</sup> | N/A | N/A | N/A |
| CPython 3.11 | ✅ | ✅ | ✅ | ✅ | ✅<sup>2</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅<sup>4</sup> | N/A | N/A | N/A |
| CPython 3.12 | ✅ | ✅ | ✅ | ✅ | ✅<sup>2</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅<sup>4</sup> | N/A | N/A | ✅<sup>3</sup> |
| CPython 3.13 | ✅ | ✅ | ✅ | ✅ | ✅<sup>2</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅<sup>4</sup> | ✅ | ✅ | ✅ |
| CPython 3.14 | ✅ | ✅ | ✅ | ✅ | ✅<sup>2</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅<sup>4</sup> | ✅ | ✅ | ✅ |
| CPython 3.15 | ✅ | ✅ | ✅ | ✅ | ✅<sup>2</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅<sup>4</sup> | ✅ | ✅ | ✅ |
| PyPy 3.9 v7.3 | ✅ | ✅ | ✅ | N/A | N/A | ✅<sup>1</sup> | ✅<sup>1</sup> | ✅<sup>1</sup> | N/A | N/A | N/A | N/A | N/A | N/A |
| PyPy 3.10 v7.3 | ✅ | ✅ | ✅ | N/A | N/A | ✅<sup>1</sup> | ✅<sup>1</sup> | ✅<sup>1</sup> | N/A | N/A | N/A | N/A | N/A | N/A |
| PyPy 3.11 v7.3 | ✅ | ✅ | ✅ | N/A | N/A | ✅<sup>1</sup> | ✅<sup>1</sup> | ✅<sup>1</sup> | N/A | N/A | N/A | N/A | N/A | N/A |
| GraalPy 3.12 v25.0 | ✅ | ✅ | ✅ | N/A | N/A | ✅<sup>1</sup> | N/A | ✅<sup>1</sup> | N/A | N/A | N/A | N/A | N/A | N/A |
<sup>**1** PyPy & GraalPy are only supported for manylinux wheels.</sup><br>
<sup>**2** Windows arm64 support is experimental.</sup><br>
<sup>**3** Not supported on PyPI, uses old `pyodide` tag instead of `pyemscripten`. Requires `pyodide-eol` [`enable`](https://cibuildwheel.pypa.io/en/stable/options/#enable).</sup><br>
<sup>**4** manylinux armv7l support is experimental. As there are no RHEL based image for this architecture, it's using an Ubuntu based image instead.</sup><br>
<sup>**5** Python 3.15 requires opt-in using [`enable`](https://cibuildwheel.pypa.io/en/stable/options/#enable).</sup><br>
- Builds manylinux, musllinux, macOS, Windows, pyemscripten, iOS, and Android wheels
- Supports CPython, PyPy, and GraalPy
+1 -1
View File
@@ -92,7 +92,7 @@ class BuildSelector:
return False
# filter out groups that are not enabled
if EnableGroup.CPythonPrerelease not in self.enable and fnmatch(build_id, "cp315*"):
if EnableGroup.CPythonPrerelease not in self.enable and fnmatch(build_id, "cp316*"):
return False
is_pypy_eol = fnmatch(build_id, "pp3?-*") or fnmatch(build_id, "pp310-*")
is_pypy = fnmatch(build_id, "pp*") and not is_pypy_eol
+12 -11
View File
@@ -278,20 +278,18 @@ def _expected_wheels(
# To be kept in sync with Python versions for Pyodide identifiers in cibuildwheel/selector.py.
if platform == "pyodide" and python_abi_tags is None:
python_abi_tags = ["cp313-cp313", "cp314-cp314"]
python_abi_tags = ["cp313-cp313", "cp314-cp314", "cp315-cp315"]
if EnableGroup.PyodideEoL in enable_groups:
python_abi_tags.insert(0, "cp312-cp312")
if EnableGroup.CPythonPrerelease in enable_groups:
python_abi_tags.append("cp315-cp315")
elif (platform == "android" and python_abi_tags is None) or (
platform == "ios" and python_abi_tags is None
):
elif platform in {"android", "ios"} and python_abi_tags is None:
python_abi_tags = [
"cp313-cp313",
"cp314-cp314",
"cp315-cp315",
]
if EnableGroup.CPythonPrerelease in enable_groups:
python_abi_tags += ["cp315-cp315"]
# python_abi_tags += ["cp316-cp316"]
... # Add cp316 here when available
elif python_abi_tags is None:
python_abi_tags = [
"cp39-cp39",
@@ -301,13 +299,16 @@ def _expected_wheels(
"cp313-cp313",
"cp314-cp314",
"cp314-cp314t",
"cp315-cp315",
"cp315-cp315t",
]
if EnableGroup.CPythonPrerelease in enable_groups:
python_abi_tags += [
"cp315-cp315",
"cp315-cp315t",
]
# python_abi_tags += [
# "cp316-cp316",
# "cp316-cp316t",
# ]
... # Add cp316 here when available
if EnableGroup.PyPyEoL in enable_groups:
python_abi_tags += [
+4 -2
View File
@@ -16,6 +16,7 @@ def test_build() -> None:
assert build_selector("cp312-manylinux_x86_64")
assert build_selector("cp313-manylinux_x86_64")
assert build_selector("cp314-manylinux_x86_64")
assert build_selector("cp315-manylinux_x86_64")
assert build_selector("pp311-manylinux_x86_64")
assert build_selector("cp36-manylinux_i686")
assert build_selector("cp37-manylinux_i686")
@@ -37,6 +38,7 @@ def test_build() -> None:
assert build_selector("cp312-win_amd64")
assert build_selector("cp313-win_amd64")
assert build_selector("cp314-win_amd64")
assert build_selector("cp315-win_amd64")
assert not build_selector("pp310-win_amd64")
assert not build_selector("pp311-win_amd64")
@@ -100,7 +102,7 @@ def test_build_filter_pyodide() -> None:
assert build_selector("cp313-pyodide_wasm32")
assert build_selector("cp314-pyodide_wasm32")
assert not build_selector("cp312-pyodide_wasm32")
assert not build_selector("cp315-pyodide_wasm32")
assert build_selector("cp315-pyodide_wasm32")
def test_build_filter_pyodide_eol() -> None:
@@ -112,7 +114,7 @@ def test_build_filter_pyodide_eol() -> None:
assert build_selector("cp312-pyodide_wasm32")
assert build_selector("cp313-pyodide_wasm32")
assert build_selector("cp314-pyodide_wasm32")
assert not build_selector("cp315-pyodide_wasm32")
assert build_selector("cp315-pyodide_wasm32")
def test_skip() -> None:
+4 -2
View File
@@ -97,9 +97,11 @@ def test_linux_container_split(tmp_path: Path, monkeypatch: pytest.MonkeyPatch)
"cp313-manylinux_x86_64",
"cp314-manylinux_x86_64",
"cp314t-manylinux_x86_64",
"cp315-manylinux_x86_64",
"cp315t-manylinux_x86_64",
]
assert before_alls(build_steps[3]) == [""] * 4
assert container_engines(build_steps[3]) == [default_container_engine] * 4
assert before_alls(build_steps[3]) == [""] * 6
assert container_engines(build_steps[3]) == [default_container_engine] * 6
def test_package_dir_outside_working_directory_raises_configuration_error(
+5 -1
View File
@@ -13,7 +13,7 @@ from cibuildwheel.__main__ import main
from cibuildwheel.oci_container import OCIPlatform
from cibuildwheel.util import file
DEFAULT_IDS = {"cp39", "cp310", "cp311", "cp312", "cp313", "cp314", "cp314t"}
DEFAULT_IDS = {"cp39", "cp310", "cp311", "cp312", "cp313", "cp314", "cp314t", "cp315", "cp315t"}
ALL_IDS = DEFAULT_IDS | {"pp39", "pp310", "pp311", "gp312_250"}
@@ -155,6 +155,8 @@ before-all = "true"
"cp313",
"cp314",
"cp314t",
"cp315",
"cp315t",
"pp39",
"pp310",
"pp311",
@@ -176,6 +178,8 @@ before-all = "true"
"cp313",
"cp314",
"cp314t",
"cp315",
"cp315t",
"pp39",
"pp310",
"pp311",