host
The host-side Python client for AmiPilot: talks server/WIRE.md's line
protocol over any byte-stream transport (a real serial cable, or
Copperline's [serial] mode = "tcp" bridge under an emulator; TCP
transport itself is phase 0.4).
Stdlib-only by design, matching the wire's own no-dependency spirit
(docs/implementation-plan.md, "Protocol and client") -- nothing here
needs installing beyond Python 3.9+.
Current state (1.1)
-
amipilot.wire--WireClient: transport-level framing (strict by-byte-count reads,VERSIONhandshake with protocol pinning). The layer everything else is built on. -
amipilot.model-- parses theTREEtext format (identical toAmiInspect's own output, seeserver/WIRE.md) intoWindow/Gadgetdataclasses. -
amipilot.client--Amipilot, the object API test code actually imports:tree(),click(),type(),get_text(),manifest(),drag(),wait_for(),launch(),wb_launch(),mui_command(), the file API (fs_list()/fs_get()/fs_put()etc.),window_move()/window_resize(),screenshot(),quit(), plus@name- and tier-2ROLE=/LABEL=/INDEX=-locator variants (click_by_name(),click_by_role(), etc.). Non-OK RCs raise typed exceptions (NotFound/CommandError/ActionFailed/Timeout) rather than requiring the caller to check codes by hand. Matches the verb setAmiPilotServercurrently implements -- seeserver/README.md. -
amipilot dump(amipilot.dump, wired up as theamipilotconsole script viapyproject.toml) -- the host half of "the inspector" (docs/implementation-plan.md): connects, prints a window's gadget tree (--format text, the same shapeAmiInspectprints) or quirk-profile-ready name suggestions (--format python). -
Golden-tree fixtures (
amipilot.golden, phase 0.5 --docs/implementation-plan.md's "Golden trees": "a saved dump doubles as a structural fixture"):assert_golden(window, path)compares a livetree()against a checked-in text snapshot, auto-creating it the first time and raisingGoldenMismatch(with a unified diff) on drift thereafter.amipilot dump <window> --golden PATH [--update-golden]is the CLI form of the same check --Amipilot.assert_tree_matches()is the one-liner for use inside a test. Locale matters here: the rendered text includes window/ screen titles verbatim, which a real (catalog-driven) application's own localization can change without any UI change at all -- seetests/copperline/README.md's "Golden-tree fixtures and Locale" section before treating a golden file as portable across machines with different Locale preferences. -
amipilot.screenshot(1.0) -- the host half ofSCREENSHOT's "wire stays simple, host does the rendering" split: decodes a raw capture (classic planar or a genuine Picasso96 pixel format, including the 16-bitPC-suffix byte-swap pitfall) and writes PNG and IFF ILBM, stdlib-only, no Pillow.Amipilot.screenshot()is the client entry point; the byte-exact decode/encode logic has its own unit tests against synthetic captures. -
Progress feedback for long transfers (
WireClient.command()'son_progressparameter,amipilot.wire.OnProgress) -- a realSCREENSHOTover serial can take anywhere from seconds to several minutes (seeuserdocs/Wire-Protocol.md's own transfer-time table) with zero feedback otherwise.on_progress(bytes_so_far, total_bytes)is called as a response payload streams in, threaded throughAmipilot.screenshot()/fs_get();amipilot.stderr_progress()is a ready-made "print a progress line" callback for the common case. Defaults toNoneeverywhere -- zero behavior change when unused. -
The MUI-ARexx bridge tier (phase 0.5 --
Amipilot.mui_command()):MUIREXX <app-base> [TIMEOUT=<n>] <command...>'s host wrapper -- sendscommandverbatim to a MUI application's own ARexx port and returns its result text. A genuinely different mechanism fromclick()/type()/get_text()(no structural walk), and an honest one: MUI's own built-in ARexx support is a small, universal command set (quit/hide/show/activate/deactivate/info/help), not a generic widget-value accessor -- confirmed live against AmigaOS 3.2's own MUI-Demo, which registers no application-specific commands at all. Seeserver/README.md's own section for the full design rationale anduserdocs/ARexx-Reference.md#driving-mui-applicationsfor the user-facing story. -
Verified end to end against a real guest under Copperline (
tests/copperline/run.sh's wire check, andamipilot dumprun by hand against the same session): connect, handshake,TREE/TYPE/GETTEXT/CLICKall round-trip correctly, RC-5 (not found) surfaces as a clean CLI error. The golden-tree check (run_golden_check) is verified the same way, against real checked-in golden files for both fixtures.mui_command()is verified live too (run_mui_check, skips cleanly when MUI isn't installed on the configured Workbench volume -- it's a third-party archive, not part of any standard install) against real MUI-Demo:info title, a not-found app base, an unrecognised command, andquitgenuinely closing the target's window, not just the wire round trip succeeding. -
amipilot.pytest_plugin-- the pytest plugin (auto-registered via thepytest11entry point oncehost/is installed): the session-scopedamipilotfixture boots a Copperline config that already stagesAmiPilotServer SERIAL(sameS:User-Startupstaging techniquetests/copperline/run.shuses), waits for the wire transport to answer, and hands the test a connectedAmipilot. This is phase 0.3's actual release gate: "a host pytest clicks a button and asserts a label changed, deterministically, under the emulator." Options:--amipilot-config PATH(or theamipilot_configini setting) -- unconfigured tests skip cleanly, the same "skip, don't fake a pass" contractmake test-targetuses without a real Kickstart/Workbench asset.--amipilot-copperline/--amipilot-copperline-ctl(default from$COPPERLINE/$COPPERLINE_CTL, else the bare binary names),--amipilot-wire-port(default 1234),--amipilot-boot-timeout(default 60s), and theamipilot_copperline_argsini setting for extra Copperline flags (model/chipset/chip/fast/etc. ----config/--serial tcp/--controlare added automatically).def test_connect_click_asserts_label(amipilot): amipilot.type("GadTools", 2, "aminet.net") assert amipilot.get_text("GadTools", 2) == "aminet.net" amipilot.click("GadTools", 1)
Running the tests
python3 -m pytest tests -v # from this directory, or:
make test-host # from the repo root (installs host/[test] first)
The plugin's own boot/skip logic is covered without a real emulator
(monkeypatched subprocesses, pytest's own pytester fixture driving
real sub-sessions); tests/copperline/run.sh additionally exercises it
live against a real guest under Copperline.
Installing (for amipilot dump)
pip install -e host/
amipilot dump "My Window Title"
Metadata
Release files for amipilot 1.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| amipilot-1.1.0.tar.gz | 71.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| amipilot-1.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 123.2 kB
Release files / amipilot-1.1.0.tar.gz
| Download URL | amipilot-1.1.0.tar.gz |
|---|---|
| Size | 71.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4b933ba819ce8c059194a3aa1b1c4a97eb9d9b20a37c46f93fcb44f3e91cbfae
|
|
BLAKE2b-256 checksum How to use checksums |
297c9a2cd877b5d2a55b58628178b43cbc51c2599dd079ff7efe2603092b18e2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 10, 2026.
Transparency logRelease files / amipilot-1.1.0-py3-none-any.whl
| Download URL | amipilot-1.1.0-py3-none-any.whl |
|---|---|
| Size | 52.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
aaa630ed26036ffc59282c1b0962f56b7e0d684db9a3dd8b493c2677cb33e4d2
|
|
BLAKE2b-256 checksum How to use checksums |
c93e6ad785281399ff93c5f1da73e03cac532976ea13c4a60c34cc571d398618
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 10, 2026.
Transparency log