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: """