Skip to main content

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, VERSION handshake with protocol pinning). The layer everything else is built on.

  • amipilot.model -- parses the TREE text format (identical to AmiInspect's own output, see server/WIRE.md) into Window/ Gadget dataclasses.

  • 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-2 ROLE=/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 set AmiPilotServer currently implements -- see server/README.md.

  • amipilot dump (amipilot.dump, wired up as the amipilot console script via pyproject.toml) -- the host half of "the inspector" (docs/implementation-plan.md): connects, prints a window's gadget tree (--format text, the same shape AmiInspect prints) 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 live tree() against a checked-in text snapshot, auto-creating it the first time and raising GoldenMismatch (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 -- see tests/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 of SCREENSHOT's "wire stays simple, host does the rendering" split: decodes a raw capture (classic planar or a genuine Picasso96 pixel format, including the 16-bit PC-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()'s on_progress parameter, amipilot.wire.OnProgress) -- a real SCREENSHOT over serial can take anywhere from seconds to several minutes (see userdocs/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 through Amipilot.screenshot()/fs_get(); amipilot.stderr_progress() is a ready-made "print a progress line" callback for the common case. Defaults to None everywhere -- 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 -- sends command verbatim to a MUI application's own ARexx port and returns its result text. A genuinely different mechanism from click()/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. See server/README.md's own section for the full design rationale and userdocs/ARexx-Reference.md#driving-mui-applications for the user-facing story.

  • Verified end to end against a real guest under Copperline (tests/copperline/run.sh's wire check, and amipilot dump run by hand against the same session): connect, handshake, TREE/TYPE/ GETTEXT/CLICK all 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, and quit genuinely closing the target's window, not just the wire round trip succeeding.

  • amipilot.pytest_plugin -- the pytest plugin (auto-registered via the pytest11 entry point once host/ is installed): the session-scoped amipilot fixture boots a Copperline config that already stages AmiPilotServer SERIAL (same S:User-Startup staging technique tests/copperline/run.sh uses), waits for the wire transport to answer, and hands the test a connected Amipilot. 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 the amipilot_config ini setting) -- unconfigured tests skip cleanly, the same "skip, don't fake a pass" contract make test-target uses 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 the amipilot_copperline_args ini setting for extra Copperline flags (model/chipset/chip/fast/etc. -- --config/--serial tcp/--control are 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)

Source distribution for amipilot 1.1.0
File Size Uploaded
amipilot-1.1.0.tar.gz 71.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for amipilot 1.1.0
File Interpreter ABI Platform
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 log

Release 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

Release history Release notifications | RSS feed

This release

1.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page