Files
cibuildwheel/test/test_pyodide.py
T
Agriya KhetarpalHood ChathamJoe RickerbyJoe RickerbyHenry Schreinerpre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
163864158d feat: Pyodide improvements: version setting, standalone environments (#2002)
* Fix a typo: pyoodide ➡️ pyodide

* Add `pyodide_build_version` attribute

* Add version to xbuildenv log step

* Add version to Emscripten log step

* Use `pyodide-build`'s version for updating constraints

* Bump Pyodide constraints by updating `pyodide-build`

* Add a schema for `pyodide-version`

* Update Pyodide constraints

* Bump `pyodide-build` to new 0.29.0

* Test out another Pyodide identifier

* Update outdated Pyodide constraints

* Add Pyodide version to temp directory name

* Remove Pyodide 0.26.1 from build configurations

* Retrieve + validate + install specific xbuildenvs

* Test wheel builds with Pyodide 0.26.2

* Add correct Pyodide version to identifier temp dir

* Don't pre-call Pyodide xbuildenv search

* Fetch just the stable Pyodide versions

* Refactor search + validation + install into one step

* Move all of it under a lock

* Reorder xbuildenv installation

* Add env and cwd to xbuildenv search call

* Temporarily lower to 0.26.2 target

* Separate out search, validate, install; again

* Run xbuildenv search in `CIBW_CACHE_PATH`

* Remove prior `PYODIDE_ROOT` env vars, copy envs

* Validate doesn't need to depend on searching

* Add file lock when searching xbuildenvs

* Test the original version: 0.26.1

* Update Pyodide constraints

* Update constraints for `pyodide-build` 0.29.0 again

* Bump Pyodide from version 0.26.1 ➡️ version 0.26.4

* Add note on compatibility for macOS + other archs

* Note Pyodide version for Pyodide identifier

* Docs about `CIBW_PYODIDE_VERSION`

* Don't fetch just the stable versions

* Discard a variable that's not used later

* Rename `search_xbuildenv` ➡️ `get_xbuildenv_versions`

* `validate_xbuildenv` ➡️ `validate_xbuildenv_version`

* Replace ordered comment, add newline

* Replace sentence on macOS support

Co-Authored-By: Hood Chatham <roberthoodchatham@gmail.com>

* Capitalise: "pyodide" ➡️ "Pyodide"

Co-Authored-By: Hood Chatham <roberthoodchatham@gmail.com>

* "work" ➡️ "may succeed"

Co-Authored-By: Hood Chatham <roberthoodchatham@gmail.com>

* Add another job to test a custom Pyodide version

* Handle "v"-prefixed + non-prefixed versions

* Convert to a proper toml-able option, and remove some hardcoded versions

This removes the enscripten and pyodide-build version specs from
pyproject.toml - pyodide-build is spec'd in the constraints file, and
the emscripten version can be read from the pyodide-build output.

* Add a schema entry

* Add docs for CIBW_PYODIDE_VERSION

* Rephrase

* Add tests for pyodide-version

* Apply suggestions from code review

* Add python_build_standalone util

* Hook up to python-build-standalone, removing dependency on host python

* Remove python hard-code in action.yml

* Add log step

* Add workaround for https://github.com/pyodide/pyodide-build/issues/143

* Add emscripten pytest test

* Remove unneeded checks

* Fix a pytest invoke for emscripten

* Generate pyodide-build constraints from the pinned pyodide version

* Remove pyodide python-build-standalone workaround

* Fixup paths from newer version of pyodide-build

* Fix/skip some failing tests

* Use `python -m pytest` on pyodide, even on Linux

* Docs fixes

* Don't call the github API at runtime, cache the release assets instead

* Ignore pylint false positive

* Add version auto-updating for pyodide

* Add support for pyodide 3.13.

* Fix tests for multiple pyodide wheels

* Remove workaround for unreleased pyodide-build

* Rename to "test_pyodide"

* Fix pathname confusion

* Remove extra github actions job

* Fix expectation for test_abi_none

* Fix the custom_repair_wheel test to actually have clashing names

* Fix pinned version test

* Document test-command limitation

* Remove pyodide 0.28.0a1 for now

* Update constraints files

* Docs/test fixes post removing pyodide cp313

* Fix ABI test expectation

* Docs improvements

* Improve some comments

* Remove logic duplication

* remove pyodide special casing

* Refactor constraints code to use a utility script, circumventing import issues

* chore: nicer nox env

Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>

* fix: typo in variable name found by copilot

Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>

* Apply suggestions from code review

* Some more Pyodide version updates in the docs section

* We haven't released Pyodide v0.27.6 yet

* Back to the Github URL for cross-build-environments

* `pyodide-build`, not `emsdk` for Windows skips

Co-Authored-By: Hood Chatham <roberthoodchatham@gmail.com>

* Move to a separate `_json_request` function

Co-Authored-By: Hood Chatham <roberthoodchatham@gmail.com>

* Rename "retries" ➡️ "retry_count"

* Add some type hints

* Copy env vars before `UV_CUSTOM_COMPILE_COMMAND`

* Use `HTTPError.headers.get` instead

* Remove extra end quote

* Change download tests URL to `https://badssl.com/`

Co-Authored-By: Joe Rickerby <1244307+joerick@users.noreply.github.com>

* Download size changes, too

* Use jsdelivr for Github asset mirroring

* Bump to Pyodide v0.27.6

* Fix unit tests

* Move to pyodide v0.27.6 again

* Bump to pyodide-build 0.30.4

* Use new URL for cross-build environments metadata

Co-authored-by: Joe Rickerby <joerick@mac.com>

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>
Co-authored-by: Hood Chatham <roberthoodchatham@gmail.com>
Co-authored-by: Joe Rickerby <joerick@mac.com>
Co-authored-by: Henry Schreiner <henryschreineriii@gmail.com>
Co-authored-by: Joe Rickerby <1244307+joerick@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2025-05-20 16:59:58 -04:00

142 lines
4.3 KiB
Python

import contextlib
import subprocess
import sys
import textwrap
import pytest
from cibuildwheel.util.file import CIBW_CACHE_PATH
from . import test_projects, utils
basic_project = test_projects.new_c_project()
basic_project.files["check_node.py"] = r"""
import sys
import shutil
from pathlib import Path
from pyodide.code import run_js
def check_node():
# cibuildwheel adds a pinned node version to the PATH
# check it's in the PATH then, check it's the one that runs Pyodide
cibw_cache_path = Path(sys.argv[1]).resolve(strict=True)
# find the node executable in PATH
node = shutil.which("node")
assert node is not None, "node is None"
node_path = Path(node).resolve(strict=True)
# it shall be in cibuildwheel cache
assert cibw_cache_path in node_path.parents, f"{cibw_cache_path} not a parent of {node_path}"
# find the path to the node executable that runs pyodide
node_js = run_js("globalThis.process.execPath")
assert node_js is not None, "node_js is None"
node_js_path = Path(node_js).resolve(strict=True)
# it shall be the one pinned by cibuildwheel
assert node_js_path == node_path, f"{node_js_path} != {node_path}"
if __name__ == "__main__":
check_node()
"""
@pytest.mark.parametrize("use_pyproject_toml", [True, False])
def test_pyodide_build(tmp_path, use_pyproject_toml):
if sys.platform == "win32":
pytest.skip("pyodide-build doesn't work correctly on Windows")
if use_pyproject_toml:
basic_project.files["pyproject.toml"] = textwrap.dedent(
"""
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"
"""
)
project_dir = tmp_path / "project"
basic_project.generate(project_dir)
# check for node in 1 case only to reduce CI load
add_env = {}
if use_pyproject_toml:
add_env["CIBW_TEST_COMMAND"] = f"python {{project}}/check_node.py {CIBW_CACHE_PATH}"
# build the wheels
actual_wheels = utils.cibuildwheel_run(
project_dir,
add_args=["--platform", "pyodide"],
add_env=add_env,
)
# check that the expected wheels are produced
expected_wheels = [
"spam-0.1.0-cp312-cp312-pyodide_2024_0_wasm32.whl",
]
print("actual_wheels", actual_wheels)
print("expected_wheels", expected_wheels)
assert set(actual_wheels) == set(expected_wheels)
def test_pyodide_version_incompatible(tmp_path, capfd):
if sys.platform == "win32":
pytest.skip("pyodide-build doesn't work correctly on Windows")
basic_project.generate(tmp_path)
with pytest.raises(subprocess.CalledProcessError):
utils.cibuildwheel_run(
tmp_path,
add_args=["--platform", "pyodide"],
add_env={
"CIBW_DEPENDENCY_VERSIONS": "packages: pyodide-build==0.29.3",
"CIBW_PYODIDE_VERSION": "0.26.0a6",
},
)
out, err = capfd.readouterr()
assert "is not compatible with the pyodide-build version" in err
@pytest.mark.parametrize("expect_failure", [True, False])
def test_pyodide_build_and_test(tmp_path, expect_failure):
if sys.platform == "win32":
pytest.skip("pyodide-build doesn't work correctly on Windows")
if expect_failure:
basic_project.files["test/spam_test.py"] = textwrap.dedent(r"""
def test_filter():
assert 0 == 1
""")
else:
basic_project.files["test/spam_test.py"] = textwrap.dedent(r"""
import spam
def test_filter():
assert spam.filter("spam") == 0
""")
basic_project.generate(tmp_path)
context = (
pytest.raises(subprocess.CalledProcessError) if expect_failure else contextlib.nullcontext()
)
with context:
# build the wheels
actual_wheels = utils.cibuildwheel_run(
tmp_path,
add_args=["--platform", "pyodide"],
add_env={
"CIBW_TEST_REQUIRES": "pytest",
"CIBW_TEST_COMMAND": "python -m pytest",
},
)
# check that the expected wheels are produced
expected_wheels = [
"spam-0.1.0-cp312-cp312-pyodide_2024_0_wasm32.whl",
]
print("actual_wheels", actual_wheels)
print("expected_wheels", expected_wheels)
assert set(actual_wheels) == set(expected_wheels)