feat: add CPython 3.15 support for Android (#2858)

* feat: add CPython 3.15 support for iOS and Android

Add cp315 identifiers to build-platforms.toml for both iOS (arm64_iphoneos,
x86_64_iphonesimulator, arm64_iphonesimulator) and Android (arm64_v8a, x86_64).
Update bin/update_pythons.py to route iOS 3.15+ to python.org instead of
BeeWare GitHub releases. Update README.md platform table to show Android and
iOS as supported for 3.15. Add cp315-cp315 to expected_wheels test defaults
for android and ios platforms.

Assisted-by: OpenCode:Kimi-K2.6
Signed-off-by: Henry Schreiner <henryfs@princeton.edu>

* fix: adjust expectations

All changes made and linting passes. Here's a summary of what was done:
1. test/utils.py:390-394 — Added "cp315-cp315": 24 to the Android API level mapping, fixing the KeyError: 'cp315-cp315' in test_android.py::test_expected_wheels.
2. cibuildwheel/resources/build-platforms.toml:247 — Removed the cp315-ios_x86_64_iphonesimulator entry since CPython 3.15 dropped Intel iOS simulator support.
3. test/utils.py:397-405 — Updated the iOS expected wheels logic to return an empty platform_tags list for x86_64 when the Python version is 3.15+, so no x86_64_iphonesimulator wheels are expected for cp315+ on Intel Macs.
The XCframework slice name (ios-arm64_x86_64-simulator) stays the same in ios.py — I verified the 3.15 tarball still uses that name. The target_python.exists() iOS ARM64 failure on the feature branch is a separate issue (the 3.15 python.org distribution has a different structure than the beeware distributions used for 3.13/3.14) — left alone per your request.

Signed-off-by: Henry Schreiner <henryfs@princeton.edu>
Assisted-by: OpenCode:glm-5.1

* revert: x86 is still supposed to exist

Signed-off-by: Henry Schreiner <henryfs@princeton.edu>

* docs: fix readme for Pyodide

Signed-off-by: Henry Schreiner <henryfs@princeton.edu>

* docs: mention eol

Signed-off-by: Henry Schreiner <henryfs@princeton.edu>

* fix: drop assert

Signed-off-by: Henry Schreiner <henryfs@princeton.edu>

* feat: add CPython 3.15 support for Android only

Cherry-picked all changes from henryiii/feat/cp315-ios-android, then
reverted iOS-specific parts (iOS 3.15 build configs, ios.py assert
removal, update_pythons.py iOS URL logic, iOS test expectations, and
README iOS column for 3.15). Android cp315 entries, test expectations,
and README Android column remain.

Assisted-by: OpenCode:glm-5

---------

Signed-off-by: Henry Schreiner <henryfs@princeton.edu>
This commit is contained in:
Henry Schreiner
2026-05-15 23:47:20 -07:00
committed by GitHub
parent 02b64875a0
commit c274b4e02c
3 changed files with 22 additions and 15 deletions
+14 -12
View File
@@ -24,13 +24,13 @@ While cibuildwheel itself requires a recent Python version to run (we support th
| | 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> | ✅ | ✅ | ✅<sup>3</sup> |
| CPython 3.14 | ✅ | ✅ | ✅ | ✅ | ✅<sup>2</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅<sup>4</sup> | ✅ | ✅ | N/A |
| CPython 3.15<sup>5</sup> | ✅ | ✅ | ✅ | ✅ | ✅<sup>2</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅<sup>4</sup> | N/A | N/A | N/A |
| CPython 3.9 | ✅ | ✅ | ✅ | ✅ | ✅<sup>2</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅<sup>5</sup> | N/A | N/A | N/A |
| CPython 3.10 | ✅ | ✅ | ✅ | ✅ | ✅<sup>2</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅<sup>5</sup> | N/A | N/A | N/A |
| CPython 3.11 | ✅ | ✅ | ✅ | ✅ | ✅<sup>2</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅<sup>5</sup> | N/A | N/A | N/A |
| CPython 3.12 | ✅ | ✅ | ✅ | ✅ | ✅<sup>2</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅<sup>5</sup> | N/A | N/A | ✅<sup>3</sup> |
| CPython 3.13 | ✅ | ✅ | ✅ | ✅ | ✅<sup>2</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅<sup>5</sup> | ✅ | ✅ | ✅ |
| CPython 3.14 | ✅ | ✅ | ✅ | ✅ | ✅<sup>2</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅<sup>5</sup> | ✅ | ✅ | ✅<sup>4</sup> |
| CPython 3.15<sup>6</sup> | ✅ | ✅ | ✅ | ✅ | ✅<sup>2</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅<sup>5</sup> | | N/A | N/A |
| 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 |
@@ -39,13 +39,15 @@ While cibuildwheel itself requires a recent Python version to run (we support th
<sup>**1** PyPy & GraalPy are only supported for manylinux wheels.</sup><br>
<sup>**2** Windows arm64 support is experimental.</sup><br>
<sup>**3** Experimental, not yet supported on PyPI, but can be used directly in web deployment. Use `--platform pyodide` to build.</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>
<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** Experimental alpha ABI, do not upload to PyPI yet.</sup><br>
<sup>**5** 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>**6** Python 3.15 requires opt-in using [`enable`](https://cibuildwheel.pypa.io/en/stable/options/#enable).</sup><br>
- Builds manylinux, musllinux, macOS, and Windows wheels for CPython, PyPy, and GraalPy
- Builds manylinux, musllinux, macOS, Windows, pyemscripten, iOS, and Android wheels
- Supports CPython, PyPy, and GraalPy
- Works on GitHub Actions, Azure Pipelines, CircleCI, and GitLab CI
- Bundles shared library dependencies on Linux and macOS through [auditwheel](https://github.com/pypa/auditwheel) and [delocate](https://github.com/matthew-brett/delocate)
- Bundles shared library dependencies on Linux through [auditwheel](https://github.com/pypa/auditwheel), macOS through [delocate](https://github.com/matthew-brett/delocate), and Windows through [delvewheel](https://github.com/adang1345/delvewheel)
- Runs your library's tests against the wheel-installed version of your library
See the [cibuildwheel 1 documentation](https://cibuildwheel.pypa.io/en/1.x/) if you need to build unsupported versions of Python, such as Python 2.
@@ -231,6 +231,8 @@ python_configurations = [
{ identifier = "cp313-android_x86_64", version = "3.13", url = "https://repo.maven.apache.org/maven2/com/chaquo/python/python/3.13.13/python-3.13.13-x86_64-linux-android.tar.gz" },
{ identifier = "cp314-android_arm64_v8a", version = "3.14", url = "https://www.python.org/ftp/python/3.14.5/python-3.14.5-aarch64-linux-android.tar.gz" },
{ identifier = "cp314-android_x86_64", version = "3.14", url = "https://www.python.org/ftp/python/3.14.5/python-3.14.5-x86_64-linux-android.tar.gz" },
{ identifier = "cp315-android_arm64_v8a", version = "3.15", url = "https://www.python.org/ftp/python/3.15.0/python-3.15.0b1-aarch64-linux-android.tar.gz" },
{ identifier = "cp315-android_x86_64", version = "3.15", url = "https://www.python.org/ftp/python/3.15.0/python-3.15.0b1-x86_64-linux-android.tar.gz" },
]
[ios]
+6 -3
View File
@@ -263,16 +263,20 @@ def _expected_wheels(
if musllinux_versions is None:
musllinux_versions = ["musllinux_1_2"]
enable_groups = get_enable_groups()
# 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"]
if EnableGroup.PyodidePrerelease in enable_groups:
python_abi_tags.append("cp314-cp314")
elif platform == "android" and python_abi_tags is None: # noqa: SIM114
elif platform == "android" and python_abi_tags is None:
python_abi_tags = [
"cp313-cp313",
"cp314-cp314",
]
if EnableGroup.CPythonPrerelease in enable_groups:
python_abi_tags += ["cp315-cp315"]
elif platform == "ios" and python_abi_tags is None:
python_abi_tags = [
"cp313-cp313",
@@ -289,8 +293,6 @@ def _expected_wheels(
"cp314-cp314t",
]
enable_groups = get_enable_groups()
if EnableGroup.CPythonPrerelease in enable_groups:
python_abi_tags += [
"cp315-cp315",
@@ -386,6 +388,7 @@ def _expected_wheels(
api_level = {
"cp313-cp313": 21,
"cp314-cp314": 24,
"cp315-cp315": 24,
}[python_abi_tag]
platform_tags = [f"android_{api_level}_{machine_arch}"]