Validate pyodide-version option against Pyodide build identifier (#2925)
* Validate pyodide-version against identifier * Add tests * Allow Pyodide nightly xbuildenvs too (for later)
This commit is contained in:
@@ -218,6 +218,36 @@ def validate_pyodide_build_version(
|
|||||||
raise errors.FatalError(msg)
|
raise errors.FatalError(msg)
|
||||||
|
|
||||||
|
|
||||||
|
def validate_pyodide_target_python(
|
||||||
|
xbuildenv_info: PyodideXBuildEnvInfo, python_configuration: PythonConfiguration
|
||||||
|
) -> None:
|
||||||
|
"""
|
||||||
|
Validate that the resolved Pyodide xbuildenv targets the same Python version
|
||||||
|
as the identifier being built.
|
||||||
|
|
||||||
|
This is to catch the case where a global ``pyodide-version`` is applied to an
|
||||||
|
identifier whose Python version does not match, such as setting
|
||||||
|
``pyodide-version = "3Y.0.0"`` (a Python 3.Y environment) while
|
||||||
|
building ``cp3X-pyodide_wasm32``.
|
||||||
|
"""
|
||||||
|
xbuildenv_version = xbuildenv_info["version"]
|
||||||
|
identifier = python_configuration.identifier
|
||||||
|
expected_version = python_configuration.version
|
||||||
|
default_version = python_configuration.default_pyodide_version
|
||||||
|
xbuildenv_python_minor = ".".join(xbuildenv_info["python"].split(".")[:2])
|
||||||
|
if xbuildenv_python_minor != expected_version:
|
||||||
|
msg = unwrap_preserving_paragraphs(f"""
|
||||||
|
The `pyodide-version` option is set to {xbuildenv_version}, which
|
||||||
|
provides Python {xbuildenv_python_minor}, but the {identifier} build
|
||||||
|
needs Python {expected_version}.
|
||||||
|
|
||||||
|
Either remove `pyodide-version` so {identifier} uses its default
|
||||||
|
({default_version}), or stop building {identifier} so that
|
||||||
|
`pyodide-version` only applies to an identifier it matches.
|
||||||
|
""")
|
||||||
|
raise errors.ConfigurationError(msg)
|
||||||
|
|
||||||
|
|
||||||
def install_xbuildenv(env: dict[str, str], xbuildenv_cache_path: Path, pyodide_version: str) -> str:
|
def install_xbuildenv(env: dict[str, str], xbuildenv_cache_path: Path, pyodide_version: str) -> str:
|
||||||
"""Install a particular Pyodide xbuildenv version and set a path to the Pyodide root."""
|
"""Install a particular Pyodide xbuildenv version and set a path to the Pyodide root."""
|
||||||
pyodide_root = xbuildenv_cache_path / pyodide_version / "xbuildenv" / "pyodide-root"
|
pyodide_root = xbuildenv_cache_path / pyodide_version / "xbuildenv" / "pyodide-root"
|
||||||
@@ -337,6 +367,10 @@ def setup_python(
|
|||||||
xbuildenv_info=xbuildenv_info,
|
xbuildenv_info=xbuildenv_info,
|
||||||
pyodide_build_version=pyodide_build_version,
|
pyodide_build_version=pyodide_build_version,
|
||||||
)
|
)
|
||||||
|
validate_pyodide_target_python(
|
||||||
|
xbuildenv_info=xbuildenv_info,
|
||||||
|
python_configuration=python_configuration,
|
||||||
|
)
|
||||||
|
|
||||||
xbuildenv_cache_path = CIBW_CACHE_PATH / f"pyodide-build-{pyodide_build_version}"
|
xbuildenv_cache_path = CIBW_CACHE_PATH / f"pyodide-build-{pyodide_build_version}"
|
||||||
|
|
||||||
|
|||||||
@@ -25,12 +25,19 @@ from cibuildwheel.options import (
|
|||||||
_get_pinned_container_images,
|
_get_pinned_container_images,
|
||||||
)
|
)
|
||||||
from cibuildwheel.platforms import ALL_PLATFORM_MODULES, get_build_identifiers
|
from cibuildwheel.platforms import ALL_PLATFORM_MODULES, get_build_identifiers
|
||||||
|
from cibuildwheel.platforms.pyodide import (
|
||||||
|
PyodideXBuildEnvInfo,
|
||||||
|
validate_pyodide_target_python,
|
||||||
|
)
|
||||||
|
from cibuildwheel.platforms.pyodide import (
|
||||||
|
PythonConfiguration as PyodidePythonConfiguration,
|
||||||
|
)
|
||||||
from cibuildwheel.util import resources
|
from cibuildwheel.util import resources
|
||||||
from cibuildwheel.util.packaging import DependencyConstraints
|
from cibuildwheel.util.packaging import DependencyConstraints
|
||||||
|
|
||||||
TYPE_CHECKING = False
|
TYPE_CHECKING = False
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from collections.abc import Sequence
|
from collections.abc import Callable, Sequence
|
||||||
|
|
||||||
PYPROJECT_1 = """
|
PYPROJECT_1 = """
|
||||||
[tool.cibuildwheel]
|
[tool.cibuildwheel]
|
||||||
@@ -106,6 +113,62 @@ def test_options_1(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
|
|||||||
assert local.pyodide_version == "0.29.4"
|
assert local.pyodide_version == "0.29.4"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def make_pyodide_xbuildenv_info() -> Callable[[str, str], PyodideXBuildEnvInfo]:
|
||||||
|
def _make(version: str, python: str) -> PyodideXBuildEnvInfo:
|
||||||
|
return {
|
||||||
|
"version": version,
|
||||||
|
"python": python,
|
||||||
|
"emscripten": "5.0.3",
|
||||||
|
"pyodide_build": {"min": None, "max": None},
|
||||||
|
"compatible": True,
|
||||||
|
}
|
||||||
|
|
||||||
|
return _make
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def make_pyodide_python_configuration() -> Callable[[str, str], PyodidePythonConfiguration]:
|
||||||
|
def _make(identifier: str, version: str) -> PyodidePythonConfiguration:
|
||||||
|
return PyodidePythonConfiguration(
|
||||||
|
version=version,
|
||||||
|
identifier=identifier,
|
||||||
|
default_pyodide_version="0.0.0",
|
||||||
|
node_version="v22",
|
||||||
|
)
|
||||||
|
|
||||||
|
return _make
|
||||||
|
|
||||||
|
|
||||||
|
def test_validate_pyodide_target_python_matching(
|
||||||
|
make_pyodide_xbuildenv_info: Callable[[str, str], PyodideXBuildEnvInfo],
|
||||||
|
make_pyodide_python_configuration: Callable[[str, str], PyodidePythonConfiguration],
|
||||||
|
) -> None:
|
||||||
|
xbuildenv_info = make_pyodide_xbuildenv_info("314.0.0", "3.14.2")
|
||||||
|
config = make_pyodide_python_configuration("cp314-pyodide_wasm32", "3.14")
|
||||||
|
# should not raise
|
||||||
|
validate_pyodide_target_python(xbuildenv_info, config)
|
||||||
|
|
||||||
|
|
||||||
|
def test_validate_pyodide_target_python_mismatch(
|
||||||
|
make_pyodide_xbuildenv_info: Callable[[str, str], PyodideXBuildEnvInfo],
|
||||||
|
make_pyodide_python_configuration: Callable[[str, str], PyodidePythonConfiguration],
|
||||||
|
) -> None:
|
||||||
|
# a Python 3.14 xbuildenv applied to a cp313-pyodide_wasm32 build, when a global
|
||||||
|
# pyodide-version is set across mismatched targets
|
||||||
|
xbuildenv_info = make_pyodide_xbuildenv_info("314.0.0", "3.14.2")
|
||||||
|
config = make_pyodide_python_configuration("cp313-pyodide_wasm32", "3.13")
|
||||||
|
|
||||||
|
with pytest.raises(errors.ConfigurationError) as exc_info:
|
||||||
|
validate_pyodide_target_python(xbuildenv_info, config)
|
||||||
|
|
||||||
|
message = str(exc_info.value)
|
||||||
|
assert "cp313-pyodide_wasm32" in message
|
||||||
|
assert "314.0.0" in message
|
||||||
|
assert "3.13" in message
|
||||||
|
assert "3.14" in message
|
||||||
|
|
||||||
|
|
||||||
def test_test_and_audit_requires_with_dependency_specifiers(tmp_path: Path) -> None:
|
def test_test_and_audit_requires_with_dependency_specifiers(tmp_path: Path) -> None:
|
||||||
"""Regression test for https://github.com/pypa/cibuildwheel/issues/2912"""
|
"""Regression test for https://github.com/pypa/cibuildwheel/issues/2912"""
|
||||||
pyproject_toml = tmp_path / "pyproject.toml"
|
pyproject_toml = tmp_path / "pyproject.toml"
|
||||||
|
|||||||
Reference in New Issue
Block a user