diff --git a/bin/update_how_it_works_image.py b/bin/update_how_it_works_image.py
index 504c9bc4..54350ace 100755
--- a/bin/update_how_it_works_image.py
+++ b/bin/update_how_it_works_image.py
@@ -1,49 +1,57 @@
#!/usr/bin/env python3
-
import subprocess
-import sys
+import tempfile
from pathlib import Path
try:
- from html2image import Html2Image # type: ignore[import-not-found]
+ from playwright.sync_api import sync_playwright # type: ignore[import-not-found]
except ImportError:
- sys.exit(
+ msg = """
+ playwright not found. Install it with:
+ pip install playwright
+ playwright install chromium
+
+ Or, run this script with:
+ nox -s update_how_it_works_image
"""
- html2image not found. Ensure you have Chrome (on Mac/Windows) or
- Chromium (on Linux) installed, and then do:
- pip install html2image
- """
- )
+ raise SystemExit(msg) from None
def main() -> None:
- subprocess.run(["mkdocs", "build"], check=True)
+ with tempfile.TemporaryDirectory() as tmp_dir_str:
+ tmp_dir = Path(tmp_dir_str)
+ subprocess.run(["mkdocs", "build", "--site-dir", tmp_dir], check=True)
- hti = Html2Image(custom_flags=["--force-device-scale-factor=2"])
+ html_str = Path("docs/diagram.html").read_text()
+ css_tags = f"""
+
+
+
+
+ """
+ html_str = f"
{css_tags}{html_str}"
- html_str = Path("docs/diagram.md").read_text()
- css_tags = f"""
-
-
-
-
- """
- html_str = css_tags + html_str
+ html_path = Path(tmp_dir) / "diagram_screenshot.html"
+ html_path.write_text(html_str)
- [screenshot, *_] = hti.screenshot(
- html_str=html_str,
- size=(830, 405),
- )
+ dest_path = Path("docs/data/how-it-works.png")
- dest_path = Path("docs/data/how-it-works.png")
- dest_path.unlink(missing_ok=True)
+ with sync_playwright() as p:
+ browser = p.chromium.launch()
+ page = browser.new_page(device_scale_factor=2, viewport={"width": 830, "height": 600})
+ page.goto(html_path.as_uri())
+ page.wait_for_load_state("networkidle")
- Path(screenshot).rename(dest_path)
+ height = page.evaluate("document.body.scrollHeight")
+ page.set_viewport_size({"width": 830, "height": height})
+
+ page.screenshot(path=str(dest_path), full_page=True)
+ browser.close()
if __name__ == "__main__":
diff --git a/docs/data/how-it-works.png b/docs/data/how-it-works.png
index 41d58990..bbbc2a30 100644
Binary files a/docs/data/how-it-works.png and b/docs/data/how-it-works.png differ
diff --git a/docs/diagram.html b/docs/diagram.html
index 52c70b9e..8d9785e2 100644
--- a/docs/diagram.html
+++ b/docs/diagram.html
@@ -5,6 +5,9 @@
@@ -17,11 +20,17 @@
+
+
+
Linux
macOS
Windows
+
Android
+
iOS
+
Pyodide
@@ -86,7 +95,7 @@
[
{
href: 'options/#before-all',
- platforms: ['linux', 'macos', 'windows'],
+ platforms: ['linux', 'macos', 'windows', 'android', 'ios', 'pyodide'],
style: 'dot',
tooltip: {
title: 'CIBW_BEFORE_ALL',
@@ -104,11 +113,27 @@
description: 'Install the version of Python required to build this wheel.'
},
},
+ {
+ label: 'Install Python & set up cross-compilation',
+ platforms: ['android', 'ios'],
+ style: 'block',
+ tooltip: {
+ description: 'Install Python for the build and target platforms, and set up a cross-compilation environment.'
+ },
+ },
+ {
+ label: 'Set up Pyodide xbuildenv',
+ platforms: ['pyodide'],
+ style: 'block',
+ tooltip: {
+ description: 'Install a base Python, set up a build virtualenv with pyodide-build, install the Pyodide cross-build environment and Emscripten toolchain.'
+ },
+ },
],
[
{
href: 'options/#before-build',
- platforms: ['linux', 'macos', 'windows'],
+ platforms: ['linux', 'macos', 'windows', 'android', 'ios', 'pyodide'],
style: 'dot',
tooltip: {
title: 'CIBW_BEFORE_BUILD',
@@ -121,12 +146,12 @@
{
label: 'Build wheel',
href: 'options/#build-frontend',
- platforms: ['linux', 'macos', 'windows'],
+ platforms: ['linux', 'macos', 'windows', 'android', 'ios', 'pyodide'],
style: 'block',
tooltip: {
title: 'CIBW_BUILD_FRONTEND',
tag: 'Customisable step',
- description: 'Build the wheel according to your package configuration, using the frontend of your choice - pip or build.'
+ description: 'Build the wheel according to your package configuration, using the frontend of your choice – pip, build, or uv.'
},
},
],
@@ -154,23 +179,31 @@
},
},
{
- env: "CIBW_REPAIR_WHEEL_COMMAND",
+ label: 'Repair wheel',
href: 'options/#repair-wheel-command',
- label: 'repair wheel',
- platforms: ['windows'],
+ platforms: ['android'],
+ style: 'block',
+ tooltip: {
+ title: 'CIBW_REPAIR_WHEEL_COMMAND',
+ tag: 'Customisable step',
+ description: 'By default, bundles libc++ into the wheel if any shared library links against it, using patchelf. Can be overridden with a custom repair command.'
+ },
+ },
+ {
+ href: 'options/#repair-wheel-command',
+ platforms: ['windows', 'ios', 'pyodide'],
style: 'dot',
- optional: true,
tooltip: {
title: 'CIBW_REPAIR_WHEEL_COMMAND',
tag: 'Optional step',
- description: 'Execute a shell command to repair each built wheel'
+ description: 'Execute a shell command to repair each built wheel.'
},
},
],
[
{
href: 'options/#before-test',
- platforms: ['linux', 'macos', 'windows'],
+ platforms: ['linux', 'macos', 'windows', 'android', 'ios', 'pyodide'],
style: 'dot',
tooltip: {
title: 'CIBW_BEFORE_TEST',
@@ -182,10 +215,10 @@
[
{
label: 'Install wheel',
- platforms: ['linux', 'macos', 'windows'],
+ platforms: ['linux', 'macos', 'windows', 'android', 'ios', 'pyodide'],
style: 'block',
tooltip: {
- description: 'Install the wheel we just built into the test virtualenv.'
+ description: 'Install the wheel we just built into the test environment.'
},
},
],
@@ -198,7 +231,40 @@
tooltip: {
title: 'CIBW_TEST_COMMAND',
tag: 'Optional step',
- description: 'Execute a shell command to test each built wheel'
+ description: 'Execute a shell command to test each built wheel.'
+ },
+ },
+ {
+ label: 'Test on emulator',
+ href: 'options/#test-command',
+ platforms: ['android'],
+ style: 'block',
+ tooltip: {
+ title: 'CIBW_TEST_COMMAND',
+ tag: 'Optional step',
+ description: 'Run the test command on an Android emulator using the CPython testbed.'
+ },
+ },
+ {
+ label: 'Test on simulator',
+ href: 'options/#test-command',
+ platforms: ['ios'],
+ style: 'block',
+ tooltip: {
+ title: 'CIBW_TEST_COMMAND',
+ tag: 'Optional step',
+ description: 'Run the test command on an iOS simulator using the testbed app.'
+ },
+ },
+ {
+ label: 'Test in Node.js',
+ href: 'options/#test-command',
+ platforms: ['pyodide'],
+ style: 'block',
+ tooltip: {
+ title: 'CIBW_TEST_COMMAND',
+ tag: 'Optional step',
+ description: 'Run the test command in a Pyodide virtualenv powered by Node.js.'
},
},
],
@@ -219,26 +285,21 @@
data() {
return {
diagram,
- platforms: ['linux', 'macos', 'windows'],
+ platforms: ['linux', 'macos', 'windows', 'android', 'ios', 'pyodide'],
}
},
methods: {
blockStyle(action) {
- let start, end
- if (action.platforms.includes('linux')) {
- start = 3
- } else if (action.platforms.includes('macos')) {
- start = 4
- } else if (action.platforms.includes('windows')) {
- start = 5
- }
+ const platformOrder = ['linux', 'macos', 'windows', 'android', 'ios', 'pyodide']
+ const rowOffset = 3 // first platform starts at grid row 3
- if (action.platforms.includes('windows')) {
- end = 6
- } else if (action.platforms.includes('macos')) {
- end = 5
- } else if (action.platforms.includes('linux')) {
- end = 4
+ let start = null
+ let end = null
+ for (let i = 0; i < platformOrder.length; i++) {
+ if (action.platforms.includes(platformOrder[i])) {
+ if (start === null) start = rowOffset + i
+ end = rowOffset + i + 1
+ }
}
return {
@@ -413,7 +474,7 @@
.grid-outline {
grid-row-end: span 1;
position: relative;
- color: #8f8f8f;
+ color: #666666;
}
.grid-outline.docker {
grid-row: 3 / span 1;
@@ -478,7 +539,7 @@
font-weight: 500;
text-transform: uppercase;
font-size: 0.9em;
- color: #C9C9C9;
+ color: #888888;
}
.tooltip-description {
margin-top: 1px;
diff --git a/noxfile.py b/noxfile.py
index 798a3f8f..53530de4 100755
--- a/noxfile.py
+++ b/noxfile.py
@@ -184,6 +184,18 @@ def docs(session: nox.Session) -> None:
session.run("mkdocs", "serve" if session.interactive else "build", "--strict", *session.posargs)
+@nox.session(default=False)
+def update_how_it_works_image(session: nox.Session) -> None:
+ """
+ Generate the how it works image.
+ """
+ pyproject = nox.project.load_toml()
+ session.install("-e.", *nox.project.dependency_groups(pyproject, "docs"))
+ session.install("playwright")
+ session.run("playwright", "install", "chromium")
+ session.run("python", "bin/update_how_it_works_image.py")
+
+
@nox.session(default=False)
def build(session: nox.Session) -> None:
"""