feat: pyemscripten platform tag (PEP 783), 314.0a1, pyodide-eol flag, and maintenance updates (#2812)
* Use `pyodide config get emscripten_dir` * Update constraints * Updates for `pyemscripten` platform tag * Weird constraints stuff... * Revert "Weird constraints stuff..." This reverts commit 4bd785de872269c0b27362ee800f17288b2b4789. * Add some special constraints for pyodide * Wheel pyemscripten collision * Put delocate back in constraints (not needed tho) * Drop Pyodide 0.27.7 (cp312-pyodide_wasm32) * Add Pyodide 314.0.0a1 (cp314-pyodide_wasm32) * Delete no-longer-needed Pyodide 312 constraints * Update Pyodide 313 and 314 constraints * Add back prerelease stuff and update tests * Fix `test_pyodide_on_windows` * Update and fix tests some more * Also enable pyodide-prerelease in GHA sample build * Update tests yet again (`SINGLE_PYTHON_VERSION` changes) * Add a Pyodide-specific maintenance guide * Add suggestions from Hood and Gyeongjae Co-Authored-By: Hood Chatham <roberthoodchatham@gmail.com> Co-Authored-By: Gyeongjae Choi <def6488@gmail.com> * Add "Last updated: May 2026" to Pyodide document * Add a Pyodide EOL filter * Fix typo * Update maintenance docs about EoL Pyodide * Add Pyodide 312 constraints back * Update Pyodide 313 and 314 constraints * Remove "experimental" note about Pyodide * Remove another experimental Pyodide sentence * Add docs about the `pyodide-eol` enable option --------- Co-authored-by: Hood Chatham <roberthoodchatham@gmail.com> Co-authored-by: Gyeongjae Choi <def6488@gmail.com> Co-authored-by: Henry Schreiner <henryfs@princeton.edu>
This commit is contained in:
co-authored by
Hood Chatham
Gyeongjae Choi
Henry Schreiner
parent
542335fb4a
commit
d2c0e59833
@@ -43,15 +43,20 @@ def test_abi3(tmp_path: Path) -> None:
|
||||
project_dir,
|
||||
add_env={
|
||||
# free_threaded, GraalPy, and PyPy do not have a Py_LIMITED_API equivalent, just build one of those
|
||||
# pyodide uses cp313 (the stable version) which supports limited API / abi3
|
||||
# also limit the number of builds for test performance reasons
|
||||
"CIBW_BUILD": "cp39-* cp310-* pp310-* gp312_250-* cp312-* cp314t-*",
|
||||
"CIBW_BUILD": (
|
||||
"cp313-*"
|
||||
if utils.get_platform() == "pyodide"
|
||||
else "cp39-* cp310-* pp310-* gp312_250-* cp312-* cp314t-*"
|
||||
),
|
||||
"CIBW_ENABLE": "all",
|
||||
},
|
||||
)
|
||||
|
||||
# check that the expected wheels are produced
|
||||
if utils.get_platform() == "pyodide":
|
||||
# there's only 1 possible configuration for pyodide, cp312. It builds
|
||||
# there's only 1 possible configuration for pyodide, cp313. It builds
|
||||
# a wheel that is tagged abi3, compatible back to 3.10
|
||||
expected_wheels = utils.expected_wheels(
|
||||
"spam",
|
||||
|
||||
@@ -18,10 +18,10 @@ from pathlib import Path
|
||||
wheel = Path(sys.argv[1])
|
||||
dest_dir = Path(sys.argv[2])
|
||||
platform = wheel.stem.split("-")[-1]
|
||||
if platform.startswith("pyodide"):
|
||||
# for the sake of this test, munge the pyodide platforms into one, it's
|
||||
if platform.startswith("pyemscripten"):
|
||||
# for the sake of this test, munge the pyemscripten platforms into one, it's
|
||||
# not valid, but it does activate the uniqueness check
|
||||
platform = "pyodide"
|
||||
platform = "pyemscripten"
|
||||
|
||||
name = f"spam-0.1.0-py2-none-{platform}.whl"
|
||||
dest = dest_dir / name
|
||||
|
||||
@@ -77,13 +77,13 @@ def get_versions_from_constraint_file(constraint_file: Path) -> dict[str, str]:
|
||||
return dict(re.findall(VERSION_REGEX, constraint_file_text))
|
||||
|
||||
|
||||
@pytest.mark.parametrize("python_version", ["3.8", "3.12"])
|
||||
@pytest.mark.parametrize("python_version", ["3.8", "3.13"])
|
||||
def test_pinned_versions(
|
||||
tmp_path: Path, python_version: str, build_frontend_env_nouv: dict[str, str]
|
||||
) -> None:
|
||||
if utils.get_platform() == "linux":
|
||||
pytest.skip("linux doesn't pin individual tool versions, it pins manylinux images instead")
|
||||
if python_version != "3.12" and utils.get_platform() == "pyodide":
|
||||
if python_version != "3.13" and utils.get_platform() == "pyodide":
|
||||
pytest.skip(f"pyodide does not support Python {python_version}")
|
||||
if (
|
||||
python_version == "3.8"
|
||||
@@ -124,7 +124,7 @@ def test_pinned_versions(
|
||||
expected_wheels = [
|
||||
w
|
||||
for w in utils.expected_wheels("spam", "0.1.0")
|
||||
if f"-cp{version_no_dot}" in w or f"-pp{version_no_dot}" in w
|
||||
if f"-cp{version_no_dot}-cp{version_no_dot}-" in w or f"-pp{version_no_dot}-" in w
|
||||
]
|
||||
|
||||
assert set(actual_wheels) == set(expected_wheels)
|
||||
@@ -140,11 +140,20 @@ def test_dependency_constraints(
|
||||
project_dir = tmp_path / "project"
|
||||
test_projects.new_c_project().generate(project_dir)
|
||||
|
||||
tool_versions = {
|
||||
"pip": "23.1.2",
|
||||
"build": "1.2.2",
|
||||
"delocate": "0.10.3",
|
||||
}
|
||||
if utils.get_platform() == "pyodide":
|
||||
# pyodide-build 0.34+ requires build~=1.4.0, so we must use a
|
||||
# compatible version here. delocate is macOS-only and not used on pyodide.
|
||||
tool_versions = {
|
||||
"pip": "23.1.2",
|
||||
"build": "1.4.2",
|
||||
"delocate": "0.10.3",
|
||||
}
|
||||
else:
|
||||
tool_versions = {
|
||||
"pip": "23.1.2",
|
||||
"build": "1.2.2",
|
||||
"delocate": "0.10.3",
|
||||
}
|
||||
|
||||
if method == "file":
|
||||
constraints_file = tmp_path / "constraints file.txt"
|
||||
|
||||
@@ -34,7 +34,7 @@ def test_cross_compiled_build(tmp_path: Path) -> None:
|
||||
add_env={"CIBW_ARCHS": "x86_64, universal2, arm64"},
|
||||
single_python=True,
|
||||
)
|
||||
python_tag = "cp{}{}".format(*utils.SINGLE_PYTHON_VERSION)
|
||||
python_tag = "cp{0}{1}-cp{0}{1}-".format(*utils.SINGLE_PYTHON_VERSION)
|
||||
expected_wheels = [w for w in ALL_MACOS_WHEELS if python_tag in w]
|
||||
assert set(actual_wheels) == set(expected_wheels)
|
||||
|
||||
@@ -176,7 +176,7 @@ def test_universal2_testing_on_x86_64(
|
||||
else:
|
||||
assert warning_message in captured.err
|
||||
|
||||
python_tag = "cp{}{}".format(*utils.SINGLE_PYTHON_VERSION)
|
||||
python_tag = "cp{0}{1}-cp{0}{1}-".format(*utils.SINGLE_PYTHON_VERSION)
|
||||
expected_wheels = [w for w in ALL_MACOS_WHEELS if python_tag in w and "universal2" in w]
|
||||
|
||||
assert set(actual_wheels) == set(expected_wheels)
|
||||
@@ -210,7 +210,7 @@ def test_universal2_testing_on_arm64(
|
||||
assert "running tests on arm64 with pillow" in captured.out
|
||||
assert "running tests on x86_64 with pillow" in captured.out
|
||||
|
||||
python_tag = "cp{}{}".format(*utils.SINGLE_PYTHON_VERSION)
|
||||
python_tag = "cp{0}{1}-cp{0}{1}-".format(*utils.SINGLE_PYTHON_VERSION)
|
||||
expected_wheels = [w for w in ALL_MACOS_WHEELS if python_tag in w and "universal2" in w]
|
||||
assert set(actual_wheels) == set(expected_wheels)
|
||||
|
||||
|
||||
@@ -79,8 +79,8 @@ def test_pyodide_build(tmp_path: Path, use_pyproject_toml: bool) -> None:
|
||||
|
||||
# check that the expected wheels are produced
|
||||
expected_wheels = [
|
||||
"spam-0.1.0-cp312-cp312-pyodide_2024_0_wasm32.whl",
|
||||
"spam-0.1.0-cp313-cp313-pyodide_2025_0_wasm32.whl",
|
||||
"spam-0.1.0-cp313-cp313-pyemscripten_2025_0_wasm32.whl",
|
||||
"spam-0.1.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl",
|
||||
]
|
||||
|
||||
print("actual_wheels", actual_wheels)
|
||||
@@ -144,8 +144,8 @@ def test_pyodide_build_and_test(tmp_path: Path, expect_failure: bool) -> None:
|
||||
)
|
||||
# check that the expected wheels are produced
|
||||
expected_wheels = [
|
||||
"spam-0.1.0-cp312-cp312-pyodide_2024_0_wasm32.whl",
|
||||
"spam-0.1.0-cp313-cp313-pyodide_2025_0_wasm32.whl",
|
||||
"spam-0.1.0-cp313-cp313-pyemscripten_2025_0_wasm32.whl",
|
||||
"spam-0.1.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl",
|
||||
]
|
||||
assert set(actual_wheels) == set(expected_wheels)
|
||||
|
||||
@@ -170,6 +170,6 @@ def test_pyodide_repair_wheel(tmp_path: Path) -> None:
|
||||
|
||||
# check that the expected wheels are produced
|
||||
expected_wheels = [
|
||||
"spam-0.1.0-cp312-cp312-pyodide_2024_0_wasm32.whl",
|
||||
"spam-0.1.0-cp313-cp313-pyemscripten_2025_0_wasm32.whl",
|
||||
]
|
||||
assert set(actual_wheels) == set(expected_wheels)
|
||||
|
||||
+10
-9
@@ -26,7 +26,7 @@ EMULATED_ARCHS: Final[list[str]] = sorted(
|
||||
PYPY_ARCHS = ["x86_64", "i686", "AMD64", "aarch64", "arm64"]
|
||||
GRAALPY_ARCHS = ["x86_64", "AMD64", "aarch64", "arm64"]
|
||||
|
||||
SINGLE_PYTHON_VERSION: Final[tuple[int, int]] = (3, 12)
|
||||
SINGLE_PYTHON_VERSION: Final[tuple[int, int]] = (3, 13)
|
||||
|
||||
# temporary workaround: set by build_frontend_env fixture to skip graalpy
|
||||
# when uv is the build frontend (compatibility issue between graalpy and uv)
|
||||
@@ -263,11 +263,11 @@ def _expected_wheels(
|
||||
if musllinux_versions is None:
|
||||
musllinux_versions = ["musllinux_1_2"]
|
||||
|
||||
# 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 = [
|
||||
"cp312-cp312",
|
||||
"cp313-cp313",
|
||||
]
|
||||
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
|
||||
python_abi_tags = [
|
||||
"cp313-cp313",
|
||||
@@ -412,13 +412,14 @@ def _expected_wheels(
|
||||
elif platform == "pyodide":
|
||||
platform_tags = {
|
||||
"cp312-cp312": ["pyodide_2024_0_wasm32"],
|
||||
"cp313-cp313": ["pyodide_2025_0_wasm32"],
|
||||
"cp313-cp313": ["pyemscripten_2025_0_wasm32"],
|
||||
"cp314-cp314": ["pyemscripten_2026_0_wasm32"],
|
||||
}.get(python_abi_tag, [])
|
||||
|
||||
if not platform_tags:
|
||||
# for example if the python tag is `none` or `abi3`, all
|
||||
# platform tags are built with that python tag
|
||||
platform_tags = ["pyodide_2024_0_wasm32"]
|
||||
# for example if the python tag is `none` or `abi3`, the wheel
|
||||
# is built by the stable cp313 Python version
|
||||
platform_tags = ["pyemscripten_2025_0_wasm32"]
|
||||
|
||||
else:
|
||||
msg = f"Unsupported platform {platform!r}"
|
||||
|
||||
Reference in New Issue
Block a user