Skip to content

Commit de6af80

Browse files
committed
Add Python demo suite with docs and helper tests
1 parent f188107 commit de6af80

15 files changed

+1018
-0
lines changed

README.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,31 @@ with PyritoneClient() as client:
3232
print(client.execute("goto 100 70 100"))
3333
```
3434

35+
## Demos / Videos
36+
37+
Beginner-friendly demo scripts live in `python/demos/`.
38+
39+
- Demo index: `python/demos/README.md`
40+
- Fast start from repo root:
41+
42+
```bash
43+
python -m pip install -e ./python
44+
cd python
45+
python demos/01_connect_discovery.py
46+
```
47+
48+
- Suggested recording set includes:
49+
- connect/discovery
50+
- basic commands
51+
- goto + completion
52+
- live event feed
53+
- cancel flow
54+
- settings mode switch
55+
- interactive mini console
56+
- async workflow
57+
- local-path build helper
58+
- CLI entrypoints
59+
3560
## One-Click Dev Client
3661

3762
- Double-click `run_dev_client.bat` at repo root, or run it in terminal:

python/README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,22 @@ async def main() -> None:
4040
asyncio.run(main())
4141
```
4242

43+
## Demos
44+
45+
The quick examples above are intentionally small.
46+
47+
For full, recordable feature walkthroughs, see:
48+
49+
- `python/demos/README.md`
50+
51+
Run from repo root:
52+
53+
```bash
54+
python -m pip install -e ./python
55+
cd python
56+
python demos/01_connect_discovery.py
57+
```
58+
4359
## Docs
4460

4561
- Full docs index: `python/docs/index.md`
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from __future__ import annotations
2+
3+
from _common import print_json, run_sync_demo, step
4+
5+
6+
def demo(client):
7+
step("Using default discovery: bridge-info file or PYRITONE_* overrides.")
8+
print_json("ping()", client.ping())
9+
print_json("status_get()", client.status_get())
10+
return 0
11+
12+
13+
if __name__ == "__main__":
14+
raise SystemExit(run_sync_demo("01 - Connect + Discovery", demo))

python/demos/02_basic_commands.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
from __future__ import annotations
2+
3+
from _common import print_json, run_sync_demo, step, summarize_dispatch
4+
5+
6+
def demo(client):
7+
step("High-level wrappers first: help(), version(), set(...).")
8+
9+
help_dispatch = client.help()
10+
print(f"help() summary: {summarize_dispatch(help_dispatch)}")
11+
print_json("help()", help_dispatch)
12+
13+
version_dispatch = client.version()
14+
print(f"version() summary: {summarize_dispatch(version_dispatch)}")
15+
print_json("version()", version_dispatch)
16+
17+
set_dispatch = client.set("allowPlace", True)
18+
print(f"set('allowPlace', True) summary: {summarize_dispatch(set_dispatch)}")
19+
print_json("set('allowPlace', True)", set_dispatch)
20+
21+
step("Raw fallback: execute('help').")
22+
print_json("execute('help')", client.execute("help"))
23+
return 0
24+
25+
26+
if __name__ == "__main__":
27+
raise SystemExit(run_sync_demo("02 - Basic Commands", demo))

python/demos/03_goto_completion.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
from __future__ import annotations
2+
3+
import argparse
4+
5+
from _common import (
6+
print_json,
7+
run_sync_demo,
8+
step,
9+
summarize_dispatch,
10+
summarize_event,
11+
terminal_summary,
12+
)
13+
14+
15+
parser = argparse.ArgumentParser(description="Dispatch goto and wait for terminal task event")
16+
parser.add_argument("x", type=int, nargs="?", default=100)
17+
parser.add_argument("y", type=int, nargs="?", default=70)
18+
parser.add_argument("z", type=int, nargs="?", default=100)
19+
args = parser.parse_args()
20+
21+
22+
def demo(client):
23+
step(f"Dispatching goto({args.x}, {args.y}, {args.z})")
24+
dispatch = client.goto(args.x, args.y, args.z)
25+
print(f"goto dispatch summary: {summarize_dispatch(dispatch)}")
26+
print_json("goto dispatch", dispatch)
27+
28+
task_id = dispatch.get("task_id")
29+
if not task_id:
30+
step("No task_id was returned, so there is nothing to wait for.")
31+
return 0
32+
33+
step(f"Waiting for terminal event for task_id={task_id}")
34+
terminal_event = client.wait_for_task(task_id)
35+
print(f"terminal event summary: {summarize_event(terminal_event)}")
36+
print_json("terminal event", terminal_event)
37+
step(terminal_summary(terminal_event))
38+
return 0
39+
40+
41+
if __name__ == "__main__":
42+
raise SystemExit(run_sync_demo("03 - Goto + Completion", demo))

python/demos/04_live_event_feed.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
from __future__ import annotations
2+
3+
import argparse
4+
5+
from _common import print_json, run_sync_demo, step, summarize_event
6+
7+
8+
parser = argparse.ArgumentParser(description="Print live bridge events")
9+
parser.add_argument("--max-events", type=int, default=20, help="0 means unlimited")
10+
parser.add_argument("--timeout", type=float, default=5.0)
11+
parser.add_argument("--full-json", action="store_true")
12+
args = parser.parse_args()
13+
14+
15+
def demo(client):
16+
step(
17+
"Listening for bridge events. Trigger Baritone commands in-game or from other scripts. Press Ctrl+C to stop."
18+
)
19+
20+
seen = 0
21+
while args.max_events <= 0 or seen < args.max_events:
22+
try:
23+
event = client.next_event(timeout=args.timeout)
24+
except TimeoutError:
25+
step("No event arrived in the timeout window. Still listening...")
26+
continue
27+
28+
seen += 1
29+
print(f"event #{seen}: {summarize_event(event)}")
30+
if args.full_json:
31+
print_json("event payload", event)
32+
33+
step(f"Reached max-events={args.max_events}; exiting.")
34+
return 0
35+
36+
37+
if __name__ == "__main__":
38+
raise SystemExit(run_sync_demo("04 - Live Event Feed", demo))

python/demos/05_cancel_task.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
from __future__ import annotations
2+
3+
import argparse
4+
import time
5+
6+
from _common import (
7+
print_json,
8+
run_sync_demo,
9+
step,
10+
summarize_dispatch,
11+
summarize_event,
12+
terminal_summary,
13+
)
14+
15+
16+
parser = argparse.ArgumentParser(description="Start a task, cancel it, and inspect terminal state")
17+
parser.add_argument("--delay", type=float, default=1.5, help="Seconds to wait before cancel")
18+
args = parser.parse_args()
19+
20+
21+
def demo(client):
22+
step("Starting a long-running task with high-level wrapper: explore()")
23+
dispatch = client.explore()
24+
print(f"explore() dispatch summary: {summarize_dispatch(dispatch)}")
25+
print_json("explore() dispatch", dispatch)
26+
27+
task_id = dispatch.get("task_id")
28+
if not task_id:
29+
step("No task_id returned, cannot target a specific cancel. Sending global cancel instead.")
30+
print_json("cancel()", client.cancel())
31+
return 0
32+
33+
step(f"Waiting {args.delay:.1f}s before canceling task_id={task_id}")
34+
time.sleep(max(args.delay, 0.0))
35+
36+
cancel_result = client.cancel(task_id=task_id)
37+
print_json("cancel(task_id)", cancel_result)
38+
39+
step("Waiting for terminal task event after cancel")
40+
terminal_event = client.wait_for_task(task_id)
41+
print(f"terminal event summary: {summarize_event(terminal_event)}")
42+
print_json("terminal event", terminal_event)
43+
step(terminal_summary(terminal_event))
44+
return 0
45+
46+
47+
if __name__ == "__main__":
48+
raise SystemExit(run_sync_demo("05 - Cancel Task", demo))
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
from __future__ import annotations
2+
3+
import argparse
4+
5+
from _common import print_json, run_sync_demo, step
6+
from pyritone import BridgeError
7+
8+
9+
MODES: dict[str, dict[str, bool]] = {
10+
"builder": {
11+
"allowPlace": True,
12+
"allowSprint": True,
13+
},
14+
"careful": {
15+
"allowPlace": False,
16+
"allowSprint": False,
17+
},
18+
}
19+
20+
21+
parser = argparse.ArgumentParser(description="Show settings API and mode presets")
22+
parser.add_argument("--mode", choices=sorted(MODES.keys()), default="builder")
23+
args = parser.parse_args()
24+
25+
26+
def _apply_mode(client, mode_name: str) -> None:
27+
mode = MODES[mode_name]
28+
step(f"Applying mode '{mode_name}' with {len(mode)} settings")
29+
30+
for setting_name, value in mode.items():
31+
try:
32+
dispatch = client.settings.set(setting_name, value)
33+
print_json(f"set {setting_name} {value}", dispatch)
34+
except BridgeError as error:
35+
print(
36+
f"[warn] Could not set {setting_name!r}: {error.code} - {error.message}. "
37+
"Continuing with remaining settings."
38+
)
39+
40+
41+
def demo(client):
42+
step("Property assignment style (sync): client.settings.allowPlace = True")
43+
client.settings.allowPlace = True
44+
if client.settings.last_dispatch is not None:
45+
print_json("last_dispatch", client.settings.last_dispatch)
46+
47+
step("Handle methods: get/toggle/reset")
48+
print_json("allowPlace.get()", client.settings.allowPlace.get())
49+
print_json("allowPlace.toggle()", client.settings.allowPlace.toggle())
50+
print_json("allowPlace.reset()", client.settings.allowPlace.reset())
51+
52+
_apply_mode(client, args.mode)
53+
54+
step("Final checks")
55+
print_json("allowPlace.get()", client.settings.allowPlace.get())
56+
print_json("allowSprint.get()", client.settings.allowSprint.get())
57+
return 0
58+
59+
60+
if __name__ == "__main__":
61+
raise SystemExit(run_sync_demo("06 - Settings Mode Switch", demo))

0 commit comments

Comments
 (0)