Skip to content
This repository was archived by the owner on Oct 28, 2026. It is now read-only.

Latest commit

 

History

History

tools

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

README.md

pydevices-examples tools/

Developer workflow only — local servers, test harnesses, and IDE typings. For repo maintenance see scripts/README.md.

PyScript / Jupyter launchers

Script Purpose
serve.py HTTP server with Cross-Origin-Isolation headers
pyscript.py Universal PyScript runner (on PATH from pydevices/bin) — pyscript.py -m bouncing_balls
jupyter.py Standalone Jupyter runner (on PATH from pydevices/bin) — jupyter.py paint.py

From repo root:

python3 -m venv .venv
.venv/bin/pip install -r requirements-dev.txt   # playwright, pytest (optional)
.venv/bin/playwright install chromium           # headless PyScript matrix

pyscript.py -m bouncing_balls
jupyter.py lib/examples/paint.py

See pydevices/docs/pyscript.md and pydevices/docs/jupyter.md.

Input / keypad probe

Script Purpose
lvgl_input_probe.py LVGL keypad-mapping diagnostic + selftests
micropython tools/lvgl_input_probe.py --selftest
cd lib && micropython ../tools/lvgl_input_probe.py   # interactive; focus the window

The core displaydev/appdev probe is owned by pydevices/tools/input_probe.py.

PyScript headless debug (Playwright)

Diagnostic probes (ps_debug.py and ps_shot.py) live in pydevices/tools/:

python ../pydevices/tools/ps_debug.py http://127.0.0.1:8000/pydevices-examples/pyscript/harness.html?modules=bouncing_balls
python ../pydevices/tools/ps_shot.py http://127.0.0.1:8000/pydevices-examples/pyscript/harness.html?modules=bouncing_balls 3

Example test matrix

Source of truth for the cross-interpreter example test system: this section (workflow), example_interpreters.toml (interpreter command templates), and example_test_manifest.toml (per-example metadata). Platform is the product category (see pydevices/docs/displaydev.md); interpreter is the concrete launcher used in automation.

Script Purpose
example_test_kit.py Cross-interpreter example matrix
example_test_manifest.toml Per-example metadata
example_interpreters.toml Interpreter command templates
sibling_repos.py Discover sibling lib/ paths for matrix runs

Unit tests first (default gate)

.venv/bin/python -m unittest discover -s tests

Preferred method (parallel interpreters, fail-fast)

For thorough verification (timer/multimer/interpreter changes, or "run the full matrix"), prefer example-by-example, all selected interpreters in parallel per example (--jobs 0, default) and --fail-fast. There is one timer mode: multimer delivers on every host by itself, so the old sync/async split (PYDEVICES_TIMER_ASYNC) is gone; the kit still accepts the variable and ignores it.

Interpreters
7 — desktop SDL: micropython, micropython.exe, circuitpython, cpython-venv, python.exe; plus pyscript, jupyter
Android (opt-in)

Default timing is already short (duration_s=2, timeout_s=15 in the interpreters/manifest defaults). After each example's parallel wave finishes, if any cell failed, stop before the next example; fix the root cause, then resume.

# PyScript needs the static server
python tools/serve.py   # separate terminal; reuse if already on :8000

export SDL_VIDEODRIVER=dummy SDL_AUDIODRIVER=dummy PYTHONUNBUFFERED=1
mkdir -p /tmp/pydevices-examples-matrix

RT="micropython micropython.exe circuitpython cpython-venv python.exe pyscript jupyter"

set -o pipefail   # keep kit exit status through tee

stdbuf -oL -eL \
  .venv/bin/python tools/example_test_kit.py --no-unit-tests --fail-fast \
  --only-interpreter $RT \
  --results-json /tmp/pydevices-examples-matrix/all.json \
  2>&1 | stdbuf -oL -eL tee /tmp/pydevices-examples-matrix/all.log

Unix subprocesses see that shell export. Windows .exe behavior is different — see Windows PE under WSL.

Windows PE under WSL

micropython.exe and python.exe are Windows PE binaries launched from WSL. They cannot read Linux-exported environment variables. The kit therefore forwards only values that must cross that boundary via wrapper argv + boarddev.env_set (notably --timer-async / --multimer-source).

Do not forward SDL_VIDEODRIVER / SDL_AUDIODRIVER to PE. Unix cells stay headless from the shell SDL_*=dummy export; PE keeps a real Windows video driver. During a matrix run you should see micropython.exe / python.exe windows — that means the cell started and is usable. Forwarding dummy into PE hides those windows.

summary: hang on PE is usually a quit failure, not a dead process. If the Windows window stays up past duration_s / until the kit timeout_s, the example is still running (you can interact with it); the harness timed out waiting for cooperative quit / EXAMPLE_RESULT. PE child output is captured via temp files so a timeout kill does not wipe stdout the way pipes often did. Fix the quit path (wrapper deadline / pydevices_test_mode / inject) rather than treating PE as “failed to launch.”

From native Windows. The kit also runs from PowerShell with python.org's Python (3.11 or newer, for tomllib): it finds micropython.exe on PATH, and nothing in its launch path needs WSL. With an exe built by micropython-pydevices (--port windows --variant pydevices --modules all):

$env:PATH = "<micropython-pydevices>\builds\windows\pydevices;$env:PATH"
python tools/example_test_kit.py --no-unit-tests --only-interpreter micropython.exe

The exe has no threads, so the wrapper quits LVGL examples with a multimer one-shot timer (pydevices_test_mode.arm_quit_timer()); the deadline hook alone never fires there.

Scheduling: with --order examples and --jobs 0 (default), all selected interpreters for an example — including both .exe launchers — run concurrently.

Results: live Running <example> @ <interpreter>... lines on stderr; summary table at end (or when --fail-fast stops). Full JSON defaults to the system temp dir (example_test_results.json), not a path under the repo. Override with --results-json PATH.

Real X display: DISPLAY=:1 (xfce) without dummy SDL opens a window titled "<impl> on <platform>". Optional: xvfb-run -a … (no SDL_VIDEODRIVER=dummy) for a real X11/SDL path without :1. Do not require Xvfb in the tools scripts; wrap when useful. PyScript/Playwright does not need Xvfb.

Interpreters and binaries

Desktop matrices use repo .venv (cpython-venv) plus interpreters on PATH / ~/bin (micropython, circuitpython). micropython.exe / python.exe are Windows binaries and cannot run in a Linux cloud sandbox.

After changes to the C modules these binaries or the PyScript runtime carry, rebuild them with micropython-pydevices' build_mp.py: for example ./build_mp.py --port unix --variant pydevices --modules all, and --port webassembly for the PyScript runtime.

micropython.exe matrix: no threading / _thread. The example wrapper uses a appdev.App.poll deadline quit (not a multimer SDL quit timer). With pydevices_test_mode.ENABLED, appdev.App skips auto-refresh wiring so examples that call show() themselves avoid a competing SDL refresh timer. WSL PE scheduling and SDL env rules: Windows PE under WSL.

Sibling pure-Python repos

Examples that import palettes / pdwidgets / pygraphics / the ctypes usdl2 fallback need those sibling lib/ dirs on path. The PyPI project literally named palettes is unrelated — do not pip install palettes. Prefer TestPyPI native builds for pygraphics and usdl2 when available.

Quick setup: bash scripts/setup_sibling_repos.sh (clones current main, writes .pth files). The harness auto-discovers the same paths via sibling_repos.py. pdwidgets also needs pydevices's lib on path (the harness adds it).

Known pre-existing failures (not environment bugs)

  • tools/png_test.py in pdwidgets (PNG probe) needs PDWIDGETS_PNG_DIR / material-design-icons and a sibling pydevices-examples checkout.

PyScript matrix

Start or reuse python tools/serve.py, then re-run with --only-interpreter pyscript. Headless needs Playwright (.venv/bin/pip install -r requirements-dev.txt and .venv/bin/playwright install chromium). Without it, pyscript cells report needs_playwright (not a hard failure). Troubleshooting hangs / CDP: PyScript headless debug above.

LVGL / timer harnesses

Script Purpose
run_desktop_lv_tests.py LVGL desktop matrix (sync/async, strict clicks)
lv_timer_test_kit.py Full LVGL timer matrix (sync/async, all interpreters)
run_test_timers.py Run the sibling core multimer timer probe across desktop interpreters
multimer_source_preload.py Force one multimer wake source, then run a script

Comparing multimer wake sources: lv_timer_test_kit.py --source NAME (or example_test_kit.py with MULTIMER_SOURCE set, which forwards --multimer-source to the wrapper). Both set MULTIMER_SOURCE inside the child and make multimer choose its source before the script runs, so they also work for the Windows .exe interpreters, which cannot read WSL-exported env vars. An interpreter that can't start that source reports unavailable and doesn't fail the run. MULTIMER_BACKEND is retired: the kit refuses to run with it set. The sources, and which host uses which, are in pydevices' multimer hosts table.

TestPyPI package smoke tests are owned by the repositories that publish the packages: core checks live in pydevices/tools/test_testpypi_standalone.sh, and pygraphics has its own standalone wheel check.

Other dev aids

Script Purpose
quit_inject.py Inject quit into running examples (used by the example harness)
pydevices_test_mode.py Test-mode env for examples
test_gallery_audio.py Load the audio cards (Audio Arpeggio, Piano, Drum Machine, Audiolive Rack) on the direct-WebAssembly gallery in headless Chromium, click as a visitor would, and assert non-silent audio reaches Web Audio
screenshot.py Run a desktop example and save its SDL2/pygame-ce window as PNG
record.py Run a desktop example and record its SDL2/pygame-ce window with FFmpeg
typings/ MicroPython stdlib stubs + core package .pyi (see below)
python tools/screenshot.py hello.py
python tools/screenshot.py bouncing_balls 3
python tools/screenshot.py logo --delay 2 --resolution 320x240 --scale 1

Without --output, screenshots are saved as docs/screenshots/EXAMPLE_NAME.png.

python tools/record.py bouncing_balls
python tools/record.py bouncing_balls 10
python tools/record.py logo --duration 3 --fps 15 --resolution 320x240 --scale 1

Without --output, recordings are saved as docs/videos/EXAMPLE_NAME.mp4. Recording requires ffmpeg on PATH or the binary-bundled imageio-ffmpeg Python package.

IDE typings (tools/typings/)

stubPath for Pylance / pyright (.vscode/settings.json, pyrightconfig.json):

Content Source
MicroPython stdlib stubs committed under tools/typings/
displaydev / appdev / multimer / events / keys committed package trees / modules; regenerate with ../scripts/gen_package_pyi.sh
lvgl committed tools/typings/lvgl.pyi (from ../lvgl-bindings/generated/lvgl.pyi)

Confirm Python: Select Interpreter → .venv/bin/python. Cursor uses cursorpyright with stubPath / typeshedPaths → tools/typings (configured in a local .vscode/settings.json when present).