Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dded469d60 | ||
|
|
327f5c327d | ||
|
|
163864158d | ||
|
|
c3c260dff7 | ||
|
|
fcdbed860e | ||
|
|
9dd7192d89 | ||
|
|
bd641d11de |
@@ -195,7 +195,7 @@ jobs:
|
||||
run: uv run --no-sync pytest --run-emulation ${{ matrix.arch }} test/test_emulation.py
|
||||
|
||||
test-pyodide:
|
||||
name: Test cibuildwheel building Pyodide wheels
|
||||
name: Test pyodide
|
||||
needs: lint
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 180
|
||||
@@ -222,6 +222,19 @@ jobs:
|
||||
env:
|
||||
CIBW_PLATFORM: pyodide
|
||||
|
||||
- name: Run a sample build (GitHub Action) for an overridden Pyodide version
|
||||
uses: ./
|
||||
with:
|
||||
package-dir: sample_proj
|
||||
output-dir: wheelhouse
|
||||
# In case this breaks at any point in time, switch to using the latest version
|
||||
# available or any other version that is not the same as the default one set
|
||||
# in cibuildwheel/resources/build-platforms.toml.
|
||||
env:
|
||||
CIBW_PLATFORM: pyodide
|
||||
CIBW_BUILD: "cp312*"
|
||||
CIBW_PYODIDE_VERSION: "0.27.6"
|
||||
|
||||
- name: Run tests with 'CIBW_PLATFORM' set to 'pyodide'
|
||||
run: |
|
||||
uv run --no-sync ./bin/run_tests.py
|
||||
|
||||
@@ -55,3 +55,7 @@ jobs:
|
||||
sign-commits: true
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
delete-branch: true
|
||||
labels: |
|
||||
CI: GraalPy
|
||||
CI: PyPy
|
||||
dependencies
|
||||
|
||||
@@ -14,7 +14,7 @@ repos:
|
||||
- id: trailing-whitespace
|
||||
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.11.9
|
||||
rev: v0.11.10
|
||||
hooks:
|
||||
- id: ruff
|
||||
args: ["--fix", "--show-fixes"]
|
||||
|
||||
@@ -97,7 +97,7 @@ jobs:
|
||||
- uses: actions/setup-python@v5
|
||||
|
||||
- name: Install cibuildwheel
|
||||
run: python -m pip install cibuildwheel==3.0.0b1
|
||||
run: python -m pip install cibuildwheel==3.0.0b2
|
||||
|
||||
- name: Build wheels
|
||||
run: python -m cibuildwheel --output-dir wheelhouse
|
||||
@@ -219,7 +219,19 @@ Changelog
|
||||
|
||||
### v3.0.0
|
||||
|
||||
Not yet released, but available for testing
|
||||
Not yet released, but available for testing.
|
||||
|
||||
Note - when using a beta version, be sure to check the [latest docs](https://cibuildwheel.pypa.io/en/latest/), rather than the stable version, which is still on v2.X.
|
||||
|
||||
Known issues:
|
||||
- ⚠️ The CWD for test-command has changed in v3.0, but that is still [being debated](https://github.com/pypa/cibuildwheel/issues/2406), it might change before the final release. Please provide feedback on the aforementioned issue if you do (or don't!) encounter issues with this.
|
||||
|
||||
#### v3.0.0b2
|
||||
|
||||
_25 May 2025_
|
||||
|
||||
- ✨ Adds the [`CIBW_TEST_ENVIRONMENT`](https://cibuildwheel.pypa.io/en/latest/options/#test-environment) option, which allows you to set environment variables for the test command. cibuildwheel now sets `PYTHONSAFEPATH=1` in test environments by default, to avoid picking up package imports from the local directory - we want to test the installed wheel, not the source tree! You can change that, or any other environment variable in the test environment using this option. (#2388)
|
||||
- ✨ Improves support for Pyodide builds and adds the [`CIBW_PYODIDE_VERSION`](https://cibuildwheel.pypa.io/en/latest/options/#pyodide-version) option, which allows you to specify the version of Pyodide to use for builds. (#2002)
|
||||
|
||||
#### v3.0.0b1
|
||||
|
||||
@@ -230,7 +242,11 @@ _19 May 2025_
|
||||
- ✨ Adds CPython 3.14 support, under the [`enable` option](https://cibuildwheel.pypa.io/en/latest/options/#enable) `cpython-prerelease`. This version of cibuildwheel uses 3.14.0b1.
|
||||
|
||||
_While CPython is in beta, the ABI can change, so your wheels might not be compatible with the final release. For this reason, we don't recommend distributing wheels until RC1, at which point 3.14 will be available in cibuildwheel without the flag._ (#2390)
|
||||
- ✨ Adds the [test-sources option](https://cibuildwheel.pypa.io/en/latest/options/#test-sources). \[discussion about the test cwd change and how to use to come!\]
|
||||
- ✨ Adds the [test-sources option](https://cibuildwheel.pypa.io/en/latest/options/#test-sources), and changes the working directory for tests.
|
||||
|
||||
- If this option is set, cibuildwheel will copy the files and folders specified in `test-sources` into a temporary directory, and run the tests from there. This is required for iOS builds, but also useful for other platforms, as it allows you to test the installed wheel without any chance of accidentally importing from the source tree.
|
||||
- If this option is not set, cibuildwheel will run the tests in the source tree. This is a change from the previous behavior, where cibuildwheel would run the tests from a temporary directory. We're still investigating what's best here, so if you encounter any issues with this, please let us know in [issue #2406](https://github.com/pypa/cibuildwheel/issues/2406).
|
||||
|
||||
- ✨ Added `dependency-versions` inline syntax (#2123)
|
||||
- 🛠 EOL manylinux options can no longer be specified by their shortname. Full OCI URL can still be used for these images, if you wish (#2316)
|
||||
- 🛠 Build environments no longer have setuptools and wheel preinstalled. (#2329)
|
||||
@@ -252,13 +268,6 @@ _24 March 2025_
|
||||
- 🛠 Dependency updates, including a manylinux update that fixes an ['undefined symbol' error](https://github.com/pypa/manylinux/issues/1760) in gcc-toolset (#2334)
|
||||
-
|
||||
|
||||
### v2.23.1
|
||||
|
||||
_15 March 2025_
|
||||
|
||||
- ⚠️ Added warnings when the shorthand values `manylinux1`, `manylinux2010`, `manylinux_2_24`, and `musllinux_1_1` are used to specify the images in linux builds. The shorthand to these (unmaintainted) images will be removed in v3.0. If you want to keep using these images, explicitly opt-in using the full image URL, which can be found in [this file](https://github.com/pypa/cibuildwheel/blob/v2.23.1/cibuildwheel/resources/pinned_docker_images.cfg). (#2312)
|
||||
- 🛠 Dependency updates, including a manylinux update which fixes an [issue with rustup](https://github.com/pypa/cibuildwheel/issues/2303). (#2315)
|
||||
|
||||
<!-- END bin/update_readme_changelog.py -->
|
||||
|
||||
---
|
||||
|
||||
+1
-2
@@ -24,11 +24,10 @@ branding:
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
# Set up the version of Python that supports pyodide
|
||||
- uses: actions/setup-python@v5
|
||||
id: python
|
||||
with:
|
||||
python-version: "3.12"
|
||||
python-version: "3.11 - 3.13"
|
||||
update-environment: false
|
||||
|
||||
- id: cibw
|
||||
|
||||
Executable
+69
@@ -0,0 +1,69 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
import textwrap
|
||||
from pathlib import Path
|
||||
|
||||
import click
|
||||
|
||||
from cibuildwheel.extra import get_pyodide_xbuildenv_info
|
||||
|
||||
|
||||
@click.command()
|
||||
@click.argument(
|
||||
"pyodide-version",
|
||||
type=str,
|
||||
)
|
||||
@click.option(
|
||||
"--output-file",
|
||||
type=click.Path(),
|
||||
default=None,
|
||||
help="Output file to write the constraints to. If not provided, the constraints will be printed to stdout.",
|
||||
)
|
||||
def generate_pyodide_constraints(pyodide_version: str, output_file: str | None = None) -> None:
|
||||
"""
|
||||
Generate constraints for a specific Pyodide version. The constraints are
|
||||
generated based on the Pyodide version's xbuildenv info, which is retrieved
|
||||
from the Pyodide repository.
|
||||
|
||||
These constraints should then be 'pinned' using `uv pip compile`.
|
||||
|
||||
Example usage:
|
||||
|
||||
bin/generate_pyodide_constraints.py 0.27.0
|
||||
"""
|
||||
xbuildenv_info = get_pyodide_xbuildenv_info()
|
||||
try:
|
||||
pyodide_version_xbuildenv_info = xbuildenv_info["releases"][pyodide_version]
|
||||
except KeyError as e:
|
||||
msg = f"Pyodide version {pyodide_version} not found in xbuildenv info. Versions available: {', '.join(xbuildenv_info['releases'].keys())}"
|
||||
raise click.BadParameter(msg) from e
|
||||
|
||||
pyodide_build_min_version = pyodide_version_xbuildenv_info.get("min_pyodide_build_version")
|
||||
pyodide_build_max_version = pyodide_version_xbuildenv_info.get("max_pyodide_build_version")
|
||||
|
||||
pyodide_build_specifier_parts: list[str] = []
|
||||
|
||||
if pyodide_build_min_version:
|
||||
pyodide_build_specifier_parts.append(f">={pyodide_build_min_version}")
|
||||
if pyodide_build_max_version:
|
||||
pyodide_build_specifier_parts.append(f"<={pyodide_build_max_version}")
|
||||
|
||||
pyodide_build_specifier = ",".join(pyodide_build_specifier_parts)
|
||||
|
||||
constraints_txt = textwrap.dedent(f"""
|
||||
pip
|
||||
build[virtualenv]
|
||||
pyodide-build{pyodide_build_specifier}
|
||||
click<8.2
|
||||
""")
|
||||
|
||||
if output_file is None:
|
||||
print(constraints_txt)
|
||||
else:
|
||||
Path(output_file).write_text(constraints_txt)
|
||||
print(f"Constraints written to {output_file}", file=sys.stderr)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
generate_pyodide_constraints()
|
||||
@@ -197,6 +197,9 @@ properties:
|
||||
xbuild-tools:
|
||||
description: Binaries on the path that should be included in an isolated cross-build environment
|
||||
type: string_array
|
||||
pyodide-version:
|
||||
type: string
|
||||
description: Specify the version of Pyodide to use
|
||||
repair-wheel-command:
|
||||
description: Execute a shell command to repair each built wheel.
|
||||
type: string_array
|
||||
@@ -221,6 +224,9 @@ properties:
|
||||
test-skip:
|
||||
description: Skip running tests on some builds.
|
||||
type: string_array
|
||||
test-environment:
|
||||
description: Set environment variables for the test environment
|
||||
type: string_table
|
||||
"""
|
||||
|
||||
schema = yaml.safe_load(starter)
|
||||
@@ -300,6 +306,7 @@ items:
|
||||
test-extras: {"$ref": "#/$defs/inherit"}
|
||||
test-sources: {"$ref": "#/$defs/inherit"}
|
||||
test-requires: {"$ref": "#/$defs/inherit"}
|
||||
test-environment: {"$ref": "#/$defs/inherit"}
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
Executable
+59
@@ -0,0 +1,59 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import json
|
||||
|
||||
from cibuildwheel.extra import github_api_request
|
||||
from cibuildwheel.util.python_build_standalone import (
|
||||
PythonBuildStandaloneAsset,
|
||||
PythonBuildStandaloneReleaseData,
|
||||
)
|
||||
from cibuildwheel.util.resources import PYTHON_BUILD_STANDALONE_RELEASES
|
||||
|
||||
|
||||
def main() -> None:
|
||||
"""
|
||||
This script updates the vendored list of release assets to the latest
|
||||
version of astral-sh/python-build-standalone.
|
||||
"""
|
||||
|
||||
# Get the latest release tag from the GitHub API
|
||||
latest_release = github_api_request("repos/astral-sh/python-build-standalone/releases/latest")
|
||||
latest_tag = latest_release["tag_name"]
|
||||
|
||||
# Get the list of assets for the latest release
|
||||
github_assets = github_api_request(
|
||||
f"repos/astral-sh/python-build-standalone/releases/tags/{latest_tag}"
|
||||
)["assets"]
|
||||
|
||||
assets: list[PythonBuildStandaloneAsset] = []
|
||||
|
||||
for github_asset in github_assets:
|
||||
name = github_asset["name"]
|
||||
if not name.endswith("install_only.tar.gz"):
|
||||
continue
|
||||
url = github_asset["browser_download_url"]
|
||||
assets.append({"name": name, "url": url})
|
||||
|
||||
# Write the assets to the JSON file. One day, we might need to support
|
||||
# multiple releases, but for now, we only support the latest one
|
||||
json_file_contents: PythonBuildStandaloneReleaseData = {
|
||||
"releases": [
|
||||
{
|
||||
"tag": latest_tag,
|
||||
"assets": assets,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
with PYTHON_BUILD_STANDALONE_RELEASES.open("w", encoding="utf-8") as f:
|
||||
json.dump(json_file_contents, f, indent=2)
|
||||
# Add a trailing newline, our pre-commit hook requires it
|
||||
f.write("\n")
|
||||
|
||||
print(
|
||||
f"Updated {PYTHON_BUILD_STANDALONE_RELEASES.name} with {len(assets)} assets for tag {latest_tag}"
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
+51
-2
@@ -19,7 +19,7 @@ from packaging.version import Version
|
||||
from rich.logging import RichHandler
|
||||
from rich.syntax import Syntax
|
||||
|
||||
from cibuildwheel.extra import dump_python_configurations
|
||||
from cibuildwheel.extra import dump_python_configurations, get_pyodide_xbuildenv_info
|
||||
|
||||
log = logging.getLogger("cibw")
|
||||
|
||||
@@ -57,7 +57,14 @@ class ConfigApple(TypedDict):
|
||||
url: str
|
||||
|
||||
|
||||
AnyConfig = ConfigWinCP | ConfigWinPP | ConfigWinGP | ConfigApple
|
||||
class ConfigPyodide(TypedDict):
|
||||
identifier: str
|
||||
version: str
|
||||
default_pyodide_version: str
|
||||
node_version: str
|
||||
|
||||
|
||||
AnyConfig = ConfigWinCP | ConfigWinPP | ConfigWinGP | ConfigApple | ConfigPyodide
|
||||
|
||||
|
||||
# The following set of "Versions" classes allow the initial call to the APIs to
|
||||
@@ -347,6 +354,39 @@ class CPythonIOSVersions:
|
||||
return None
|
||||
|
||||
|
||||
class PyodideVersions:
|
||||
def __init__(self) -> None:
|
||||
xbuildenv_info = get_pyodide_xbuildenv_info()
|
||||
self.releases = xbuildenv_info["releases"]
|
||||
|
||||
def update_version_pyodide(
|
||||
self, identifier: str, version: Version, spec: Specifier, node_version: str
|
||||
) -> ConfigPyodide | None:
|
||||
# get releases that match the python version
|
||||
releases = [
|
||||
r for r in self.releases.values() if spec.contains(Version(r["python_version"]))
|
||||
]
|
||||
# sort by version, latest first
|
||||
releases.sort(key=lambda r: Version(r["version"]), reverse=True)
|
||||
|
||||
if not releases:
|
||||
msg = f"Pyodide not found for {spec}!"
|
||||
raise ValueError(msg)
|
||||
|
||||
final_releases = [r for r in releases if not Version(r["version"]).is_prerelease]
|
||||
|
||||
# prefer a final release if available, otherwise use the latest
|
||||
# pre-release
|
||||
release = final_releases[0] if final_releases else releases[0]
|
||||
|
||||
return ConfigPyodide(
|
||||
identifier=identifier,
|
||||
version=str(version),
|
||||
default_pyodide_version=release["version"],
|
||||
node_version=node_version,
|
||||
)
|
||||
|
||||
|
||||
# This is a universal interface to all the above Versions classes. Given an
|
||||
# identifier, it updates a config dict.
|
||||
|
||||
@@ -369,6 +409,8 @@ class AllVersions:
|
||||
|
||||
self.graalpy = GraalPyVersions()
|
||||
|
||||
self.pyodide = PyodideVersions()
|
||||
|
||||
def update_config(self, config: MutableMapping[str, str]) -> None:
|
||||
identifier = config["identifier"]
|
||||
version = Version(config["version"])
|
||||
@@ -407,6 +449,10 @@ class AllVersions:
|
||||
config_update = self.windows_arm64.update_version_windows(spec)
|
||||
elif "ios" in identifier:
|
||||
config_update = self.ios_cpython.update_version_ios(identifier, version)
|
||||
elif "pyodide" in identifier:
|
||||
config_update = self.pyodide.update_version_pyodide(
|
||||
identifier, version, spec, config["node_version"]
|
||||
)
|
||||
|
||||
assert config_update is not None, f"{identifier} not found!"
|
||||
config.update(**config_update)
|
||||
@@ -445,6 +491,9 @@ def update_pythons(force: bool, level: str) -> None:
|
||||
for config in configs["ios"]["python_configurations"]:
|
||||
all_versions.update_config(config)
|
||||
|
||||
for config in configs["pyodide"]["python_configurations"]:
|
||||
all_versions.update_config(config)
|
||||
|
||||
result_toml = dump_python_configurations(configs)
|
||||
|
||||
rich.print() # spacer
|
||||
|
||||
@@ -1 +1 @@
|
||||
__version__ = "3.0.0b1"
|
||||
__version__ = "3.0.0b2"
|
||||
|
||||
+70
-1
@@ -2,9 +2,16 @@
|
||||
These are utilities for the `/bin` scripts, not for the `cibuildwheel` program.
|
||||
"""
|
||||
|
||||
import json
|
||||
import time
|
||||
import typing
|
||||
import urllib.error
|
||||
import urllib.request
|
||||
from collections.abc import Mapping, Sequence
|
||||
from io import StringIO
|
||||
from typing import Protocol
|
||||
from typing import Any, NotRequired, Protocol
|
||||
|
||||
from cibuildwheel import __version__ as cibw_version
|
||||
|
||||
__all__ = ("Printable", "dump_python_configurations")
|
||||
|
||||
@@ -30,3 +37,65 @@ def dump_python_configurations(
|
||||
output.write("\n")
|
||||
# Strip the final newline, to avoid two blank lines at the end.
|
||||
return output.getvalue()[:-1]
|
||||
|
||||
|
||||
def _json_request(request: urllib.request.Request, timeout: int = 30) -> dict[str, Any]:
|
||||
with urllib.request.urlopen(request, timeout=timeout) as response:
|
||||
return typing.cast(dict[str, Any], json.load(response))
|
||||
|
||||
|
||||
def github_api_request(path: str, *, max_retries: int = 3) -> dict[str, Any]:
|
||||
"""
|
||||
Makes a GitHub API request to the given path and returns the JSON response.
|
||||
"""
|
||||
api_url = f"https://api.github.com/{path}"
|
||||
headers = {
|
||||
"Accept": "application/vnd.github.v3+json",
|
||||
"User-Agent": f"cibuildwheel/{cibw_version}",
|
||||
}
|
||||
request = urllib.request.Request(api_url, headers=headers)
|
||||
|
||||
for retry_count in range(max_retries):
|
||||
try:
|
||||
return _json_request(request)
|
||||
except (urllib.error.URLError, TimeoutError) as e:
|
||||
# pylint: disable=E1101
|
||||
if (
|
||||
isinstance(e, urllib.error.HTTPError)
|
||||
and (e.code == 403 or e.code == 429)
|
||||
and e.headers.get("x-ratelimit-remaining") == "0"
|
||||
):
|
||||
reset_time = int(e.headers.get("x-ratelimit-reset", 0))
|
||||
wait_time = max(0, reset_time - int(e.headers.get("date", 0)))
|
||||
print(f"Github rate limit exceeded. Waiting for {wait_time} seconds.")
|
||||
time.sleep(wait_time)
|
||||
else:
|
||||
print(f"Retrying GitHub API request due to error: {e}")
|
||||
|
||||
if retry_count == max_retries - 1:
|
||||
print(f"GitHub API request failed (Network error: {e}). Check network connection.")
|
||||
raise e
|
||||
|
||||
# Should never be reached but to keep the type checker happy
|
||||
msg = "Unexpected execution path in github_api_request"
|
||||
raise RuntimeError(msg)
|
||||
|
||||
|
||||
class PyodideXBuildEnvRelease(typing.TypedDict):
|
||||
version: str
|
||||
python_version: str
|
||||
emscripten_version: str
|
||||
min_pyodide_build_version: NotRequired[str]
|
||||
max_pyodide_build_version: NotRequired[str]
|
||||
|
||||
|
||||
class PyodideXBuildEnvInfo(typing.TypedDict):
|
||||
releases: dict[str, PyodideXBuildEnvRelease]
|
||||
|
||||
|
||||
def get_pyodide_xbuildenv_info() -> PyodideXBuildEnvInfo:
|
||||
xbuildenv_info_url = (
|
||||
"https://pyodide.github.io/pyodide/api/pyodide-cross-build-environments.json"
|
||||
)
|
||||
with urllib.request.urlopen(xbuildenv_info_url) as response:
|
||||
return typing.cast(PyodideXBuildEnvInfo, json.loads(response.read().decode("utf-8")))
|
||||
|
||||
@@ -107,10 +107,12 @@ class BuildOptions:
|
||||
test_requires: list[str]
|
||||
test_extras: str
|
||||
test_groups: list[str]
|
||||
test_environment: ParsedEnvironment
|
||||
build_verbosity: int
|
||||
build_frontend: BuildFrontendConfig | None
|
||||
config_settings: str
|
||||
container_engine: OCIContainerEngineConfig
|
||||
pyodide_version: str | None
|
||||
|
||||
@property
|
||||
def package_dir(self) -> Path:
|
||||
@@ -739,6 +741,15 @@ class Options:
|
||||
"test-sources", option_format=ListFormat(sep=" ", quote=shlex.quote)
|
||||
)
|
||||
)
|
||||
test_environment_config = self.reader.get(
|
||||
"test-environment", option_format=EnvironmentFormat()
|
||||
)
|
||||
try:
|
||||
test_environment = parse_environment(test_environment_config)
|
||||
except (EnvironmentParseError, ValueError) as e:
|
||||
msg = f"Malformed environment option {test_environment_config!r}"
|
||||
raise errors.ConfigurationError(msg) from e
|
||||
|
||||
test_requires = self.reader.get(
|
||||
"test-requires", option_format=ListFormat(sep=" ")
|
||||
).split()
|
||||
@@ -840,10 +851,13 @@ class Options:
|
||||
msg = f"Failed to parse container config. {e}"
|
||||
raise errors.ConfigurationError(msg) from e
|
||||
|
||||
pyodide_version = self.reader.get("pyodide-version", env_plat=False)
|
||||
|
||||
return BuildOptions(
|
||||
globals=self.globals,
|
||||
test_command=test_command,
|
||||
test_sources=test_sources,
|
||||
test_environment=test_environment,
|
||||
test_requires=[*test_requires, *test_requirements_from_groups],
|
||||
test_extras=test_extras,
|
||||
test_groups=test_groups,
|
||||
@@ -860,6 +874,7 @@ class Options:
|
||||
build_frontend=build_frontend,
|
||||
config_settings=config_settings,
|
||||
container_engine=container_engine,
|
||||
pyodide_version=pyodide_version or None,
|
||||
)
|
||||
|
||||
def check_for_invalid_configuration(self, identifiers: Iterable[str]) -> None:
|
||||
|
||||
@@ -536,13 +536,17 @@ def build(options: Options, tmp_path: Path) -> None:
|
||||
elif config.arch != os.uname().machine:
|
||||
log.step("Skipping tests on non-native simulator architecture")
|
||||
else:
|
||||
test_env = build_options.test_environment.as_dictionary(
|
||||
prev_environment=build_env
|
||||
)
|
||||
|
||||
if build_options.before_test:
|
||||
before_test_prepared = prepare_command(
|
||||
build_options.before_test,
|
||||
project=".",
|
||||
package=build_options.package_dir,
|
||||
)
|
||||
shell(before_test_prepared, env=env)
|
||||
shell(before_test_prepared, env=test_env)
|
||||
|
||||
log.step("Setting up test harness...")
|
||||
# Clone the testbed project into the build directory
|
||||
@@ -552,7 +556,7 @@ def build(options: Options, tmp_path: Path) -> None:
|
||||
target_install_path / "testbed",
|
||||
"clone",
|
||||
testbed_path,
|
||||
env=build_env,
|
||||
env=test_env,
|
||||
)
|
||||
|
||||
if not build_options.test_sources:
|
||||
@@ -574,7 +578,7 @@ def build(options: Options, tmp_path: Path) -> None:
|
||||
# the test requirements. Use the --platform tag to force
|
||||
# the installation of iOS wheels; this requires the use of
|
||||
# --only-binary=:all:
|
||||
ios_version = build_env["IPHONEOS_DEPLOYMENT_TARGET"]
|
||||
ios_version = test_env["IPHONEOS_DEPLOYMENT_TARGET"]
|
||||
platform_tag = f"ios_{ios_version.replace('.', '_')}_{config.arch}_{config.sdk}"
|
||||
|
||||
call(
|
||||
@@ -589,7 +593,7 @@ def build(options: Options, tmp_path: Path) -> None:
|
||||
testbed_path / "iOSTestbed" / "app_packages",
|
||||
f"{test_wheel}{build_options.test_extras}",
|
||||
*build_options.test_requires,
|
||||
env=build_env,
|
||||
env=test_env,
|
||||
)
|
||||
|
||||
log.step("Running test suite...")
|
||||
@@ -638,7 +642,7 @@ def build(options: Options, tmp_path: Path) -> None:
|
||||
*(["--verbose"] if build_options.build_verbosity > 0 else []),
|
||||
"--",
|
||||
*test_command_parts,
|
||||
env=build_env,
|
||||
env=test_env,
|
||||
)
|
||||
failed = False
|
||||
except subprocess.CalledProcessError:
|
||||
|
||||
@@ -361,6 +361,10 @@ def build_in_container(
|
||||
virtualenv_env = env.copy()
|
||||
virtualenv_env["PATH"] = f"{venv_dir / 'bin'}:{virtualenv_env['PATH']}"
|
||||
virtualenv_env["VIRTUAL_ENV"] = str(venv_dir)
|
||||
virtualenv_env["PYTHONSAFEPATH"] = "1"
|
||||
virtualenv_env = build_options.test_environment.as_dictionary(
|
||||
prev_environment=virtualenv_env
|
||||
)
|
||||
|
||||
if build_options.before_test:
|
||||
before_test_prepared = prepare_command(
|
||||
|
||||
@@ -648,6 +648,13 @@ def build(options: Options, tmp_path: Path) -> None:
|
||||
|
||||
virtualenv_env["MACOSX_DEPLOYMENT_TARGET"] = get_test_macosx_deployment_target()
|
||||
|
||||
# see https://github.com/pypa/cibuildwheel/issues/2358 for discussion
|
||||
virtualenv_env["PYTHONSAFEPATH"] = "1"
|
||||
|
||||
virtualenv_env = build_options.test_environment.as_dictionary(
|
||||
prev_environment=virtualenv_env
|
||||
)
|
||||
|
||||
# check that we are using the Python from the virtual environment
|
||||
call_with_arch("which", "python", env=virtualenv_env)
|
||||
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
import functools
|
||||
import json
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
import tomllib
|
||||
import typing
|
||||
from collections.abc import Set
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from tempfile import TemporaryDirectory
|
||||
from typing import Final
|
||||
from typing import Final, TypedDict
|
||||
|
||||
from filelock import FileLock
|
||||
|
||||
@@ -28,8 +30,12 @@ from ..util.file import (
|
||||
extract_zip,
|
||||
move_file,
|
||||
)
|
||||
from ..util.helpers import prepare_command
|
||||
from ..util.helpers import prepare_command, unwrap, unwrap_preserving_paragraphs
|
||||
from ..util.packaging import combine_constraints, find_compatible_wheel, get_pip_version
|
||||
from ..util.python_build_standalone import (
|
||||
PythonBuildStandaloneError,
|
||||
create_python_build_standalone_environment,
|
||||
)
|
||||
from ..venv import constraint_flags, virtualenv
|
||||
|
||||
IS_WIN: Final[bool] = sys.platform.startswith("win")
|
||||
@@ -39,12 +45,23 @@ IS_WIN: Final[bool] = sys.platform.startswith("win")
|
||||
class PythonConfiguration:
|
||||
version: str
|
||||
identifier: str
|
||||
pyodide_version: str
|
||||
pyodide_build_version: str
|
||||
emscripten_version: str
|
||||
default_pyodide_version: str
|
||||
node_version: str
|
||||
|
||||
|
||||
class PyodideXBuildEnvInfoVersionRange(TypedDict):
|
||||
min: str | None
|
||||
max: str | None
|
||||
|
||||
|
||||
class PyodideXBuildEnvInfo(TypedDict):
|
||||
version: str
|
||||
python: str
|
||||
emscripten: str
|
||||
pyodide_build: PyodideXBuildEnvInfoVersionRange
|
||||
compatible: bool
|
||||
|
||||
|
||||
@functools.cache
|
||||
def ensure_node(major_version: str) -> Path:
|
||||
with resources.NODEJS.open("rb") as f:
|
||||
@@ -77,8 +94,6 @@ def ensure_node(major_version: str) -> Path:
|
||||
|
||||
|
||||
def install_emscripten(tmp: Path, version: str) -> Path:
|
||||
# We don't need to match the emsdk version to the version we install, but
|
||||
# we do for stability
|
||||
url = f"https://github.com/emscripten-core/emsdk/archive/refs/tags/{version}.zip"
|
||||
installation_path = CIBW_CACHE_PATH / f"emsdk-{version}"
|
||||
emsdk_path = installation_path / f"emsdk-{version}/emsdk"
|
||||
@@ -96,16 +111,82 @@ def install_emscripten(tmp: Path, version: str) -> Path:
|
||||
return emcc_path
|
||||
|
||||
|
||||
def get_all_xbuildenv_version_info(env: dict[str, str]) -> list[PyodideXBuildEnvInfo]:
|
||||
xbuildenvs_info_str = call(
|
||||
"pyodide",
|
||||
"xbuildenv",
|
||||
"search",
|
||||
"--json",
|
||||
"--all",
|
||||
env=env,
|
||||
cwd=CIBW_CACHE_PATH,
|
||||
capture_stdout=True,
|
||||
).strip()
|
||||
|
||||
xbuildenvs_info = json.loads(xbuildenvs_info_str)
|
||||
|
||||
if "environments" not in xbuildenvs_info:
|
||||
msg = f"Invalid xbuildenvs info, got {xbuildenvs_info}"
|
||||
raise ValueError(msg)
|
||||
|
||||
return typing.cast(list[PyodideXBuildEnvInfo], xbuildenvs_info["environments"])
|
||||
|
||||
|
||||
def get_xbuildenv_version_info(
|
||||
env: dict[str, str], version: str, pyodide_build_version: str
|
||||
) -> PyodideXBuildEnvInfo:
|
||||
xbuildenvs_info = get_all_xbuildenv_version_info(env)
|
||||
for xbuildenv_info in xbuildenvs_info:
|
||||
if xbuildenv_info["version"] == version:
|
||||
return xbuildenv_info
|
||||
|
||||
msg = unwrap(f"""
|
||||
Could not find Pyodide cross-build environment version {version} in the available
|
||||
versions as reported by pyodide-build v{pyodide_build_version}.
|
||||
Available pyodide xbuildenv versions are:
|
||||
{", ".join(e["version"] for e in xbuildenvs_info if e["compatible"])}
|
||||
""")
|
||||
raise errors.FatalError(msg)
|
||||
|
||||
|
||||
# The default pyodide xbuildenv version that's specified in
|
||||
# build-platforms.toml is compatible with the pyodide-build version that's
|
||||
# pinned in the bundled constraints file. But if the user changes
|
||||
# pyodide-version and/or dependency-constraints in the cibuildwheel config, we
|
||||
# need to check if the xbuildenv version is compatible with the pyodide-build
|
||||
# version.
|
||||
def validate_pyodide_build_version(
|
||||
xbuildenv_info: PyodideXBuildEnvInfo, pyodide_build_version: str
|
||||
) -> None:
|
||||
"""
|
||||
Validate the Pyodide version is compatible with the installed
|
||||
pyodide-build version.
|
||||
"""
|
||||
|
||||
pyodide_version = xbuildenv_info["version"]
|
||||
|
||||
if not xbuildenv_info["compatible"]:
|
||||
msg = unwrap_preserving_paragraphs(f"""
|
||||
The Pyodide xbuildenv version {pyodide_version} is not compatible
|
||||
with the pyodide-build version {pyodide_build_version}. Please use
|
||||
the 'pyodide xbuildenv search --all' command to find a compatible
|
||||
version.
|
||||
|
||||
Set the pyodide-build version using the `dependency-constraints`
|
||||
option, or set the Pyodide xbuildenv version using the
|
||||
`pyodide-version` option.
|
||||
""")
|
||||
raise errors.FatalError(msg)
|
||||
|
||||
|
||||
def install_xbuildenv(env: dict[str, str], pyodide_build_version: str, pyodide_version: str) -> str:
|
||||
"""Install a particular Pyodide xbuildenv version and set a path to the Pyodide root."""
|
||||
# Since pyodide-build was unvendored from Pyodide v0.27.0, the versions of pyodide-build are
|
||||
# not guaranteed to match the versions of Pyodide or be in sync with them. Hence, we shall
|
||||
# specify the pyodide-build version in the root path, which will set up the xbuildenv for
|
||||
# the requested Pyodide version.
|
||||
pyodide_root = (
|
||||
CIBW_CACHE_PATH
|
||||
/ f".pyodide-xbuildenv-{pyodide_build_version}/{pyodide_version}/xbuildenv/pyodide-root"
|
||||
)
|
||||
# Since pyodide-build was unvendored from Pyodide v0.27.0, the versions of
|
||||
# pyodide-build are uncoupled from the versions of Pyodide. So, we specify
|
||||
# both the pyodide-build version and the Pyodide version in the temp path.
|
||||
xbuildenv_cache_path = CIBW_CACHE_PATH / f"pyodide-build-{pyodide_build_version}"
|
||||
pyodide_root = xbuildenv_cache_path / pyodide_version / "xbuildenv" / "pyodide-root"
|
||||
|
||||
with FileLock(CIBW_CACHE_PATH / "xbuildenv.lock"):
|
||||
if pyodide_root.exists():
|
||||
return str(pyodide_root)
|
||||
@@ -114,31 +195,36 @@ def install_xbuildenv(env: dict[str, str], pyodide_build_version: str, pyodide_v
|
||||
# PYODIDE_ROOT so copy it first.
|
||||
env = dict(env)
|
||||
env.pop("PYODIDE_ROOT", None)
|
||||
|
||||
# Install the xbuildenv
|
||||
call(
|
||||
"pyodide",
|
||||
"xbuildenv",
|
||||
"install",
|
||||
"--path",
|
||||
str(xbuildenv_cache_path),
|
||||
pyodide_version,
|
||||
env=env,
|
||||
cwd=CIBW_CACHE_PATH,
|
||||
)
|
||||
assert pyodide_root.exists()
|
||||
|
||||
return str(pyodide_root)
|
||||
|
||||
|
||||
def get_base_python(identifier: str) -> Path:
|
||||
implementation_id = identifier.split("-")[0]
|
||||
majorminor = implementation_id[len("cp") :]
|
||||
version_info = (int(majorminor[0]), int(majorminor[1:]))
|
||||
if version_info == sys.version_info[:2]:
|
||||
return Path(sys.executable)
|
||||
|
||||
major_minor = ".".join(str(v) for v in version_info)
|
||||
python_name = f"python{major_minor}"
|
||||
which_python = shutil.which(python_name)
|
||||
if which_python is None:
|
||||
msg = f"CPython {major_minor} is not installed."
|
||||
raise errors.FatalError(msg)
|
||||
return Path(which_python)
|
||||
def get_base_python(tmp: Path, python_configuration: PythonConfiguration) -> Path:
|
||||
try:
|
||||
return create_python_build_standalone_environment(
|
||||
python_version=python_configuration.version,
|
||||
temp_dir=tmp,
|
||||
cache_dir=CIBW_CACHE_PATH,
|
||||
)
|
||||
except PythonBuildStandaloneError as e:
|
||||
msg = unwrap(f"""
|
||||
Failed to create a Python build environment:
|
||||
{e}
|
||||
""")
|
||||
raise errors.FatalError(msg) from e
|
||||
|
||||
|
||||
def setup_python(
|
||||
@@ -146,10 +232,13 @@ def setup_python(
|
||||
python_configuration: PythonConfiguration,
|
||||
constraints_path: Path | None,
|
||||
environment: ParsedEnvironment,
|
||||
user_pyodide_version: str | None,
|
||||
) -> dict[str, str]:
|
||||
base_python = get_base_python(python_configuration.identifier)
|
||||
log.step("Installing a base python environment...")
|
||||
base_python = get_base_python(tmp / "base", python_configuration)
|
||||
|
||||
log.step("Setting up build environment...")
|
||||
pyodide_version = user_pyodide_version or python_configuration.default_pyodide_version
|
||||
venv_path = tmp / "venv"
|
||||
env = virtualenv(python_configuration.version, base_python, venv_path, None, use_uv=False)
|
||||
venv_bin_path = venv_path / "bin"
|
||||
@@ -201,15 +290,28 @@ def setup_python(
|
||||
env=env,
|
||||
)
|
||||
|
||||
log.step(f"Installing Emscripten version: {python_configuration.emscripten_version} ...")
|
||||
emcc_path = install_emscripten(tmp, python_configuration.emscripten_version)
|
||||
pyodide_build_version = call(
|
||||
"python",
|
||||
"-c",
|
||||
"from importlib.metadata import version; print(version('pyodide-build'))",
|
||||
env=env,
|
||||
capture_stdout=True,
|
||||
).strip()
|
||||
|
||||
xbuildenv_info = get_xbuildenv_version_info(env, pyodide_version, pyodide_build_version)
|
||||
validate_pyodide_build_version(
|
||||
xbuildenv_info=xbuildenv_info,
|
||||
pyodide_build_version=pyodide_build_version,
|
||||
)
|
||||
|
||||
emscripten_version = xbuildenv_info["emscripten"]
|
||||
log.step(f"Installing Emscripten version: {emscripten_version} ...")
|
||||
emcc_path = install_emscripten(tmp, emscripten_version)
|
||||
|
||||
env["PATH"] = os.pathsep.join([str(emcc_path.parent), env["PATH"]])
|
||||
|
||||
log.step(f"Installing Pyodide xbuildenv version: {python_configuration.pyodide_version} ...")
|
||||
env["PYODIDE_ROOT"] = install_xbuildenv(
|
||||
env, python_configuration.pyodide_build_version, python_configuration.pyodide_version
|
||||
)
|
||||
log.step(f"Installing Pyodide xbuildenv version: {pyodide_version} ...")
|
||||
env["PYODIDE_ROOT"] = install_xbuildenv(env, pyodide_build_version, pyodide_version)
|
||||
|
||||
return env
|
||||
|
||||
@@ -259,6 +361,7 @@ def build(options: Options, tmp_path: Path) -> None:
|
||||
log.build_start(config.identifier)
|
||||
|
||||
identifier_tmp_dir = tmp_path / config.identifier
|
||||
|
||||
built_wheel_dir = identifier_tmp_dir / "built_wheel"
|
||||
repaired_wheel_dir = identifier_tmp_dir / "repaired_wheel"
|
||||
identifier_tmp_dir.mkdir()
|
||||
@@ -270,10 +373,11 @@ def build(options: Options, tmp_path: Path) -> None:
|
||||
)
|
||||
|
||||
env = setup_python(
|
||||
identifier_tmp_dir / "build",
|
||||
config,
|
||||
constraints_path,
|
||||
build_options.environment,
|
||||
tmp=identifier_tmp_dir / "build",
|
||||
python_configuration=config,
|
||||
constraints_path=constraints_path,
|
||||
environment=build_options.environment,
|
||||
user_pyodide_version=build_options.pyodide_version,
|
||||
)
|
||||
pip_version = get_pip_version(env)
|
||||
# The Pyodide command line runner mounts all directories in the host
|
||||
@@ -380,6 +484,12 @@ def build(options: Options, tmp_path: Path) -> None:
|
||||
)
|
||||
virtualenv_env["VIRTUAL_ENV"] = str(venv_dir)
|
||||
|
||||
virtualenv_env["PYTHONSAFEPATH"] = "1"
|
||||
|
||||
virtualenv_env = build_options.test_environment.as_dictionary(
|
||||
prev_environment=virtualenv_env
|
||||
)
|
||||
|
||||
# check that we are using the Python from the virtual environment
|
||||
call("which", "python", env=virtualenv_env)
|
||||
|
||||
|
||||
@@ -558,6 +558,13 @@ def build(options: Options, tmp_path: Path) -> None:
|
||||
pip_version=pip_version,
|
||||
)
|
||||
|
||||
# see https://github.com/pypa/cibuildwheel/issues/2358 for discussion
|
||||
virtualenv_env["PYTHONSAFEPATH"] = "1"
|
||||
|
||||
virtualenv_env = build_options.test_environment.as_dictionary(
|
||||
prev_environment=virtualenv_env
|
||||
)
|
||||
|
||||
# check that we are using the Python from the virtual environment
|
||||
call("where", "python", env=virtualenv_env)
|
||||
|
||||
|
||||
@@ -220,7 +220,7 @@ python_configurations = [
|
||||
|
||||
[pyodide]
|
||||
python_configurations = [
|
||||
{ identifier = "cp312-pyodide_wasm32", version = "3.12", pyodide_version = "0.27.0", pyodide_build_version = "0.29.2", emscripten_version = "3.1.58", node_version = "v20" },
|
||||
{ identifier = "cp312-pyodide_wasm32", version = "3.12", default_pyodide_version = "0.27.6", node_version = "v22" },
|
||||
]
|
||||
|
||||
[ios]
|
||||
|
||||
@@ -424,6 +424,11 @@
|
||||
],
|
||||
"title": "CIBW_XBUILD_TOOLS"
|
||||
},
|
||||
"pyodide-version": {
|
||||
"type": "string",
|
||||
"description": "Specify the version of Pyodide to use",
|
||||
"title": "CIBW_PYODIDE_VERSION"
|
||||
},
|
||||
"repair-wheel-command": {
|
||||
"description": "Execute a shell command to repair each built wheel.",
|
||||
"oneOf": [
|
||||
@@ -544,6 +549,24 @@
|
||||
],
|
||||
"title": "CIBW_TEST_SKIP"
|
||||
},
|
||||
"test-environment": {
|
||||
"description": "Set environment variables for the test environment",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {
|
||||
".+": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"title": "CIBW_TEST_ENVIRONMENT"
|
||||
},
|
||||
"overrides": {
|
||||
"type": "array",
|
||||
"description": "An overrides array",
|
||||
@@ -610,6 +633,9 @@
|
||||
},
|
||||
"test-requires": {
|
||||
"$ref": "#/$defs/inherit"
|
||||
},
|
||||
"test-environment": {
|
||||
"$ref": "#/$defs/inherit"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -697,6 +723,9 @@
|
||||
"xbuild-tools": {
|
||||
"$ref": "#/properties/xbuild-tools"
|
||||
},
|
||||
"pyodide-version": {
|
||||
"$ref": "#/properties/pyodide-version"
|
||||
},
|
||||
"repair-wheel-command": {
|
||||
"$ref": "#/properties/repair-wheel-command"
|
||||
},
|
||||
@@ -714,6 +743,9 @@
|
||||
},
|
||||
"test-requires": {
|
||||
"$ref": "#/properties/test-requires"
|
||||
},
|
||||
"test-environment": {
|
||||
"$ref": "#/properties/test-environment"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -806,6 +838,9 @@
|
||||
"xbuild-tools": {
|
||||
"$ref": "#/properties/xbuild-tools"
|
||||
},
|
||||
"pyodide-version": {
|
||||
"$ref": "#/properties/pyodide-version"
|
||||
},
|
||||
"repair-wheel-command": {
|
||||
"description": "Execute a shell command to repair each built wheel.",
|
||||
"oneOf": [
|
||||
@@ -836,6 +871,9 @@
|
||||
},
|
||||
"test-requires": {
|
||||
"$ref": "#/properties/test-requires"
|
||||
},
|
||||
"test-environment": {
|
||||
"$ref": "#/properties/test-environment"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -873,6 +911,9 @@
|
||||
"xbuild-tools": {
|
||||
"$ref": "#/properties/xbuild-tools"
|
||||
},
|
||||
"pyodide-version": {
|
||||
"$ref": "#/properties/pyodide-version"
|
||||
},
|
||||
"repair-wheel-command": {
|
||||
"$ref": "#/properties/repair-wheel-command"
|
||||
},
|
||||
@@ -890,6 +931,9 @@
|
||||
},
|
||||
"test-requires": {
|
||||
"$ref": "#/properties/test-requires"
|
||||
},
|
||||
"test-environment": {
|
||||
"$ref": "#/properties/test-environment"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -927,6 +971,9 @@
|
||||
"xbuild-tools": {
|
||||
"$ref": "#/properties/xbuild-tools"
|
||||
},
|
||||
"pyodide-version": {
|
||||
"$ref": "#/properties/pyodide-version"
|
||||
},
|
||||
"repair-wheel-command": {
|
||||
"description": "Execute a shell command to repair each built wheel.",
|
||||
"oneOf": [
|
||||
@@ -957,6 +1004,9 @@
|
||||
},
|
||||
"test-requires": {
|
||||
"$ref": "#/properties/test-requires"
|
||||
},
|
||||
"test-environment": {
|
||||
"$ref": "#/properties/test-environment"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -994,6 +1044,9 @@
|
||||
"xbuild-tools": {
|
||||
"$ref": "#/properties/xbuild-tools"
|
||||
},
|
||||
"pyodide-version": {
|
||||
"$ref": "#/properties/pyodide-version"
|
||||
},
|
||||
"repair-wheel-command": {
|
||||
"$ref": "#/properties/repair-wheel-command"
|
||||
},
|
||||
@@ -1011,6 +1064,9 @@
|
||||
},
|
||||
"test-requires": {
|
||||
"$ref": "#/properties/test-requires"
|
||||
},
|
||||
"test-environment": {
|
||||
"$ref": "#/properties/test-environment"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1048,6 +1104,9 @@
|
||||
"xbuild-tools": {
|
||||
"$ref": "#/properties/xbuild-tools"
|
||||
},
|
||||
"pyodide-version": {
|
||||
"$ref": "#/properties/pyodide-version"
|
||||
},
|
||||
"repair-wheel-command": {
|
||||
"$ref": "#/properties/repair-wheel-command"
|
||||
},
|
||||
@@ -1065,6 +1124,9 @@
|
||||
},
|
||||
"test-requires": {
|
||||
"$ref": "#/properties/test-requires"
|
||||
},
|
||||
"test-environment": {
|
||||
"$ref": "#/properties/test-environment"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ annotated-types==0.7.0
|
||||
# via pydantic
|
||||
anyio==4.9.0
|
||||
# via httpx
|
||||
auditwheel-emscripten==0.0.16
|
||||
auditwheel-emscripten==0.1.0
|
||||
# via pyodide-build
|
||||
build==1.2.2.post1
|
||||
# via
|
||||
@@ -21,8 +21,6 @@ click==8.1.8
|
||||
# via
|
||||
# -r .nox/update_constraints/tmp/constraints-pyodide.in
|
||||
# typer
|
||||
cmake==4.0.2
|
||||
# via pyodide-build
|
||||
distlib==0.3.9
|
||||
# via virtualenv
|
||||
filelock==3.18.0
|
||||
@@ -53,7 +51,9 @@ packaging==25.0
|
||||
pip==25.1.1
|
||||
# via -r .nox/update_constraints/tmp/constraints-pyodide.in
|
||||
platformdirs==4.3.8
|
||||
# via virtualenv
|
||||
# via
|
||||
# pyodide-build
|
||||
# virtualenv
|
||||
pydantic==2.11.4
|
||||
# via
|
||||
# pyodide-build
|
||||
@@ -62,9 +62,9 @@ pydantic-core==2.33.2
|
||||
# via pydantic
|
||||
pygments==2.19.1
|
||||
# via rich
|
||||
pyodide-build==0.29.2
|
||||
pyodide-build==0.30.4
|
||||
# via -r .nox/update_constraints/tmp/constraints-pyodide.in
|
||||
pyodide-cli==0.2.4
|
||||
pyodide-cli==0.3.0
|
||||
# via
|
||||
# auditwheel-emscripten
|
||||
# pyodide-build
|
||||
|
||||
@@ -24,9 +24,12 @@ test-sources = []
|
||||
test-requires = []
|
||||
test-extras = []
|
||||
test-groups = []
|
||||
test-environment = {}
|
||||
|
||||
container-engine = "docker"
|
||||
|
||||
pyodide-version = ""
|
||||
|
||||
manylinux-x86_64-image = "manylinux_2_28"
|
||||
manylinux-i686-image = "manylinux2014"
|
||||
manylinux-aarch64-image = "manylinux_2_28"
|
||||
|
||||
@@ -0,0 +1,425 @@
|
||||
{
|
||||
"releases": [
|
||||
{
|
||||
"tag": "20250409",
|
||||
"assets": [
|
||||
{
|
||||
"name": "cpython-3.10.17+20250409-aarch64-apple-darwin-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.10.17%2B20250409-aarch64-apple-darwin-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.10.17+20250409-aarch64-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.10.17%2B20250409-aarch64-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.10.17+20250409-armv7-unknown-linux-gnueabi-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.10.17%2B20250409-armv7-unknown-linux-gnueabi-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.10.17+20250409-armv7-unknown-linux-gnueabihf-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.10.17%2B20250409-armv7-unknown-linux-gnueabihf-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.10.17+20250409-i686-pc-windows-msvc-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.10.17%2B20250409-i686-pc-windows-msvc-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.10.17+20250409-ppc64le-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.10.17%2B20250409-ppc64le-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.10.17+20250409-riscv64-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.10.17%2B20250409-riscv64-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.10.17+20250409-s390x-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.10.17%2B20250409-s390x-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.10.17+20250409-x86_64-apple-darwin-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.10.17%2B20250409-x86_64-apple-darwin-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.10.17+20250409-x86_64-pc-windows-msvc-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.10.17%2B20250409-x86_64-pc-windows-msvc-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.10.17+20250409-x86_64-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.10.17%2B20250409-x86_64-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.10.17+20250409-x86_64-unknown-linux-musl-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.10.17%2B20250409-x86_64-unknown-linux-musl-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.10.17+20250409-x86_64_v2-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.10.17%2B20250409-x86_64_v2-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.10.17+20250409-x86_64_v2-unknown-linux-musl-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.10.17%2B20250409-x86_64_v2-unknown-linux-musl-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.10.17+20250409-x86_64_v3-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.10.17%2B20250409-x86_64_v3-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.10.17+20250409-x86_64_v3-unknown-linux-musl-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.10.17%2B20250409-x86_64_v3-unknown-linux-musl-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.10.17+20250409-x86_64_v4-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.10.17%2B20250409-x86_64_v4-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.10.17+20250409-x86_64_v4-unknown-linux-musl-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.10.17%2B20250409-x86_64_v4-unknown-linux-musl-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.11.12+20250409-aarch64-apple-darwin-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.11.12%2B20250409-aarch64-apple-darwin-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.11.12+20250409-aarch64-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.11.12%2B20250409-aarch64-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.11.12+20250409-armv7-unknown-linux-gnueabi-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.11.12%2B20250409-armv7-unknown-linux-gnueabi-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.11.12+20250409-armv7-unknown-linux-gnueabihf-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.11.12%2B20250409-armv7-unknown-linux-gnueabihf-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.11.12+20250409-i686-pc-windows-msvc-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.11.12%2B20250409-i686-pc-windows-msvc-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.11.12+20250409-ppc64le-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.11.12%2B20250409-ppc64le-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.11.12+20250409-riscv64-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.11.12%2B20250409-riscv64-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.11.12+20250409-s390x-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.11.12%2B20250409-s390x-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.11.12+20250409-x86_64-apple-darwin-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.11.12%2B20250409-x86_64-apple-darwin-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.11.12+20250409-x86_64-pc-windows-msvc-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.11.12%2B20250409-x86_64-pc-windows-msvc-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.11.12+20250409-x86_64-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.11.12%2B20250409-x86_64-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.11.12+20250409-x86_64-unknown-linux-musl-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.11.12%2B20250409-x86_64-unknown-linux-musl-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.11.12+20250409-x86_64_v2-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.11.12%2B20250409-x86_64_v2-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.11.12+20250409-x86_64_v2-unknown-linux-musl-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.11.12%2B20250409-x86_64_v2-unknown-linux-musl-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.11.12+20250409-x86_64_v3-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.11.12%2B20250409-x86_64_v3-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.11.12+20250409-x86_64_v3-unknown-linux-musl-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.11.12%2B20250409-x86_64_v3-unknown-linux-musl-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.11.12+20250409-x86_64_v4-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.11.12%2B20250409-x86_64_v4-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.11.12+20250409-x86_64_v4-unknown-linux-musl-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.11.12%2B20250409-x86_64_v4-unknown-linux-musl-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.12.10+20250409-aarch64-apple-darwin-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.12.10%2B20250409-aarch64-apple-darwin-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.12.10+20250409-aarch64-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.12.10%2B20250409-aarch64-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.12.10+20250409-armv7-unknown-linux-gnueabi-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.12.10%2B20250409-armv7-unknown-linux-gnueabi-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.12.10+20250409-armv7-unknown-linux-gnueabihf-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.12.10%2B20250409-armv7-unknown-linux-gnueabihf-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.12.10+20250409-i686-pc-windows-msvc-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.12.10%2B20250409-i686-pc-windows-msvc-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.12.10+20250409-ppc64le-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.12.10%2B20250409-ppc64le-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.12.10+20250409-riscv64-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.12.10%2B20250409-riscv64-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.12.10+20250409-s390x-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.12.10%2B20250409-s390x-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.12.10+20250409-x86_64-apple-darwin-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.12.10%2B20250409-x86_64-apple-darwin-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.12.10+20250409-x86_64-pc-windows-msvc-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.12.10%2B20250409-x86_64-pc-windows-msvc-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.12.10+20250409-x86_64-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.12.10%2B20250409-x86_64-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.12.10+20250409-x86_64-unknown-linux-musl-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.12.10%2B20250409-x86_64-unknown-linux-musl-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.12.10+20250409-x86_64_v2-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.12.10%2B20250409-x86_64_v2-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.12.10+20250409-x86_64_v2-unknown-linux-musl-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.12.10%2B20250409-x86_64_v2-unknown-linux-musl-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.12.10+20250409-x86_64_v3-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.12.10%2B20250409-x86_64_v3-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.12.10+20250409-x86_64_v3-unknown-linux-musl-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.12.10%2B20250409-x86_64_v3-unknown-linux-musl-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.12.10+20250409-x86_64_v4-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.12.10%2B20250409-x86_64_v4-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.12.10+20250409-x86_64_v4-unknown-linux-musl-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.12.10%2B20250409-x86_64_v4-unknown-linux-musl-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.13.3+20250409-aarch64-apple-darwin-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.13.3%2B20250409-aarch64-apple-darwin-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.13.3+20250409-aarch64-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.13.3%2B20250409-aarch64-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.13.3+20250409-armv7-unknown-linux-gnueabi-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.13.3%2B20250409-armv7-unknown-linux-gnueabi-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.13.3+20250409-armv7-unknown-linux-gnueabihf-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.13.3%2B20250409-armv7-unknown-linux-gnueabihf-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.13.3+20250409-i686-pc-windows-msvc-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.13.3%2B20250409-i686-pc-windows-msvc-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.13.3+20250409-ppc64le-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.13.3%2B20250409-ppc64le-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.13.3+20250409-riscv64-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.13.3%2B20250409-riscv64-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.13.3+20250409-s390x-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.13.3%2B20250409-s390x-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.13.3+20250409-x86_64-apple-darwin-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.13.3%2B20250409-x86_64-apple-darwin-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.13.3+20250409-x86_64-pc-windows-msvc-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.13.3%2B20250409-x86_64-pc-windows-msvc-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.13.3+20250409-x86_64-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.13.3%2B20250409-x86_64-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.13.3+20250409-x86_64-unknown-linux-musl-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.13.3%2B20250409-x86_64-unknown-linux-musl-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.13.3+20250409-x86_64_v2-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.13.3%2B20250409-x86_64_v2-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.13.3+20250409-x86_64_v2-unknown-linux-musl-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.13.3%2B20250409-x86_64_v2-unknown-linux-musl-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.13.3+20250409-x86_64_v3-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.13.3%2B20250409-x86_64_v3-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.13.3+20250409-x86_64_v3-unknown-linux-musl-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.13.3%2B20250409-x86_64_v3-unknown-linux-musl-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.13.3+20250409-x86_64_v4-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.13.3%2B20250409-x86_64_v4-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.13.3+20250409-x86_64_v4-unknown-linux-musl-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.13.3%2B20250409-x86_64_v4-unknown-linux-musl-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.14.0a6+20250409-aarch64-apple-darwin-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.14.0a6%2B20250409-aarch64-apple-darwin-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.14.0a6+20250409-aarch64-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.14.0a6%2B20250409-aarch64-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.14.0a6+20250409-armv7-unknown-linux-gnueabi-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.14.0a6%2B20250409-armv7-unknown-linux-gnueabi-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.14.0a6+20250409-armv7-unknown-linux-gnueabihf-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.14.0a6%2B20250409-armv7-unknown-linux-gnueabihf-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.14.0a6+20250409-i686-pc-windows-msvc-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.14.0a6%2B20250409-i686-pc-windows-msvc-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.14.0a6+20250409-ppc64le-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.14.0a6%2B20250409-ppc64le-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.14.0a6+20250409-riscv64-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.14.0a6%2B20250409-riscv64-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.14.0a6+20250409-s390x-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.14.0a6%2B20250409-s390x-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.14.0a6+20250409-x86_64-apple-darwin-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.14.0a6%2B20250409-x86_64-apple-darwin-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.14.0a6+20250409-x86_64-pc-windows-msvc-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.14.0a6%2B20250409-x86_64-pc-windows-msvc-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.14.0a6+20250409-x86_64-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.14.0a6%2B20250409-x86_64-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.14.0a6+20250409-x86_64_v2-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.14.0a6%2B20250409-x86_64_v2-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.14.0a6+20250409-x86_64_v3-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.14.0a6%2B20250409-x86_64_v3-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.14.0a6+20250409-x86_64_v4-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.14.0a6%2B20250409-x86_64_v4-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.9.22+20250409-aarch64-apple-darwin-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.9.22%2B20250409-aarch64-apple-darwin-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.9.22+20250409-aarch64-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.9.22%2B20250409-aarch64-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.9.22+20250409-armv7-unknown-linux-gnueabi-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.9.22%2B20250409-armv7-unknown-linux-gnueabi-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.9.22+20250409-armv7-unknown-linux-gnueabihf-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.9.22%2B20250409-armv7-unknown-linux-gnueabihf-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.9.22+20250409-i686-pc-windows-msvc-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.9.22%2B20250409-i686-pc-windows-msvc-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.9.22+20250409-ppc64le-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.9.22%2B20250409-ppc64le-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.9.22+20250409-riscv64-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.9.22%2B20250409-riscv64-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.9.22+20250409-s390x-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.9.22%2B20250409-s390x-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.9.22+20250409-x86_64-apple-darwin-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.9.22%2B20250409-x86_64-apple-darwin-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.9.22+20250409-x86_64-pc-windows-msvc-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.9.22%2B20250409-x86_64-pc-windows-msvc-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.9.22+20250409-x86_64-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.9.22%2B20250409-x86_64-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.9.22+20250409-x86_64-unknown-linux-musl-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.9.22%2B20250409-x86_64-unknown-linux-musl-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.9.22+20250409-x86_64_v2-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.9.22%2B20250409-x86_64_v2-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.9.22+20250409-x86_64_v2-unknown-linux-musl-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.9.22%2B20250409-x86_64_v2-unknown-linux-musl-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.9.22+20250409-x86_64_v3-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.9.22%2B20250409-x86_64_v3-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.9.22+20250409-x86_64_v3-unknown-linux-musl-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.9.22%2B20250409-x86_64_v3-unknown-linux-musl-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.9.22+20250409-x86_64_v4-unknown-linux-gnu-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.9.22%2B20250409-x86_64_v4-unknown-linux-gnu-install_only.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "cpython-3.9.22+20250409-x86_64_v4-unknown-linux-musl-install_only.tar.gz",
|
||||
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20250409/cpython-3.9.22%2B20250409-x86_64_v4-unknown-linux-musl-install_only.tar.gz"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -165,6 +165,9 @@ def find_compatible_wheel(wheels: Sequence[T], identifier: str) -> T | None:
|
||||
continue
|
||||
if not tag.platform.endswith(f"_{arch}"):
|
||||
continue
|
||||
elif platform.startswith("pyodide"):
|
||||
# each Pyodide version has its own platform tag
|
||||
continue
|
||||
else:
|
||||
# Windows should exactly match
|
||||
if tag.platform != platform:
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
import fnmatch
|
||||
import functools
|
||||
import json
|
||||
import platform
|
||||
import typing
|
||||
from pathlib import Path
|
||||
|
||||
from filelock import FileLock
|
||||
|
||||
from cibuildwheel.util.file import download, extract_tar
|
||||
from cibuildwheel.util.resources import PYTHON_BUILD_STANDALONE_RELEASES
|
||||
|
||||
|
||||
class PythonBuildStandaloneAsset(typing.TypedDict):
|
||||
name: str
|
||||
url: str
|
||||
|
||||
|
||||
class PythonBuildStandaloneRelease(typing.TypedDict):
|
||||
tag: str
|
||||
assets: list[PythonBuildStandaloneAsset]
|
||||
|
||||
|
||||
class PythonBuildStandaloneReleaseData(typing.TypedDict):
|
||||
releases: list[PythonBuildStandaloneRelease]
|
||||
|
||||
|
||||
@functools.cache
|
||||
def get_python_build_standalone_release_data() -> PythonBuildStandaloneReleaseData:
|
||||
with open(PYTHON_BUILD_STANDALONE_RELEASES, "rb") as f:
|
||||
return typing.cast(PythonBuildStandaloneReleaseData, json.load(f))
|
||||
|
||||
|
||||
class PythonBuildStandaloneError(Exception):
|
||||
"""Errors related to python-build-standalone."""
|
||||
|
||||
|
||||
def _get_platform_identifiers() -> tuple[str, str, str | None]:
|
||||
"""
|
||||
Detects the current platform and returns architecture, platform, and libc
|
||||
identifiers.
|
||||
"""
|
||||
system = platform.system()
|
||||
machine = platform.machine()
|
||||
machine_lower = machine.lower()
|
||||
|
||||
arch_identifier: str
|
||||
platform_identifier: str
|
||||
libc_identifier: str | None = None
|
||||
|
||||
# Map Architecture
|
||||
if machine_lower in ["x86_64", "amd64"]:
|
||||
arch_identifier = "x86_64"
|
||||
elif machine_lower in ["aarch64", "arm64"]:
|
||||
arch_identifier = "aarch64"
|
||||
else:
|
||||
msg = f"Unsupported architecture: {system} {machine}. Cannot download appropriate Python build."
|
||||
raise PythonBuildStandaloneError(msg)
|
||||
|
||||
# Map OS + Libc
|
||||
if system == "Linux":
|
||||
platform_identifier = "unknown-linux"
|
||||
libc_identifier = "musl" if "musl" in (platform.libc_ver() or ("", "")) else "gnu"
|
||||
elif system == "Darwin":
|
||||
platform_identifier = "apple-darwin"
|
||||
elif system == "Windows":
|
||||
platform_identifier = "pc-windows-msvc"
|
||||
else:
|
||||
msg = f"Unsupported operating system: {system}. Cannot download appropriate Python build."
|
||||
raise PythonBuildStandaloneError(msg)
|
||||
|
||||
print(
|
||||
f"Detected platform: arch='{arch_identifier}', platform='{platform_identifier}', libc='{libc_identifier}'"
|
||||
)
|
||||
return arch_identifier, platform_identifier, libc_identifier
|
||||
|
||||
|
||||
def _get_pbs_asset(
|
||||
*,
|
||||
python_version: str,
|
||||
arch_identifier: str,
|
||||
platform_identifier: str,
|
||||
libc_identifier: str | None,
|
||||
) -> tuple[str, str, str]:
|
||||
"""Finds the asset, returning (tag, filename, url)."""
|
||||
release_data = get_python_build_standalone_release_data()
|
||||
|
||||
expected_suffix = f"{arch_identifier}-{platform_identifier}"
|
||||
if libc_identifier:
|
||||
expected_suffix += f"-{libc_identifier}"
|
||||
expected_suffix += "-install_only.tar.gz"
|
||||
|
||||
asset_pattern = f"cpython-{python_version}.*-{expected_suffix}"
|
||||
print(f"Looking for file with pattern {asset_pattern}")
|
||||
|
||||
for release in release_data["releases"]:
|
||||
for asset in release["assets"]:
|
||||
asset_name = asset["name"]
|
||||
if not fnmatch.fnmatch(asset_name, asset_pattern):
|
||||
continue
|
||||
|
||||
asset_url = asset["url"]
|
||||
return release["tag"], asset_url, asset_name
|
||||
|
||||
# If loop completes without finding a match
|
||||
msg = f"Could not find python-build-standalone release asset matching {asset_pattern!r}."
|
||||
raise PythonBuildStandaloneError(msg)
|
||||
|
||||
|
||||
def _download_or_get_from_cache(asset_url: str, asset_filename: str, cache_dir: Path) -> Path:
|
||||
with FileLock(cache_dir / (asset_filename + ".lock")):
|
||||
asset_cache_path = cache_dir / asset_filename
|
||||
if asset_cache_path.is_file():
|
||||
print(f"Using cached python_build_standalone: {asset_cache_path}")
|
||||
return asset_cache_path
|
||||
|
||||
print(f"Downloading python_build_standalone: {asset_url} to {asset_cache_path}")
|
||||
download(asset_url, asset_cache_path)
|
||||
return asset_cache_path
|
||||
|
||||
|
||||
def _find_python_executable(extracted_dir: Path) -> Path:
|
||||
"""Finds the python executable within the extracted directory structure."""
|
||||
# Structure is typically 'python/bin/python' or 'python/python.exe'
|
||||
base_install_dir = extracted_dir / "python"
|
||||
|
||||
if platform.system() == "Windows":
|
||||
executable_path = base_install_dir / "python.exe"
|
||||
else:
|
||||
executable_path = base_install_dir / "bin" / "python"
|
||||
|
||||
if not executable_path.is_file():
|
||||
msg = f"Could not locate python executable at expected path {executable_path} within {extracted_dir}."
|
||||
raise PythonBuildStandaloneError(msg)
|
||||
|
||||
print(f"Found python executable: {executable_path}")
|
||||
return executable_path.resolve() # Return absolute path
|
||||
|
||||
|
||||
def create_python_build_standalone_environment(
|
||||
python_version: str, temp_dir: Path, cache_dir: Path
|
||||
) -> Path:
|
||||
"""
|
||||
Returns a Python environment from python-build-standalone, downloading it
|
||||
if necessary using a cache, and expanding it into a fresh base path.
|
||||
|
||||
Args:
|
||||
python_version: The Python version string (e.g., "3.12").
|
||||
temp_dir: A directory where the Python environment will be created.
|
||||
cache_dir: A directory to store/retrieve downloaded archives.
|
||||
|
||||
Returns:
|
||||
The absolute path to the python executable within the created environment (in temp_dir).
|
||||
|
||||
Raises:
|
||||
PythonBuildStandaloneError: If the platform is unsupported, the build cannot be found,
|
||||
download/extraction fails, or configuration is invalid.
|
||||
"""
|
||||
|
||||
print(f"Creating python-build-standalone environment: version={python_version}")
|
||||
|
||||
arch_id, platform_id, libc_id = _get_platform_identifiers()
|
||||
|
||||
pbs_tag, asset_url, asset_filename = _get_pbs_asset(
|
||||
python_version=python_version,
|
||||
arch_identifier=arch_id,
|
||||
platform_identifier=platform_id,
|
||||
libc_identifier=libc_id,
|
||||
)
|
||||
|
||||
print(f"Using python-build-standalone release: {pbs_tag}")
|
||||
|
||||
archive_path = _download_or_get_from_cache(
|
||||
asset_url=asset_url, asset_filename=asset_filename, cache_dir=cache_dir
|
||||
)
|
||||
|
||||
python_base_dir = temp_dir / "pbs"
|
||||
assert not python_base_dir.exists()
|
||||
extract_tar(archive_path, python_base_dir)
|
||||
|
||||
return _find_python_executable(python_base_dir)
|
||||
@@ -16,6 +16,7 @@ BUILD_PLATFORMS: Final[Path] = PATH / "build-platforms.toml"
|
||||
CONSTRAINTS: Final[Path] = PATH / "constraints.txt"
|
||||
VIRTUALENV: Final[Path] = PATH / "virtualenv.toml"
|
||||
CIBUILDWHEEL_SCHEMA: Final[Path] = PATH / "cibuildwheel.schema.json"
|
||||
PYTHON_BUILD_STANDALONE_RELEASES: Final[Path] = PATH / "python-build-standalone-releases.json"
|
||||
|
||||
|
||||
# this value is cached because it's used a lot in unit tests
|
||||
|
||||
+18
-2
@@ -6,7 +6,19 @@ title: Changelog
|
||||
|
||||
### v3.0.0
|
||||
|
||||
Not yet released, but available for testing
|
||||
Not yet released, but available for testing.
|
||||
|
||||
Note - when using a beta version, be sure to check the [latest docs](https://cibuildwheel.pypa.io/en/latest/), rather than the stable version, which is still on v2.X.
|
||||
|
||||
Known issues:
|
||||
- ⚠️ The CWD for test-command has changed in v3.0, but that is still [being debated](https://github.com/pypa/cibuildwheel/issues/2406), it might change before the final release. Please provide feedback on the aforementioned issue if you do (or don't!) encounter issues with this.
|
||||
|
||||
#### v3.0.0b2
|
||||
|
||||
_25 May 2025_
|
||||
|
||||
- ✨ Adds the [`CIBW_TEST_ENVIRONMENT`](https://cibuildwheel.pypa.io/en/latest/options/#test-environment) option, which allows you to set environment variables for the test command. cibuildwheel now sets `PYTHONSAFEPATH=1` in test environments by default, to avoid picking up package imports from the local directory - we want to test the installed wheel, not the source tree! You can change that, or any other environment variable in the test environment using this option. (#2388)
|
||||
- ✨ Improves support for Pyodide builds and adds the [`CIBW_PYODIDE_VERSION`](https://cibuildwheel.pypa.io/en/latest/options/#pyodide-version) option, which allows you to specify the version of Pyodide to use for builds. (#2002)
|
||||
|
||||
#### v3.0.0b1
|
||||
|
||||
@@ -17,7 +29,11 @@ _19 May 2025_
|
||||
- ✨ Adds CPython 3.14 support, under the [`enable` option](https://cibuildwheel.pypa.io/en/latest/options/#enable) `cpython-prerelease`. This version of cibuildwheel uses 3.14.0b1.
|
||||
|
||||
_While CPython is in beta, the ABI can change, so your wheels might not be compatible with the final release. For this reason, we don't recommend distributing wheels until RC1, at which point 3.14 will be available in cibuildwheel without the flag._ (#2390)
|
||||
- ✨ Adds the [test-sources option](https://cibuildwheel.pypa.io/en/latest/options/#test-sources). \[discussion about the test cwd change and how to use to come!\]
|
||||
- ✨ Adds the [test-sources option](https://cibuildwheel.pypa.io/en/latest/options/#test-sources), and changes the working directory for tests.
|
||||
|
||||
- If this option is set, cibuildwheel will copy the files and folders specified in `test-sources` into a temporary directory, and run the tests from there. This is required for iOS builds, but also useful for other platforms, as it allows you to test the installed wheel without any chance of accidentally importing from the source tree.
|
||||
- If this option is not set, cibuildwheel will run the tests in the source tree. This is a change from the previous behavior, where cibuildwheel would run the tests from a temporary directory. We're still investigating what's best here, so if you encounter any issues with this, please let us know in [issue #2406](https://github.com/pypa/cibuildwheel/issues/2406).
|
||||
|
||||
- ✨ Added `dependency-versions` inline syntax (#2123)
|
||||
- 🛠 EOL manylinux options can no longer be specified by their shortname. Full OCI URL can still be used for these images, if you wish (#2316)
|
||||
- 🛠 Build environments no longer have setuptools and wheel preinstalled. (#2329)
|
||||
|
||||
+3
-3
@@ -60,7 +60,7 @@ There are two suggested methods for keeping cibuildwheel up to date that instead
|
||||
If you use GitHub Actions for builds, you can use cibuildwheel as an action:
|
||||
|
||||
```yaml
|
||||
uses: pypa/cibuildwheel@v3.0.0b1
|
||||
uses: pypa/cibuildwheel@v3.0.0b2
|
||||
```
|
||||
|
||||
This is a composite step that just runs cibuildwheel using pipx. You can set command-line options as `with:` parameters, and use `env:` as normal.
|
||||
@@ -82,7 +82,7 @@ The second option, and the only one that supports other CI systems, is using a `
|
||||
|
||||
```bash
|
||||
# requirements-cibw.txt
|
||||
cibuildwheel==3.0.0b1
|
||||
cibuildwheel==3.0.0b2
|
||||
```
|
||||
|
||||
Then your install step would have `python -m pip install -r requirements-cibw.txt` in it. Your `.github/dependabot.yml` file could look like this:
|
||||
@@ -247,7 +247,7 @@ Solutions to this vary, but the simplest is to use pipx:
|
||||
# most runners have pipx preinstalled, but in case you don't
|
||||
python3 -m pip install pipx
|
||||
|
||||
pipx run cibuildwheel==3.0.0b1 --output-dir wheelhouse
|
||||
pipx run cibuildwheel==3.0.0b2 --output-dir wheelhouse
|
||||
pipx run twine upload wheelhouse/*.whl
|
||||
```
|
||||
|
||||
|
||||
+91
-18
@@ -17,7 +17,9 @@ Default: `auto`
|
||||
- For `linux`, you need [Docker or Podman](#container-engine) running, on Linux, macOS, or Windows.
|
||||
- For `macos` and `windows`, you need to be running on the respective system, with a working compiler toolchain installed - Xcode Command Line tools for macOS, and MSVC for Windows.
|
||||
- For `ios` you need to be running on macOS, with Xcode and the iOS simulator installed.
|
||||
- For `pyodide` you need to be on an x86-64 linux runner and `python3.12` must be available in `PATH`.
|
||||
- For `pyodide`, you need a Linux or macOS machine.
|
||||
|
||||
Check the [platforms](platforms.md) page for more information on platform requirements.
|
||||
|
||||
This option can also be set using the [command-line option](#command-line) `--platform`. This option is not available in the `pyproject.toml` config.
|
||||
|
||||
@@ -49,20 +51,19 @@ When both options are specified, both conditions are applied and only builds wit
|
||||
When setting the options, you can use shell-style globbing syntax, as per [fnmatch](https://docs.python.org/3/library/fnmatch.html) with the addition of curly bracket syntax `{option1,option2}`, provided by [bracex](https://pypi.org/project/bracex/). All the build identifiers supported by cibuildwheel are shown below:
|
||||
|
||||
<div class="build-id-table-marker"></div>
|
||||
|
||||
| | macOS | Windows | Linux Intel | Linux Other | iOS |
|
||||
|---------------|------------------------------------------------------------------------|-----------------------------------------------------|-----------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------|
|
||||
| Python 3.8 | cp38-macosx_x86_64<br/>cp38-macosx_universal2<br/>cp38-macosx_arm64 | cp38-win_amd64<br/>cp38-win32 | cp38-manylinux_x86_64<br/>cp38-manylinux_i686<br/>cp38-musllinux_x86_64<br/>cp38-musllinux_i686 | cp38-manylinux_aarch64<br/>cp38-manylinux_ppc64le<br/>cp38-manylinux_s390x<br/>cp38-manylinux_armv7l<br/>cp38-manylinux_riscv64<br/>cp38-musllinux_aarch64<br/>cp38-musllinux_ppc64le<br/>cp38-musllinux_s390x<br/>cp38-musllinux_armv7l<br/>cp38-musllinux_riscv64 | |
|
||||
| Python 3.9 | cp39-macosx_x86_64<br/>cp39-macosx_universal2<br/>cp39-macosx_arm64 | cp39-win_amd64<br/>cp39-win32<br/>cp39-win_arm64 | cp39-manylinux_x86_64<br/>cp39-manylinux_i686<br/>cp39-musllinux_x86_64<br/>cp39-musllinux_i686 | cp39-manylinux_aarch64<br/>cp39-manylinux_ppc64le<br/>cp39-manylinux_s390x<br/>cp39-manylinux_armv7l<br/>cp39-manylinux_riscv64<br/>cp39-musllinux_aarch64<br/>cp39-musllinux_ppc64le<br/>cp39-musllinux_s390x<br/>cp39-musllinux_armv7l<br/>cp39-musllinux_riscv64 | |
|
||||
| Python 3.10 | cp310-macosx_x86_64<br/>cp310-macosx_universal2<br/>cp310-macosx_arm64 | cp310-win_amd64<br/>cp310-win32<br/>cp310-win_arm64 | cp310-manylinux_x86_64<br/>cp310-manylinux_i686<br/>cp310-musllinux_x86_64<br/>cp310-musllinux_i686 | cp310-manylinux_aarch64<br/>cp310-manylinux_ppc64le<br/>cp310-manylinux_s390x<br/>cp310-manylinux_armv7l<br/>cp310-manylinux_riscv64<br/>cp310-musllinux_aarch64<br/>cp310-musllinux_ppc64le<br/>cp310-musllinux_s390x<br/>cp310-musllinux_armv7l<br/>cp310-musllinux_riscv64 | |
|
||||
| Python 3.11 | cp311-macosx_x86_64<br/>cp311-macosx_universal2<br/>cp311-macosx_arm64 | cp311-win_amd64<br/>cp311-win32<br/>cp311-win_arm64 | cp311-manylinux_x86_64<br/>cp311-manylinux_i686<br/>cp311-musllinux_x86_64<br/>cp311-musllinux_i686 | cp311-manylinux_aarch64<br/>cp311-manylinux_ppc64le<br/>cp311-manylinux_s390x<br/>cp311-manylinux_armv7l<br/>cp311-manylinux_riscv64<br/>cp311-musllinux_aarch64<br/>cp311-musllinux_ppc64le<br/>cp311-musllinux_s390x<br/>cp311-musllinux_armv7l<br/>cp311-musllinux_riscv64 | |
|
||||
| Python 3.12 | cp312-macosx_x86_64<br/>cp312-macosx_universal2<br/>cp312-macosx_arm64 | cp312-win_amd64<br/>cp312-win32<br/>cp312-win_arm64 | cp312-manylinux_x86_64<br/>cp312-manylinux_i686<br/>cp312-musllinux_x86_64<br/>cp312-musllinux_i686 | cp312-manylinux_aarch64<br/>cp312-manylinux_ppc64le<br/>cp312-manylinux_s390x<br/>cp312-manylinux_armv7l<br/>cp312-manylinux_riscv64<br/>cp312-musllinux_aarch64<br/>cp312-musllinux_ppc64le<br/>cp312-musllinux_s390x<br/>cp312-musllinux_armv7l<br/>cp312-musllinux_riscv64 | |
|
||||
| Python 3.13 | cp313-macosx_x86_64<br/>cp313-macosx_universal2<br/>cp313-macosx_arm64 | cp313-win_amd64<br/>cp313-win32<br/>cp313-win_arm64 | cp313-manylinux_x86_64<br/>cp313-manylinux_i686<br/>cp313-musllinux_x86_64<br/>cp313-musllinux_i686 | cp313-manylinux_aarch64<br/>cp313-manylinux_ppc64le<br/>cp313-manylinux_s390x<br/>cp313-manylinux_armv7l<br/>cp313-manylinux_riscv64<br/>cp313-musllinux_aarch64<br/>cp313-musllinux_ppc64le<br/>cp313-musllinux_s390x<br/>cp313-musllinux_armv7l<br/>cp313-musllinux_riscv64 | cp313-ios_arm64_iphoneos<br/>cp313-ios_arm64_iphonesimulator<br/>cp313-ios_x86_64_iphonesimulator |
|
||||
| Python 3.14 | cp314-macosx_x86_64<br/>cp314-macosx_universal2<br/>cp314-macosx_arm64 | cp314-win_amd64<br/>cp314-win32<br/>cp314-win_arm64 | cp314-manylinux_x86_64<br/>cp314-manylinux_i686<br/>cp314-musllinux_x86_64<br/>cp314-musllinux_i686 | cp314-manylinux_aarch64<br/>cp314-manylinux_ppc64le<br/>cp314-manylinux_s390x<br/>cp314-manylinux_armv7l<br/>cp314-manylinux_riscv64<br/>cp314-musllinux_aarch64<br/>cp314-musllinux_ppc64le<br/>cp314-musllinux_s390x<br/>cp314-musllinux_armv7l<br/>cp314-musllinux_riscv64 | |
|
||||
| PyPy3.8 v7.3 | pp38-macosx_x86_64<br/>pp38-macosx_arm64 | pp38-win_amd64 | pp38-manylinux_x86_64<br/>pp38-manylinux_i686 | pp38-manylinux_aarch64 | |
|
||||
| PyPy3.9 v7.3 | pp39-macosx_x86_64<br/>pp39-macosx_arm64 | pp39-win_amd64 | pp39-manylinux_x86_64<br/>pp39-manylinux_i686 | pp39-manylinux_aarch64 | |
|
||||
| PyPy3.10 v7.3 | pp310-macosx_x86_64<br/>pp310-macosx_arm64 | pp310-win_amd64 | pp310-manylinux_x86_64<br/>pp310-manylinux_i686 | pp310-manylinux_aarch64 | |
|
||||
| PyPy3.11 v7.3 | pp311-macosx_x86_64<br/>pp311-macosx_arm64 | pp311-win_amd64 | pp311-manylinux_x86_64<br/>pp311-manylinux_i686 | pp311-manylinux_aarch64 | |
|
||||
| | macOS | Windows | Linux Intel | Linux Other | iOS | pyodide (WASM) |
|
||||
|---------------|------------------------------------------------------------------------|-----------------------------------------------------|-----------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------|----------------------|
|
||||
| Python 3.8 | cp38-macosx_x86_64<br/>cp38-macosx_universal2<br/>cp38-macosx_arm64 | cp38-win_amd64<br/>cp38-win32 | cp38-manylinux_x86_64<br/>cp38-manylinux_i686<br/>cp38-musllinux_x86_64<br/>cp38-musllinux_i686 | cp38-manylinux_aarch64<br/>cp38-manylinux_ppc64le<br/>cp38-manylinux_s390x<br/>cp38-manylinux_armv7l<br/>cp38-manylinux_riscv64<br/>cp38-musllinux_aarch64<br/>cp38-musllinux_ppc64le<br/>cp38-musllinux_s390x<br/>cp38-musllinux_armv7l<br/>cp38-musllinux_riscv64 | | |
|
||||
| Python 3.9 | cp39-macosx_x86_64<br/>cp39-macosx_universal2<br/>cp39-macosx_arm64 | cp39-win_amd64<br/>cp39-win32<br/>cp39-win_arm64 | cp39-manylinux_x86_64<br/>cp39-manylinux_i686<br/>cp39-musllinux_x86_64<br/>cp39-musllinux_i686 | cp39-manylinux_aarch64<br/>cp39-manylinux_ppc64le<br/>cp39-manylinux_s390x<br/>cp39-manylinux_armv7l<br/>cp39-manylinux_riscv64<br/>cp39-musllinux_aarch64<br/>cp39-musllinux_ppc64le<br/>cp39-musllinux_s390x<br/>cp39-musllinux_armv7l<br/>cp39-musllinux_riscv64 | | |
|
||||
| Python 3.10 | cp310-macosx_x86_64<br/>cp310-macosx_universal2<br/>cp310-macosx_arm64 | cp310-win_amd64<br/>cp310-win32<br/>cp310-win_arm64 | cp310-manylinux_x86_64<br/>cp310-manylinux_i686<br/>cp310-musllinux_x86_64<br/>cp310-musllinux_i686 | cp310-manylinux_aarch64<br/>cp310-manylinux_ppc64le<br/>cp310-manylinux_s390x<br/>cp310-manylinux_armv7l<br/>cp310-manylinux_riscv64<br/>cp310-musllinux_aarch64<br/>cp310-musllinux_ppc64le<br/>cp310-musllinux_s390x<br/>cp310-musllinux_armv7l<br/>cp310-musllinux_riscv64 | | |
|
||||
| Python 3.11 | cp311-macosx_x86_64<br/>cp311-macosx_universal2<br/>cp311-macosx_arm64 | cp311-win_amd64<br/>cp311-win32<br/>cp311-win_arm64 | cp311-manylinux_x86_64<br/>cp311-manylinux_i686<br/>cp311-musllinux_x86_64<br/>cp311-musllinux_i686 | cp311-manylinux_aarch64<br/>cp311-manylinux_ppc64le<br/>cp311-manylinux_s390x<br/>cp311-manylinux_armv7l<br/>cp311-manylinux_riscv64<br/>cp311-musllinux_aarch64<br/>cp311-musllinux_ppc64le<br/>cp311-musllinux_s390x<br/>cp311-musllinux_armv7l<br/>cp311-musllinux_riscv64 | | |
|
||||
| Python 3.12 | cp312-macosx_x86_64<br/>cp312-macosx_universal2<br/>cp312-macosx_arm64 | cp312-win_amd64<br/>cp312-win32<br/>cp312-win_arm64 | cp312-manylinux_x86_64<br/>cp312-manylinux_i686<br/>cp312-musllinux_x86_64<br/>cp312-musllinux_i686 | cp312-manylinux_aarch64<br/>cp312-manylinux_ppc64le<br/>cp312-manylinux_s390x<br/>cp312-manylinux_armv7l<br/>cp312-manylinux_riscv64<br/>cp312-musllinux_aarch64<br/>cp312-musllinux_ppc64le<br/>cp312-musllinux_s390x<br/>cp312-musllinux_armv7l<br/>cp312-musllinux_riscv64 | | cp312-pyodide_wasm32 |
|
||||
| Python 3.13 | cp313-macosx_x86_64<br/>cp313-macosx_universal2<br/>cp313-macosx_arm64 | cp313-win_amd64<br/>cp313-win32<br/>cp313-win_arm64 | cp313-manylinux_x86_64<br/>cp313-manylinux_i686<br/>cp313-musllinux_x86_64<br/>cp313-musllinux_i686 | cp313-manylinux_aarch64<br/>cp313-manylinux_ppc64le<br/>cp313-manylinux_s390x<br/>cp313-manylinux_armv7l<br/>cp313-manylinux_riscv64<br/>cp313-musllinux_aarch64<br/>cp313-musllinux_ppc64le<br/>cp313-musllinux_s390x<br/>cp313-musllinux_armv7l<br/>cp313-musllinux_riscv64 | cp313-ios_arm64_iphoneos<br/>cp313-ios_arm64_iphonesimulator<br/>cp313-ios_x86_64_iphonesimulator | |
|
||||
| Python 3.14 | cp314-macosx_x86_64<br/>cp314-macosx_universal2<br/>cp314-macosx_arm64 | cp314-win_amd64<br/>cp314-win32<br/>cp314-win_arm64 | cp314-manylinux_x86_64<br/>cp314-manylinux_i686<br/>cp314-musllinux_x86_64<br/>cp314-musllinux_i686 | cp314-manylinux_aarch64<br/>cp314-manylinux_ppc64le<br/>cp314-manylinux_s390x<br/>cp314-manylinux_armv7l<br/>cp314-manylinux_riscv64<br/>cp314-musllinux_aarch64<br/>cp314-musllinux_ppc64le<br/>cp314-musllinux_s390x<br/>cp314-musllinux_armv7l<br/>cp314-musllinux_riscv64 | | |
|
||||
| PyPy3.8 v7.3 | pp38-macosx_x86_64<br/>pp38-macosx_arm64 | pp38-win_amd64 | pp38-manylinux_x86_64<br/>pp38-manylinux_i686 | pp38-manylinux_aarch64 | | |
|
||||
| PyPy3.9 v7.3 | pp39-macosx_x86_64<br/>pp39-macosx_arm64 | pp39-win_amd64 | pp39-manylinux_x86_64<br/>pp39-manylinux_i686 | pp39-manylinux_aarch64 | | |
|
||||
| PyPy3.10 v7.3 | pp310-macosx_x86_64<br/>pp310-macosx_arm64 | pp310-win_amd64 | pp310-manylinux_x86_64<br/>pp310-manylinux_i686 | pp310-manylinux_aarch64 | | |
|
||||
| PyPy3.11 v7.3 | pp311-macosx_x86_64<br/>pp311-macosx_arm64 | pp311-win_amd64 | pp311-manylinux_x86_64<br/>pp311-manylinux_i686 | pp311-manylinux_aarch64 | | |
|
||||
|
||||
The list of supported and currently selected build identifiers can also be retrieved by passing the `--print-build-identifiers` flag to cibuildwheel.
|
||||
The format is `python_tag-platform_tag`, with tags similar to those in [PEP 425](https://www.python.org/dev/peps/pep-0425/#details).
|
||||
@@ -70,9 +71,6 @@ The format is `python_tag-platform_tag`, with tags similar to those in [PEP 425]
|
||||
Windows arm64 platform support is experimental.
|
||||
Linux riscv64 platform support is experimental and requires an explicit opt-in through [CIBW_ENABLE](#enable).
|
||||
|
||||
For an experimental WebAssembly build with `--platform pyodide`,
|
||||
`cp312-pyodide_wasm32` is the only platform identifier.
|
||||
|
||||
See the [cibuildwheel 2 documentation](https://cibuildwheel.pypa.io/en/2.x/) for past end-of-life versions of Python.
|
||||
|
||||
#### Examples
|
||||
@@ -1223,6 +1221,45 @@ Platform-specific environment variables are also available:<br/>
|
||||
dependency-versions = { packages = ["pyodide-build==0.29.1"] }
|
||||
```
|
||||
|
||||
### `CIBW_PYODIDE_VERSION` {: #pyodide-version}
|
||||
|
||||
> Specify the Pyodide version to use for `pyodide` platform builds
|
||||
|
||||
This option allows you to specify a specific version of Pyodide to be used when building wheels for the `pyodide` platform. If unset, cibuildwheel will use a pinned Pyodide version.
|
||||
|
||||
This option is particularly useful for:
|
||||
|
||||
- Testing against specific Pyodide alpha or older releases.
|
||||
- Ensuring reproducibility by targeting a known Pyodide version.
|
||||
|
||||
The available Pyodide versions are determined by the version of `pyodide-build` being used. You can list the compatible versions using the command `pyodide xbuildenv search --all` as described in the [Pyodide platform documentation](platforms.md#pyodide-choosing-a-version).
|
||||
|
||||
!!! tip
|
||||
You can set the version of `pyodide-build` using the [`CIBW_DEPENDENCY_VERSIONS`](#dependency-versions) option.
|
||||
|
||||
#### Examples
|
||||
|
||||
!!! tab examples "Environment variables"
|
||||
|
||||
```yaml
|
||||
# Build Pyodide wheels using Pyodide version 0.27.6
|
||||
CIBW_PYODIDE_VERSION: 0.27.6
|
||||
|
||||
# Build Pyodide wheels using a specific alpha release
|
||||
CIBW_PYODIDE_VERSION: 0.28.0a2
|
||||
```
|
||||
|
||||
!!! tab examples "pyproject.toml"
|
||||
|
||||
```toml
|
||||
[tool.cibuildwheel.pyodide]
|
||||
# Build Pyodide wheels using Pyodide version 0.27.6
|
||||
pyodide-version = "0.27.6"
|
||||
|
||||
[tool.cibuildwheel.pyodide]
|
||||
# Build Pyodide wheels using a specific alpha release
|
||||
pyodide-version = "0.28.0a2"
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
@@ -1539,6 +1576,42 @@ This option is not supported in the overrides section in `pyproject.toml`.
|
||||
test-skip = "*-macosx_arm64 *-macosx_universal2:arm64"
|
||||
```
|
||||
|
||||
### `CIBW_TEST_ENVIRONMENT` {: #test-environment}
|
||||
|
||||
> Set environment variables for the test environment
|
||||
|
||||
A space-separated list of environment variables to set in the test environment.
|
||||
|
||||
The syntax is the same as for [`CIBW_ENVIRONMENT`](#environment).
|
||||
|
||||
cibuildwheel sets the variable [`PYTHONSAFEPATH`](https://docs.python.org/3/using/cmdline.html#envvar-PYTHONSAFEPATH) to avoid picking up in-tree dependencies when running the tests - we want to test the installed wheel, not the in-tree version. However, this can be overridden by setting `PYTHONSAFEPATH` to an empty string.
|
||||
|
||||
Platform-specific environment variables are also available:<br/>
|
||||
`CIBW_TEST_ENVIRONMENT_MACOS` | `CIBW_TEST_ENVIRONMENT_WINDOWS` | `CIBW_TEST_ENVIRONMENT_LINUX` | `CIBW_TEST_ENVIRONMENT_IOS` | `CIBW_TEST_ENVIRONMENT_PYODIDE`
|
||||
|
||||
#### Examples
|
||||
|
||||
!!! tab examples "Environment variables"
|
||||
|
||||
```yaml
|
||||
# Set the environment variable MY_ENV_VAR to "my_value" in the test environment
|
||||
CIBW_TEST_ENVIRONMENT: MY_ENV_VAR=my_value
|
||||
|
||||
# Unset PYTHONSAFEPATH in the test environment
|
||||
CIBW_TEST_ENVIRONMENT: PYTHONSAFEPATH=
|
||||
```
|
||||
|
||||
!!! tab examples "pyproject.toml"
|
||||
|
||||
```toml
|
||||
[tool.cibuildwheel]
|
||||
# Set the environment variable MY_ENV_VAR to "my_value" in the test environment
|
||||
test-environment = { MY_ENV_VAR="my_value" }
|
||||
|
||||
# Unset PYTHONSAFEPATH in the test environment
|
||||
test-environment = { PYTHONSAFEPATH="" }
|
||||
```
|
||||
|
||||
## Debugging
|
||||
|
||||
### `CIBW_DEBUG_KEEP_CONTAINER`
|
||||
|
||||
+14
-6
@@ -3,7 +3,7 @@ title: Platforms
|
||||
---
|
||||
# Platforms
|
||||
|
||||
## Linux
|
||||
## Linux {: #linux}
|
||||
|
||||
### System requirements
|
||||
|
||||
@@ -31,7 +31,7 @@ Linux wheels are built in [`manylinux`/`musllinux` containers](https://github.co
|
||||
|
||||
- Alternative Docker images can be specified with the `CIBW_MANYLINUX_*_IMAGE`/`CIBW_MUSLLINUX_*_IMAGE` options to allow for a custom, preconfigured build environment for the Linux builds. See [options](options.md#linux-image) for more details.
|
||||
|
||||
## macOS
|
||||
## macOS {: #macos}
|
||||
|
||||
### System requirements
|
||||
|
||||
@@ -138,7 +138,7 @@ Regarding testing,
|
||||
As a workaround, the tag can be fixed before running delocate to repair the wheel. The [`wheel tags`](https://wheel.readthedocs.io/en/stable/reference/wheel_tags.html) command is ideal for this. See [this workflow](https://gist.github.com/anderssonjohan/49f07e33fc5cb2420515a8ac76dc0c95#file-build-pendulum-wheels-yml-L39-L53) for an example usage of `wheel tags`.
|
||||
|
||||
|
||||
## Windows
|
||||
## Windows {: #windows}
|
||||
|
||||
### System requirements
|
||||
|
||||
@@ -160,15 +160,23 @@ By default, `ARM64` is not enabled when running on non-ARM64 runners. Use [`CIBW
|
||||
|
||||
Pyodide is offered as an experimental feature in cibuildwheel.
|
||||
|
||||
### Prerequisites
|
||||
### System requirements
|
||||
|
||||
You need to have a matching host version of Python (unlike all other cibuildwheel platforms). Linux host highly recommended; macOS hosts may work (e.g. invoking `pytest` directly in [`CIBW_TEST_COMMAND`](options.md#test-command) is [currently failing](https://github.com/pyodide/pyodide/issues/4802)) and Windows hosts will not work.
|
||||
Pyodide builds require a Linux or macOS machine.
|
||||
|
||||
### Specifying a pyodide build
|
||||
|
||||
You must target pyodide with `--platform pyodide` (or use `--only` on the identifier).
|
||||
|
||||
## iOS
|
||||
### Choosing a Pyodide version {: #pyodide-choosing-a-version}
|
||||
|
||||
It is also possible to target a specific Pyodide version by setting the `CIBW_PYODIDE_VERSION` option to the desired version. Users are responsible for setting an appropriate Pyodide version according to the `pyodide-build` version. A list is available in Pyodide's [cross-build environments metadata file](https://github.com/pyodide/pyodide/blob/main/pyodide-cross-build-environments.json), which can be viewed more easily by installing `pyodide-build` from PyPI and using `pyodide xbuildenv search --all` to see a compatibility table.
|
||||
|
||||
### Running tests
|
||||
|
||||
Currently, it's recommended to run tests using a `python -m` entrypoint, rather than a command line entrypoint, or a shell script. This is because custom entrypoints have some issues in the Pyodide virtual environment. For example, `pytest` may not work as a command line entrypoint, but will work as a `python -m pytest` entrypoint.
|
||||
|
||||
## iOS {: #ios}
|
||||
|
||||
### System requirements
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ jobs:
|
||||
- bash: |
|
||||
set -o errexit
|
||||
python3 -m pip install --upgrade pip
|
||||
pip3 install cibuildwheel==3.0.0b1
|
||||
pip3 install cibuildwheel==3.0.0b2
|
||||
displayName: Install dependencies
|
||||
- bash: cibuildwheel --output-dir wheelhouse .
|
||||
displayName: Build wheels
|
||||
@@ -20,7 +20,7 @@ jobs:
|
||||
- bash: |
|
||||
set -o errexit
|
||||
python3 -m pip install --upgrade pip
|
||||
python3 -m pip install cibuildwheel==3.0.0b1
|
||||
python3 -m pip install cibuildwheel==3.0.0b2
|
||||
displayName: Install dependencies
|
||||
- bash: cibuildwheel --output-dir wheelhouse .
|
||||
displayName: Build wheels
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
- bash: |
|
||||
set -o errexit
|
||||
python -m pip install --upgrade pip
|
||||
pip install cibuildwheel==3.0.0b1
|
||||
pip install cibuildwheel==3.0.0b2
|
||||
displayName: Install dependencies
|
||||
- bash: cibuildwheel --output-dir wheelhouse .
|
||||
displayName: Build wheels
|
||||
|
||||
@@ -11,7 +11,7 @@ jobs:
|
||||
- run:
|
||||
name: Build the Linux wheels.
|
||||
command: |
|
||||
python3 -m pip install --user cibuildwheel==3.0.0b1
|
||||
python3 -m pip install --user cibuildwheel==3.0.0b2
|
||||
cibuildwheel --output-dir wheelhouse
|
||||
- store_artifacts:
|
||||
path: wheelhouse/
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
- run:
|
||||
name: Build the Linux aarch64 wheels.
|
||||
command: |
|
||||
python3 -m pip install --user cibuildwheel==3.0.0b1
|
||||
python3 -m pip install --user cibuildwheel==3.0.0b2
|
||||
python3 -m cibuildwheel --output-dir wheelhouse
|
||||
- store_artifacts:
|
||||
path: wheelhouse/
|
||||
@@ -44,7 +44,7 @@ jobs:
|
||||
name: Build the OS X wheels.
|
||||
command: |
|
||||
sudo softwareupdate --install-rosetta --agree-to-license # for python<=3.8 or x86_64/universal2 tests
|
||||
pip3 install cibuildwheel==3.0.0b1
|
||||
pip3 install cibuildwheel==3.0.0b2
|
||||
cibuildwheel --output-dir wheelhouse
|
||||
- store_artifacts:
|
||||
path: wheelhouse/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
build_and_store_wheels: &BUILD_AND_STORE_WHEELS
|
||||
install_cibuildwheel_script:
|
||||
- python -m pip install cibuildwheel==3.0.0b1
|
||||
- python -m pip install cibuildwheel==3.0.0b2
|
||||
run_cibuildwheel_script:
|
||||
- cibuildwheel
|
||||
wheels_artifacts:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
build_and_store_wheels: &BUILD_AND_STORE_WHEELS
|
||||
install_cibuildwheel_script:
|
||||
- python -m pip install cibuildwheel==3.0.0b1
|
||||
- python -m pip install cibuildwheel==3.0.0b2
|
||||
run_cibuildwheel_script:
|
||||
- cibuildwheel
|
||||
wheels_artifacts:
|
||||
|
||||
@@ -44,7 +44,7 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Build wheels
|
||||
uses: pypa/cibuildwheel@v3.0.0b1
|
||||
uses: pypa/cibuildwheel@v3.0.0b2
|
||||
env:
|
||||
CIBW_PLATFORM: ${{ matrix.platform }}
|
||||
CIBW_ARCHS: ${{ matrix.archs }}
|
||||
|
||||
@@ -15,7 +15,7 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Build wheels
|
||||
uses: pypa/cibuildwheel@v3.0.0b1
|
||||
uses: pypa/cibuildwheel@v3.0.0b2
|
||||
# env:
|
||||
# CIBW_SOME_OPTION: value
|
||||
# ...
|
||||
|
||||
@@ -15,7 +15,7 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Build wheels
|
||||
run: pipx run cibuildwheel==3.0.0b1
|
||||
run: pipx run cibuildwheel==3.0.0b2
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
|
||||
@@ -21,7 +21,7 @@ jobs:
|
||||
platforms: all
|
||||
|
||||
- name: Build wheels
|
||||
uses: pypa/cibuildwheel@v3.0.0b1
|
||||
uses: pypa/cibuildwheel@v3.0.0b2
|
||||
env:
|
||||
# configure cibuildwheel on Linux to build native archs ('auto'),
|
||||
# and to split the remaining architectures between the x86_64 and
|
||||
|
||||
@@ -12,7 +12,7 @@ linux:
|
||||
DOCKER_TLS_CERTDIR: ""
|
||||
script:
|
||||
- curl -sSL https://get.docker.com/ | sh
|
||||
- python -m pip install cibuildwheel==3.0.0b1
|
||||
- python -m pip install cibuildwheel==3.0.0b2
|
||||
- cibuildwheel --output-dir wheelhouse
|
||||
artifacts:
|
||||
paths:
|
||||
@@ -23,7 +23,7 @@ windows:
|
||||
before_script:
|
||||
- choco install python -y --version 3.12.4
|
||||
- choco install git.install -y
|
||||
- py -m pip install cibuildwheel==3.0.0b1
|
||||
- py -m pip install cibuildwheel==3.0.0b2
|
||||
script:
|
||||
- py -m cibuildwheel --output-dir wheelhouse --platform windows
|
||||
artifacts:
|
||||
@@ -35,7 +35,7 @@ windows:
|
||||
macos:
|
||||
image: macos-14-xcode-15
|
||||
before_script:
|
||||
- python3 -m pip install cibuildwheel==3.0.0b1
|
||||
- python3 -m pip install cibuildwheel==3.0.0b2
|
||||
script:
|
||||
- python3 -m cibuildwheel --output-dir wheelhouse
|
||||
artifacts:
|
||||
|
||||
@@ -14,7 +14,7 @@ linux:
|
||||
- curl -sSL https://get.docker.com/ | sh
|
||||
# Warning: This is extremely slow, be careful with how many wheels you build
|
||||
- docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
|
||||
- python -m pip install cibuildwheel==3.0.0b1
|
||||
- python -m pip install cibuildwheel==3.0.0b2
|
||||
# Assuming your CI runner's default architecture is x86_64...
|
||||
- cibuildwheel --output-dir wheelhouse --platform linux --archs aarch64
|
||||
artifacts:
|
||||
|
||||
@@ -20,7 +20,7 @@ jobs:
|
||||
- ln -s /c/Python312/python.exe /c/Python312/python3.exe
|
||||
|
||||
install:
|
||||
- python3 -m pip install cibuildwheel==3.0.0b1
|
||||
- python3 -m pip install cibuildwheel==3.0.0b2
|
||||
|
||||
script:
|
||||
# build the wheels, put them into './dist'
|
||||
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
- ln -s /c/Python312/python.exe /c/Python312/python3.exe
|
||||
|
||||
install:
|
||||
- python3 -m pip install cibuildwheel==3.0.0b1
|
||||
- python3 -m pip install cibuildwheel==3.0.0b2
|
||||
|
||||
script:
|
||||
# build the wheels, put them into './wheelhouse'
|
||||
|
||||
@@ -52,7 +52,7 @@ jobs:
|
||||
- stage: deploy
|
||||
name: Build and deploy Linux wheels
|
||||
services: docker
|
||||
install: python3 -m pip install cibuildwheel==3.0.0b1 twine
|
||||
install: python3 -m pip install cibuildwheel==3.0.0b2 twine
|
||||
script: python3 -m cibuildwheel --output-dir wheelhouse
|
||||
after_success: python3 -m twine upload --skip-existing wheelhouse/*.whl
|
||||
# Deploy on windows
|
||||
@@ -60,7 +60,7 @@ jobs:
|
||||
name: Build and deploy Windows wheels
|
||||
os: windows
|
||||
language: shell
|
||||
install: python3 -m pip install cibuildwheel==3.0.0b1 twine
|
||||
install: python3 -m pip install cibuildwheel==3.0.0b2 twine
|
||||
script: python3 -m cibuildwheel --output-dir wheelhouse
|
||||
after_success: python3 -m twine upload --skip-existing wheelhouse/*.whl
|
||||
|
||||
|
||||
+21
-9
@@ -68,17 +68,20 @@ def update_constraints(session: nox.Session) -> None:
|
||||
Update the dependencies inplace.
|
||||
"""
|
||||
|
||||
session.install("-e.", "click")
|
||||
|
||||
resources = Path("cibuildwheel/resources")
|
||||
|
||||
if session.venv_backend != "uv":
|
||||
session.install("uv>=0.1.23")
|
||||
|
||||
# CUSTOM_COMPILE_COMMAND is a pip-compile option that tells users how to
|
||||
# regenerate the constraints files
|
||||
env = os.environ.copy()
|
||||
env["UV_CUSTOM_COMPILE_COMMAND"] = f"nox -s {session.name}"
|
||||
|
||||
for minor_version in range(8, 15):
|
||||
python_version = f"3.{minor_version}"
|
||||
env = os.environ.copy()
|
||||
# CUSTOM_COMPILE_COMMAND is a pip-compile option that tells users how to
|
||||
# regenerate the constraints files
|
||||
env["UV_CUSTOM_COMPILE_COMMAND"] = f"nox -s {session.name}"
|
||||
output_file = resources / f"constraints-python{python_version.replace('.', '')}.txt"
|
||||
session.run(
|
||||
"uv",
|
||||
@@ -100,12 +103,19 @@ def update_constraints(session: nox.Session) -> None:
|
||||
pyodides = build_platforms["pyodide"]["python_configurations"]
|
||||
for pyodide in pyodides:
|
||||
python_version = ".".join(pyodide["version"].split(".")[:2])
|
||||
pyodide_build_version = pyodide["pyodide_build_version"]
|
||||
output_file = resources / f"constraints-pyodide{python_version.replace('.', '')}.txt"
|
||||
pyodide_version = pyodide["default_pyodide_version"]
|
||||
|
||||
tmp_file = Path(session.create_tmp()) / "constraints-pyodide.in"
|
||||
tmp_file.write_text(
|
||||
f"pip\nbuild[virtualenv]\npyodide-build=={pyodide_build_version}\nclick<8.2"
|
||||
|
||||
session.run(
|
||||
"python",
|
||||
"bin/generate_pyodide_constraints.py",
|
||||
"--output-file",
|
||||
tmp_file,
|
||||
pyodide_version,
|
||||
)
|
||||
|
||||
output_file = resources / f"constraints-pyodide{python_version.replace('.', '')}.txt"
|
||||
session.run(
|
||||
"uv",
|
||||
"pip",
|
||||
@@ -121,7 +131,8 @@ def update_constraints(session: nox.Session) -> None:
|
||||
@nox.session(default=False, tags=["update"])
|
||||
def update_pins(session: nox.Session) -> None:
|
||||
"""
|
||||
Update the python, docker and virtualenv pins version inplace.
|
||||
Update the python, docker, virtualenv, node, and python-build-standalone
|
||||
version pins inplace.
|
||||
"""
|
||||
pyproject = nox.project.load_toml()
|
||||
session.install("-e.", *nox.project.dependency_groups(pyproject, "bin"))
|
||||
@@ -129,6 +140,7 @@ def update_pins(session: nox.Session) -> None:
|
||||
session.run("python", "bin/update_docker.py")
|
||||
session.run("python", "bin/update_virtualenv.py", "--force")
|
||||
session.run("python", "bin/update_nodejs.py", "--force")
|
||||
session.run("python", "bin/update_python_build_standalone.py")
|
||||
|
||||
|
||||
@nox.session(default=False, reuse_venv=True, tags=["update"])
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
||||
|
||||
[project]
|
||||
name = "cibuildwheel"
|
||||
version = "3.0.0b1"
|
||||
version = "3.0.0b2"
|
||||
description = "Build Python wheels on CI with minimal configuration."
|
||||
readme = "README.md"
|
||||
license = "BSD-2-Clause"
|
||||
|
||||
@@ -48,8 +48,13 @@ def test_abi3(tmp_path):
|
||||
|
||||
# check that the expected wheels are produced
|
||||
if utils.get_platform() == "pyodide":
|
||||
# there's only 1 possible configuration for pyodide, cp312
|
||||
expected_wheels = utils.expected_wheels("spam", "0.1.0", python_abi_tags=["cp310-abi3"])
|
||||
# there's only 1 possible configuration for pyodide, cp312. It builds
|
||||
# a wheel that is tagged abi3, compatible back to 3.10
|
||||
expected_wheels = utils.expected_wheels(
|
||||
"spam",
|
||||
"0.1.0",
|
||||
python_abi_tags=["cp310-abi3"],
|
||||
)
|
||||
else:
|
||||
expected_wheels = utils.expected_wheels(
|
||||
"spam",
|
||||
@@ -189,15 +194,17 @@ def test_abi_none(tmp_path, capfd):
|
||||
},
|
||||
)
|
||||
|
||||
# check that the expected wheels are produced
|
||||
expected_wheels = utils.expected_wheels("ctypesexample", "1.0.0", python_abi_tags=["py3-none"])
|
||||
# check that the expected wheels are produced
|
||||
assert set(actual_wheels) == set(expected_wheels)
|
||||
|
||||
# check that each wheel was built once, and reused
|
||||
captured = capfd.readouterr()
|
||||
assert "Building wheel..." in captured.out
|
||||
|
||||
if utils.get_platform() == "pyodide":
|
||||
# there's only 1 possible configuration for pyodide, we won't see the message expected on following builds
|
||||
# pyodide builds a different platform tag for each python version, so
|
||||
# wheels are not reused
|
||||
assert "Found previously built wheel" not in captured.out
|
||||
else:
|
||||
# check that each wheel was built once, and reused
|
||||
assert "Building wheel..." in captured.out
|
||||
assert "Found previously built wheel" in captured.out
|
||||
|
||||
@@ -16,6 +16,11 @@ 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
|
||||
# not valid, but it does activate the uniqueness check
|
||||
platform = "pyodide"
|
||||
|
||||
name = f"spam-0.1.0-py2-none-{platform}.whl"
|
||||
dest = dest_dir / name
|
||||
dest_dir.mkdir(parents=True, exist_ok=True)
|
||||
@@ -48,11 +53,6 @@ def test(tmp_path, capfd):
|
||||
assert "Build failed because a wheel named" in captured.err
|
||||
assert exc_info.value.returncode == 6
|
||||
else:
|
||||
# We only produced one wheel (currently Pyodide)
|
||||
# We only produced one wheel (perhaps Pyodide)
|
||||
# check that it has the right name
|
||||
#
|
||||
# As far as I can tell, this is the only full test coverage for
|
||||
# CIBW_REPAIR_WHEEL_COMMAND so this is useful even in the case when no
|
||||
# error is raised
|
||||
assert "spam-0.1.0-py2-none-pyodide" in captured.out
|
||||
assert result[0].startswith("spam-0.1.0-py2-none-")
|
||||
|
||||
@@ -70,7 +70,10 @@ def test_pinned_versions(tmp_path, python_version, build_frontend_env_nouv):
|
||||
version_no_dot = python_version.replace(".", "")
|
||||
build_environment = {}
|
||||
build_pattern = f"[cp]p{version_no_dot}-*"
|
||||
constraint_filename = f"constraints-python{version_no_dot}.txt"
|
||||
if utils.get_platform() == "pyodide":
|
||||
constraint_filename = f"constraints-pyodide{version_no_dot}.txt"
|
||||
else:
|
||||
constraint_filename = f"constraints-python{version_no_dot}.txt"
|
||||
constraint_file = resources.PATH / constraint_filename
|
||||
constraint_versions = get_versions_from_constraint_file(constraint_file)
|
||||
|
||||
|
||||
@@ -100,7 +100,12 @@ def test_overridden_path(tmp_path, capfd):
|
||||
"build_frontend",
|
||||
[
|
||||
pytest.param("pip", marks=utils.skip_if_pyodide("No pip for pyodide")),
|
||||
"build",
|
||||
pytest.param(
|
||||
"build",
|
||||
marks=utils.skip_if_pyodide(
|
||||
"pyodide doesn't support multiple values for PIP_CONSTRAINT"
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_overridden_pip_constraint(tmp_path, build_frontend):
|
||||
|
||||
+10
-3
@@ -60,12 +60,19 @@ def test_pep518(tmp_path, build_frontend_env):
|
||||
assert not (project_dir / "42").exists()
|
||||
assert not (project_dir / "4.1.2").exists()
|
||||
|
||||
# pypa/build creates a "build" folder & a "*.egg-info" folder for the wheel being built,
|
||||
# this should be harmless so remove them
|
||||
# pypa/build creates a "build" folder & a "*.egg-info" folder for the
|
||||
# wheel being built, this should be harmless so remove them. pyodide-build
|
||||
# creates a ".pyodide_build" folder, but this is gitignored with a
|
||||
# .gitignore file inside.
|
||||
contents = [
|
||||
item
|
||||
for item in project_dir.iterdir()
|
||||
if item.name != "build" and not item.name.endswith(".egg-info")
|
||||
if item.name != "build"
|
||||
and not item.name.endswith(".egg-info")
|
||||
and item.name != ".pyodide_build"
|
||||
]
|
||||
|
||||
print("Project contents after build:")
|
||||
print("\n".join(f" {f}" for f in contents))
|
||||
|
||||
assert len(contents) == len(basic_project.files)
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import shutil
|
||||
import contextlib
|
||||
import subprocess
|
||||
import sys
|
||||
import textwrap
|
||||
|
||||
import pytest
|
||||
|
||||
from cibuildwheel.ci import CIProvider, detect_ci_provider
|
||||
from cibuildwheel.util.file import CIBW_CACHE_PATH
|
||||
|
||||
from . import test_projects, utils
|
||||
@@ -43,13 +43,7 @@ if __name__ == "__main__":
|
||||
@pytest.mark.parametrize("use_pyproject_toml", [True, False])
|
||||
def test_pyodide_build(tmp_path, use_pyproject_toml):
|
||||
if sys.platform == "win32":
|
||||
pytest.skip("emsdk doesn't work correctly on Windows")
|
||||
|
||||
if not shutil.which("python3.12"):
|
||||
pytest.skip("Python 3.12 not installed")
|
||||
|
||||
if detect_ci_provider() == CIProvider.travis_ci:
|
||||
pytest.skip("Python 3.12 is just a non-working pyenv shim")
|
||||
pytest.skip("pyodide-build doesn't work correctly on Windows")
|
||||
|
||||
if use_pyproject_toml:
|
||||
basic_project.files["pyproject.toml"] = textwrap.dedent(
|
||||
@@ -84,3 +78,64 @@ def test_pyodide_build(tmp_path, use_pyproject_toml):
|
||||
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)
|
||||
+2
-2
@@ -10,9 +10,9 @@ project_with_ssl_tests = test_projects.new_c_project(
|
||||
from urllib.request import urlopen
|
||||
|
||||
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
|
||||
# badssl.com is a HTTPS test server that can be used to test SSL connections
|
||||
data = urlopen("https://tls-v1-2.badssl.com", context=context)
|
||||
data = urlopen("https://raw.githubusercontent.com/pypa/cibuildwheel/main/CI.md", context=context)
|
||||
data = urlopen("https://raw.githubusercontent.com/pypa/cibuildwheel/main/CI.md")
|
||||
data = urlopen("https://tls-v1-2.badssl.com")
|
||||
"""
|
||||
)
|
||||
)
|
||||
|
||||
+23
-1
@@ -66,6 +66,12 @@ class TestSpam(TestCase):
|
||||
bits = struct.calcsize("P") * 8
|
||||
if bits == 32:
|
||||
self.assertIn(platform.machine(), ["i686", "armv7l","armv8l", "wasm32"])
|
||||
|
||||
def test_pythonsafepath(self):
|
||||
# check that the PYTHONSAFEPATH environment variable is set
|
||||
value = os.environ.get("PYTHONSAFEPATH")
|
||||
self.assertIsNotNone(value)
|
||||
self.assertNotEqual(value, "")
|
||||
'''
|
||||
|
||||
|
||||
@@ -218,10 +224,10 @@ def test_test_sources(tmp_path):
|
||||
project_dir,
|
||||
add_env={
|
||||
"CIBW_TEST_REQUIRES": "pytest",
|
||||
"CIBW_TEST_COMMAND": "pytest",
|
||||
# pytest fails on GraalPy 24.2.0 on Windows so we skip it there
|
||||
# until https://github.com/oracle/graalpython/issues/490 is fixed
|
||||
"CIBW_TEST_COMMAND_WINDOWS": "where graalpy || pytest",
|
||||
"CIBW_TEST_COMMAND": utils.invoke_pytest(),
|
||||
"CIBW_TEST_SOURCES": "test",
|
||||
},
|
||||
)
|
||||
@@ -229,3 +235,19 @@ def test_test_sources(tmp_path):
|
||||
# also check that we got the right wheels
|
||||
expected_wheels = utils.expected_wheels("spam", "0.1.0")
|
||||
assert set(actual_wheels) == set(expected_wheels)
|
||||
|
||||
|
||||
def test_test_environment(tmp_path):
|
||||
project_dir = tmp_path / "project"
|
||||
test_projects.new_c_project().generate(project_dir)
|
||||
|
||||
actual_wheels = utils.cibuildwheel_run(
|
||||
project_dir,
|
||||
add_env={
|
||||
"CIBW_TEST_ENVIRONMENT": "MYVAR=somevalue PYTHONSAFEPATH=",
|
||||
"CIBW_TEST_COMMAND": "python -c \"import os; assert os.environ.get('MYVAR') == 'somevalue'; assert os.environ.get('PYTHONSAFEPATH') == ''\"",
|
||||
},
|
||||
)
|
||||
# also check that we got the right wheels
|
||||
expected_wheels = utils.expected_wheels("spam", "0.1.0")
|
||||
assert set(actual_wheels) == set(expected_wheels)
|
||||
|
||||
+10
-2
@@ -382,7 +382,15 @@ def _expected_wheels(
|
||||
raise Exception(msg)
|
||||
|
||||
elif platform == "pyodide":
|
||||
platform_tags = ["pyodide_2024_0_wasm32"]
|
||||
platform_tags = {
|
||||
"cp312-cp312": ["pyodide_2024_0_wasm32"],
|
||||
"cp313-cp313": ["pyodide_2025_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"]
|
||||
|
||||
else:
|
||||
msg = f"Unsupported platform {platform!r}"
|
||||
@@ -425,7 +433,7 @@ def skip_if_pyodide(reason: str) -> Any:
|
||||
|
||||
def invoke_pytest() -> str:
|
||||
# see https://github.com/pyodide/pyodide/issues/4802
|
||||
if get_platform() == "pyodide" and sys.platform.startswith("darwin"):
|
||||
if get_platform() == "pyodide":
|
||||
return "python -m pytest"
|
||||
return "pytest"
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import pytest
|
||||
|
||||
from cibuildwheel.util.file import download
|
||||
|
||||
DOWNLOAD_URL = "https://raw.githubusercontent.com/pypa/cibuildwheel/v1.6.3/requirements-dev.txt"
|
||||
DOWNLOAD_URL = "https://cdn.jsdelivr.net/gh/pypa/cibuildwheel@v1.6.3/requirements-dev.txt"
|
||||
|
||||
|
||||
def test_download(monkeypatch, tmp_path):
|
||||
|
||||
@@ -34,6 +34,8 @@ manylinux-x86_64-image = "manylinux_2_28"
|
||||
|
||||
environment-pass = ["EXAMPLE_ENV"]
|
||||
|
||||
pyodide-version = "0.27.6"
|
||||
|
||||
[tool.cibuildwheel.macos]
|
||||
test-requires = "else"
|
||||
|
||||
@@ -88,6 +90,9 @@ def test_options_1(tmp_path, monkeypatch):
|
||||
assert local.test_sources == ["test", "other dir"]
|
||||
assert local.manylinux_images["x86_64"] == pinned_x86_64_container_image["manylinux_2_34"]
|
||||
|
||||
local = options.build_options("cp312-pyodide_wasm32")
|
||||
assert local.pyodide_version == "0.27.6"
|
||||
|
||||
|
||||
def test_passthrough(tmp_path, monkeypatch):
|
||||
with tmp_path.joinpath("pyproject.toml").open("w") as f:
|
||||
|
||||
@@ -12,6 +12,8 @@ from cibuildwheel.util.helpers import (
|
||||
format_safe,
|
||||
parse_key_value_string,
|
||||
prepare_command,
|
||||
unwrap,
|
||||
unwrap_preserving_paragraphs,
|
||||
)
|
||||
from cibuildwheel.util.packaging import find_compatible_wheel
|
||||
|
||||
@@ -363,3 +365,33 @@ def test_copy_test_sources_alternate_copy_into(sample_project):
|
||||
],
|
||||
any_order=True,
|
||||
)
|
||||
|
||||
|
||||
def test_unwrap():
|
||||
assert (
|
||||
unwrap("""
|
||||
This is a
|
||||
multiline
|
||||
string
|
||||
""")
|
||||
== "This is a multiline string"
|
||||
)
|
||||
|
||||
|
||||
def test_unwrap_preserving_paragraphs():
|
||||
assert (
|
||||
unwrap("""
|
||||
This is a
|
||||
multiline
|
||||
string
|
||||
""")
|
||||
== "This is a multiline string"
|
||||
)
|
||||
assert (
|
||||
unwrap_preserving_paragraphs("""
|
||||
paragraph one
|
||||
|
||||
paragraph two
|
||||
""")
|
||||
== "paragraph one\n\nparagraph two"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user