docs: update "How it works" diagram with details of Android, iOS, and Pyodide builds (#2816)

* Update diagram with details of Android, iOS, and Pyodide builds

* Update diagram as well

* Simplify

Co-Authored-By: Malcolm Smith <smith@chaquo.com>

* Improve WCAG for some text elements

* Update diagram snapshot

* Modernise image generation script and rerun

---------

Co-authored-by: Malcolm Smith <smith@chaquo.com>
Co-authored-by: Joe Rickerby <joerick@mac.com>
This commit is contained in:
Agriya Khetarpal
2026-04-10 13:09:28 -04:00
committed by GitHub
co-authored by Malcolm Smith Joe Rickerby
parent a42e5d3563
commit 1d5d9be23f
4 changed files with 141 additions and 60 deletions
+38 -30
View File
@@ -1,49 +1,57 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import subprocess import subprocess
import sys import tempfile
from pathlib import Path from pathlib import Path
try: try:
from html2image import Html2Image # type: ignore[import-not-found] from playwright.sync_api import sync_playwright # type: ignore[import-not-found]
except ImportError: 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 raise SystemExit(msg) from None
Chromium (on Linux) installed, and then do:
pip install html2image
"""
)
def main() -> 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"""
<style>{(tmp_dir / "css/theme.css").read_text()}</style>
<style>{(tmp_dir / "css/theme_extra.css").read_text()}</style>
<style>{(tmp_dir / "extra.css").read_text()}</style>
<style>
body {{
background: white;
}}
</style>
"""
html_str = f"<html><head>{css_tags}</head><body>{html_str}</body></html>"
html_str = Path("docs/diagram.md").read_text() html_path = Path(tmp_dir) / "diagram_screenshot.html"
css_tags = f""" html_path.write_text(html_str)
<style>{Path("site/css/theme.css").read_text()}</style>
<style>{Path("site/css/theme_extra.css").read_text()}</style>
<style>{Path("site/extra.css").read_text()}</style>
<style>
body {{
background: white;
}}
</style>
"""
html_str = css_tags + html_str
[screenshot, *_] = hti.screenshot( dest_path = Path("docs/data/how-it-works.png")
html_str=html_str,
size=(830, 405),
)
dest_path = Path("docs/data/how-it-works.png") with sync_playwright() as p:
dest_path.unlink(missing_ok=True) 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__": if __name__ == "__main__":
Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 91 KiB

+91 -30
View File
@@ -5,6 +5,9 @@
<div class="grid-line" style="grid-row-start: 3"></div> <div class="grid-line" style="grid-row-start: 3"></div>
<div class="grid-line" style="grid-row-start: 4"></div> <div class="grid-line" style="grid-row-start: 4"></div>
<div class="grid-line" style="grid-row-start: 5"></div> <div class="grid-line" style="grid-row-start: 5"></div>
<div class="grid-line" style="grid-row-start: 6"></div>
<div class="grid-line" style="grid-row-start: 7"></div>
<div class="grid-line" style="grid-row-start: 8"></div>
<!-- the docker container outline --> <!-- the docker container outline -->
<div class="grid-outline docker"> <div class="grid-outline docker">
<div class="outline"> <div class="outline">
@@ -17,11 +20,17 @@
</div> </div>
<div class="grid-outline testVenv" style="grid-row-start: 4"><div class="outline"></div></div> <div class="grid-outline testVenv" style="grid-row-start: 4"><div class="outline"></div></div>
<div class="grid-outline testVenv" style="grid-row-start: 5"><div class="outline"></div></div> <div class="grid-outline testVenv" style="grid-row-start: 5"><div class="outline"></div></div>
<div class="grid-outline testVenv" style="grid-row-start: 6"><div class="outline"></div></div>
<div class="grid-outline testVenv" style="grid-row-start: 7"><div class="outline"></div></div>
<div class="grid-outline testVenv" style="grid-row-start: 8"><div class="outline"></div></div>
<!-- THE GRID CONTENT --> <!-- THE GRID CONTENT -->
<!-- the row labels --> <!-- the row labels -->
<div class="grid-row-label" style="grid-row-start: 3">Linux</div> <div class="grid-row-label" style="grid-row-start: 3">Linux</div>
<div class="grid-row-label" style="grid-row-start: 4">macOS</div> <div class="grid-row-label" style="grid-row-start: 4">macOS</div>
<div class="grid-row-label" style="grid-row-start: 5">Windows</div> <div class="grid-row-label" style="grid-row-start: 5">Windows</div>
<div class="grid-row-label" style="grid-row-start: 6">Android</div>
<div class="grid-row-label" style="grid-row-start: 7">iOS</div>
<div class="grid-row-label" style="grid-row-start: 8">Pyodide</div>
<!-- the column labels --> <!-- the column labels -->
<div class="grid-column-label" <div class="grid-column-label"
style="grid-row: 1 / span 1; grid-column: 5 / -3"> style="grid-row: 1 / span 1; grid-column: 5 / -3">
@@ -86,7 +95,7 @@
[ [
{ {
href: 'options/#before-all', href: 'options/#before-all',
platforms: ['linux', 'macos', 'windows'], platforms: ['linux', 'macos', 'windows', 'android', 'ios', 'pyodide'],
style: 'dot', style: 'dot',
tooltip: { tooltip: {
title: 'CIBW_BEFORE_ALL', title: 'CIBW_BEFORE_ALL',
@@ -104,11 +113,27 @@
description: 'Install the version of Python required to build this wheel.' 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', href: 'options/#before-build',
platforms: ['linux', 'macos', 'windows'], platforms: ['linux', 'macos', 'windows', 'android', 'ios', 'pyodide'],
style: 'dot', style: 'dot',
tooltip: { tooltip: {
title: 'CIBW_BEFORE_BUILD', title: 'CIBW_BEFORE_BUILD',
@@ -121,12 +146,12 @@
{ {
label: 'Build wheel', label: 'Build wheel',
href: 'options/#build-frontend', href: 'options/#build-frontend',
platforms: ['linux', 'macos', 'windows'], platforms: ['linux', 'macos', 'windows', 'android', 'ios', 'pyodide'],
style: 'block', style: 'block',
tooltip: { tooltip: {
title: 'CIBW_BUILD_FRONTEND', title: 'CIBW_BUILD_FRONTEND',
tag: 'Customisable step', 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', href: 'options/#repair-wheel-command',
label: 'repair wheel', platforms: ['android'],
platforms: ['windows'], 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', style: 'dot',
optional: true,
tooltip: { tooltip: {
title: 'CIBW_REPAIR_WHEEL_COMMAND', title: 'CIBW_REPAIR_WHEEL_COMMAND',
tag: 'Optional step', 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', href: 'options/#before-test',
platforms: ['linux', 'macos', 'windows'], platforms: ['linux', 'macos', 'windows', 'android', 'ios', 'pyodide'],
style: 'dot', style: 'dot',
tooltip: { tooltip: {
title: 'CIBW_BEFORE_TEST', title: 'CIBW_BEFORE_TEST',
@@ -182,10 +215,10 @@
[ [
{ {
label: 'Install wheel', label: 'Install wheel',
platforms: ['linux', 'macos', 'windows'], platforms: ['linux', 'macos', 'windows', 'android', 'ios', 'pyodide'],
style: 'block', style: 'block',
tooltip: { 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: { tooltip: {
title: 'CIBW_TEST_COMMAND', title: 'CIBW_TEST_COMMAND',
tag: 'Optional step', 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() { data() {
return { return {
diagram, diagram,
platforms: ['linux', 'macos', 'windows'], platforms: ['linux', 'macos', 'windows', 'android', 'ios', 'pyodide'],
} }
}, },
methods: { methods: {
blockStyle(action) { blockStyle(action) {
let start, end const platformOrder = ['linux', 'macos', 'windows', 'android', 'ios', 'pyodide']
if (action.platforms.includes('linux')) { const rowOffset = 3 // first platform starts at grid row 3
start = 3
} else if (action.platforms.includes('macos')) {
start = 4
} else if (action.platforms.includes('windows')) {
start = 5
}
if (action.platforms.includes('windows')) { let start = null
end = 6 let end = null
} else if (action.platforms.includes('macos')) { for (let i = 0; i < platformOrder.length; i++) {
end = 5 if (action.platforms.includes(platformOrder[i])) {
} else if (action.platforms.includes('linux')) { if (start === null) start = rowOffset + i
end = 4 end = rowOffset + i + 1
}
} }
return { return {
@@ -413,7 +474,7 @@
.grid-outline { .grid-outline {
grid-row-end: span 1; grid-row-end: span 1;
position: relative; position: relative;
color: #8f8f8f; color: #666666;
} }
.grid-outline.docker { .grid-outline.docker {
grid-row: 3 / span 1; grid-row: 3 / span 1;
@@ -478,7 +539,7 @@
font-weight: 500; font-weight: 500;
text-transform: uppercase; text-transform: uppercase;
font-size: 0.9em; font-size: 0.9em;
color: #C9C9C9; color: #888888;
} }
.tooltip-description { .tooltip-description {
margin-top: 1px; margin-top: 1px;
+12
View File
@@ -184,6 +184,18 @@ def docs(session: nox.Session) -> None:
session.run("mkdocs", "serve" if session.interactive else "build", "--strict", *session.posargs) 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) @nox.session(default=False)
def build(session: nox.Session) -> None: def build(session: nox.Session) -> None:
""" """