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:
agriya khetarpal
2026-05-09 14:01:41 -04:00
committed by GitHub
co-authored by Hood Chatham Gyeongjae Choi Henry Schreiner
parent 542335fb4a
commit d2c0e59833
20 changed files with 343 additions and 99 deletions
+10 -11
View File
@@ -94,20 +94,19 @@ def ensure_node(major_version: str) -> Path:
return path
def install_emscripten(
env: dict[str, str], version: str, xbuildenv_cache_path: Path, pyodide_version: str
) -> Path:
def install_emscripten(env: dict[str, str], version: str, xbuildenv_cache_path: Path) -> Path:
"""Install Emscripten via pyodide-build, which also applies Pyodide-specific patches."""
emcc_path = (
xbuildenv_cache_path / pyodide_version / "emsdk" / "upstream" / "emscripten" / "emcc"
emscripten_dir = Path(
call("pyodide", "config", "get", "emscripten_dir", env=env, capture_stdout=True).strip()
)
with FileLock(CIBW_CACHE_PATH / "emscripten.lock"):
if emcc_path.exists():
return emcc_path
if emscripten_dir.exists():
return emscripten_dir
call(
"pyodide",
"xbuildenv",
"install-emscripten",
"--force",
"--version",
version,
"--path",
@@ -115,8 +114,8 @@ def install_emscripten(
env=env,
cwd=CIBW_CACHE_PATH,
)
assert emcc_path.exists()
return emcc_path
assert emscripten_dir.exists()
return emscripten_dir
def get_all_xbuildenv_version_info(env: dict[str, str]) -> list[PyodideXBuildEnvInfo]:
@@ -315,9 +314,9 @@ def setup_python(
log.step(
f"Installing Emscripten {emscripten_version} and applying Pyodide-specific patches ..."
)
emcc_path = install_emscripten(env, emscripten_version, xbuildenv_cache_path, pyodide_version)
emscripten_dir = install_emscripten(env, emscripten_version, xbuildenv_cache_path)
env["PATH"] = os.pathsep.join([str(emcc_path.parent), env["PATH"]])
env["PATH"] = os.pathsep.join([str(emscripten_dir), env["PATH"]])
return env
+2 -1
View File
@@ -206,7 +206,8 @@ python_configurations = [
[pyodide]
python_configurations = [
{ identifier = "cp312-pyodide_wasm32", version = "3.12", default_pyodide_version = "0.27.7", node_version = "v22" },
{ identifier = "cp313-pyodide_wasm32", version = "3.13", default_pyodide_version = "0.29.3", node_version = "v22" },
{ identifier = "cp313-pyodide_wasm32", version = "3.13", default_pyodide_version = "0.29.4", node_version = "v22" },
{ identifier = "cp314-pyodide_wasm32", version = "3.14", default_pyodide_version = "314.0.0a1", node_version = "v24" },
]
[android]
@@ -2,15 +2,15 @@
# nox -s update_constraints
annotated-types==0.7.0
# via pydantic
auditwheel-emscripten==0.2.3
auditwheel-emscripten==0.2.4
# via pyodide-build
build==1.2.2.post1
build==1.5.0
# via
# -r .nox/update_constraints/tmp/constraints-pyodide.in
# pyodide-build
certifi==2026.2.25
certifi==2026.4.22
# via requests
charset-normalizer==3.4.6
charset-normalizer==3.4.7
# via requests
click==8.1.8
# via
@@ -19,54 +19,54 @@ click==8.1.8
# pyodide-cli
distlib==0.4.0
# via virtualenv
filelock==3.25.2
filelock==3.29.0
# via
# python-discovery
# virtualenv
idna==3.11
idna==3.13
# via requests
leb128==1.0.9
# via auditwheel-emscripten
markdown-it-py==4.0.0
markdown-it-py==4.2.0
# via rich
mdurl==0.1.2
# via markdown-it-py
packaging==26.0
packaging==26.2
# via
# auditwheel-emscripten
# build
# pyodide-build
# wheel
pip==26.0.1
pip==26.1.1
# via -r .nox/update_constraints/tmp/constraints-pyodide.in
platformdirs==4.9.4
platformdirs==4.9.6
# via
# pyodide-build
# python-discovery
# virtualenv
pydantic==2.12.5
pydantic==2.13.4
# via
# pyodide-build
# pyodide-lock
pydantic-core==2.41.5
pydantic-core==2.46.4
# via pydantic
pygments==2.19.2
pygments==2.20.0
# via rich
pyodide-build==0.33.0
pyodide-build==0.34.3
# via -r .nox/update_constraints/tmp/constraints-pyodide.in
pyodide-cli==0.5.0
# via
# auditwheel-emscripten
# pyodide-build
pyodide-lock==0.1.2
pyodide-lock==0.1.3
# via pyodide-build
pyproject-hooks==1.2.0
# via build
python-discovery==1.2.0
python-discovery==1.3.0
# via virtualenv
requests==2.32.5
requests==2.33.1
# via pyodide-build
rich==14.3.3
rich==15.0.0
# via
# pyodide-build
# pyodide-cli
@@ -81,11 +81,11 @@ typing-inspection==0.4.2
# via pydantic
urllib3==2.6.3
# via requests
virtualenv==21.2.0
virtualenv==21.3.1
# via
# build
# pyodide-build
wheel==0.46.3
wheel==0.47.0
# via
# auditwheel-emscripten
# pyodide-build
@@ -2,15 +2,15 @@
# nox -s update_constraints
annotated-types==0.7.0
# via pydantic
auditwheel-emscripten==0.2.3
auditwheel-emscripten==0.2.4
# via pyodide-build
build==1.2.2.post1
build==1.5.0
# via
# -r .nox/update_constraints/tmp/constraints-pyodide.in
# pyodide-build
certifi==2026.2.25
certifi==2026.4.22
# via requests
charset-normalizer==3.4.6
charset-normalizer==3.4.7
# via requests
click==8.1.8
# via
@@ -19,54 +19,54 @@ click==8.1.8
# pyodide-cli
distlib==0.4.0
# via virtualenv
filelock==3.25.2
filelock==3.29.0
# via
# python-discovery
# virtualenv
idna==3.11
idna==3.13
# via requests
leb128==1.0.9
# via auditwheel-emscripten
markdown-it-py==4.0.0
markdown-it-py==4.2.0
# via rich
mdurl==0.1.2
# via markdown-it-py
packaging==26.0
packaging==26.2
# via
# auditwheel-emscripten
# build
# pyodide-build
# wheel
pip==26.0.1
pip==26.1.1
# via -r .nox/update_constraints/tmp/constraints-pyodide.in
platformdirs==4.9.4
platformdirs==4.9.6
# via
# pyodide-build
# python-discovery
# virtualenv
pydantic==2.12.5
pydantic==2.13.4
# via
# pyodide-build
# pyodide-lock
pydantic-core==2.41.5
pydantic-core==2.46.4
# via pydantic
pygments==2.19.2
pygments==2.20.0
# via rich
pyodide-build==0.33.0
pyodide-build==0.34.3
# via -r .nox/update_constraints/tmp/constraints-pyodide.in
pyodide-cli==0.5.0
# via
# auditwheel-emscripten
# pyodide-build
pyodide-lock==0.1.2
pyodide-lock==0.1.3
# via pyodide-build
pyproject-hooks==1.2.0
# via build
python-discovery==1.2.0
python-discovery==1.3.0
# via virtualenv
requests==2.32.5
requests==2.33.1
# via pyodide-build
rich==14.3.3
rich==15.0.0
# via
# pyodide-build
# pyodide-cli
@@ -81,11 +81,11 @@ typing-inspection==0.4.2
# via pydantic
urllib3==2.6.3
# via requests
virtualenv==21.2.0
virtualenv==21.3.1
# via
# build
# pyodide-build
wheel==0.46.3
wheel==0.47.0
# via
# auditwheel-emscripten
# pyodide-build
@@ -0,0 +1,91 @@
# This file was autogenerated by uv via the following command:
# nox -s update_constraints
annotated-types==0.7.0
# via pydantic
auditwheel-emscripten==0.2.4
# via pyodide-build
build==1.5.0
# via
# -r .nox/update_constraints/tmp/constraints-pyodide.in
# pyodide-build
certifi==2026.4.22
# via requests
charset-normalizer==3.4.7
# via requests
click==8.1.8
# via
# -r .nox/update_constraints/tmp/constraints-pyodide.in
# pyodide-build
# pyodide-cli
distlib==0.4.0
# via virtualenv
filelock==3.29.0
# via
# python-discovery
# virtualenv
idna==3.13
# via requests
leb128==1.0.9
# via auditwheel-emscripten
markdown-it-py==4.2.0
# via rich
mdurl==0.1.2
# via markdown-it-py
packaging==26.2
# via
# auditwheel-emscripten
# build
# pyodide-build
# wheel
pip==26.1.1
# via -r .nox/update_constraints/tmp/constraints-pyodide.in
platformdirs==4.9.6
# via
# pyodide-build
# python-discovery
# virtualenv
pydantic==2.13.4
# via
# pyodide-build
# pyodide-lock
pydantic-core==2.46.4
# via pydantic
pygments==2.20.0
# via rich
pyodide-build==0.34.3
# via -r .nox/update_constraints/tmp/constraints-pyodide.in
pyodide-cli==0.5.0
# via
# auditwheel-emscripten
# pyodide-build
pyodide-lock==0.1.3
# via pyodide-build
pyproject-hooks==1.2.0
# via build
python-discovery==1.3.0
# via virtualenv
requests==2.33.1
# via pyodide-build
rich==15.0.0
# via
# pyodide-build
# pyodide-cli
ruamel-yaml==0.19.1
# via pyodide-build
typing-extensions==4.15.0
# via
# pydantic
# pydantic-core
# typing-inspection
typing-inspection==0.4.2
# via pydantic
urllib3==2.6.3
# via requests
virtualenv==21.3.1
# via
# build
# pyodide-build
wheel==0.47.0
# via
# auditwheel-emscripten
# pyodide-build
+15 -10
View File
@@ -33,6 +33,7 @@ class EnableGroup(StrEnum):
GraalPy = "graalpy"
PyPy = "pypy"
PyPyEoL = "pypy-eol"
PyodideEoL = "pyodide-eol"
PyodidePrerelease = "pyodide-prerelease"
@classmethod
@@ -93,17 +94,21 @@ class BuildSelector:
return False
if EnableGroup.GraalPy not in self.enable and fnmatch(build_id, "gp*"):
return False
# TODO: Re-enable this when we have Pyodide prereleases again (e.g., 0.29.0a1+)
# Python 3.13 support became stable in Pyodide 0.28.0, so it no longer needs a prerelease
# flag.
# Also update Pyodide tests in unit_test/build_selector_test.py accordingly.
# When re-enabling, update the pattern to match the experimental Python version in case
# it is bumped to Python 3.14 (likely cp314-pyodide_* but could remain as 3.13 as well).
if EnableGroup.PyodideEoL not in self.enable and fnmatch(build_id, "cp312-pyodide_*"):
return False
# NOTE: Disable this when we don't have any Pyodide prereleases (e.g., 314.0.0a1+)
# When doing this, also:
# 1. update Pyodide tests in unit_test/build_selector_test.py and unit_test/options_test.py accordingly.
# 2. update Python versions for Pyodide identifiers in cibuildwheel/selector.py.
# 3. update constraints as necessary via bin/generate_pyodide_constraints.py and add/delete
# Pyodide constraints files in cibuildwheel/resources/constraints/ as necessary.
# When disabling, update the pattern to match the experimental Python version in case
# it is bumped to Python 3.15 (likely cp315-pyodide_* but could remain as 3.14 as well).
# This depends on the CPython version being used in the Pyodide runtime at the time.
# if EnableGroup.PyodidePrerelease not in self.enable and fnmatch(
# build_id, "cp313-pyodide_*"
# ):
# return False
if EnableGroup.PyodidePrerelease not in self.enable and fnmatch(
build_id, "cp314-pyodide_*"
):
return False
should_build = selector_matches(self.build_config, build_id)
should_skip = selector_matches(self.skip_config, build_id)