feat: jupyter example (#10)

Add a Python getting-started Jupyter notebook and reorganize the Python examples under examples/python/.

- examples/python/getting_started.ipynb: add notebook demonstrating the single-threaded tick loop (`spawn`/`send`/`tick`/`inbox`/`try_recv`) and the multi-threaded path via `RuntimeConfig` + `rt.run()`/`handle.shutdown()`
- examples/: relocate `hello_async.py` and `hello_single_thread.py` under `examples/python/`
- pyproject.toml: add a `dev` dependency group containing jupyter and ipykernel
- uv.lock: regenerate the lockfile for the new dev dependencies (2452 lines)

Signed-off-by: Zachery Aaron Shores-Chmielewski <zacheryasc@gmail.com>
This commit is contained in:
zacheryasc 2026-02-06 14:04:48 +00:00
parent 2fd0c412e0
commit fc8e766bd3
6 changed files with 2651 additions and 0 deletions

View file

@ -0,0 +1,98 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Swactor — Getting Started\n",
"\n",
"This notebook walks through the basics of the swactor actor runtime from Python."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from swactor import Runtime"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Single-threaded: spawn, send, tick\n",
"\n",
"The simplest way to use swactor is with `tick()` — manually stepping the runtime one tick at a time."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def echo(ctx, msg):\n",
" ctx.send(msg[\"reply_to\"], f\"hello, {msg['name']}!\")\n",
"\n",
"rt = Runtime()\n",
"addr = rt.spawn(echo)\n",
"inbox = rt.inbox()\n",
"\n",
"rt.send(addr, {\"name\": \"world\", \"reply_to\": inbox.addr})\n",
"rt.tick()\n",
"\n",
"print(inbox.try_recv())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Multi-threaded: background runtime\n",
"\n",
"For real workloads you can run the runtime on background threads with `RuntimeConfig`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import time\n",
"from swactor import Runtime, RuntimeConfig\n",
"\n",
"def echo(ctx, msg):\n",
" ctx.send(msg[\"reply_to\"], f\"hello, {msg['name']}!\")\n",
"\n",
"rt = Runtime(RuntimeConfig(num_threads=2))\n",
"addr = rt.spawn(echo)\n",
"inbox = rt.inbox()\n",
"handle = rt.run()\n",
"\n",
"for name in [\"alice\", \"bob\", \"charlie\"]:\n",
" handle.send(addr, {\"name\": name, \"reply_to\": inbox.addr})\n",
" time.sleep(0.05) # give the runtime a moment\n",
" print(inbox.try_recv())\n",
"\n",
"handle.shutdown()\n",
"handle.join()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"name": "python",
"version": "3.9.0"
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View file

@ -0,0 +1,98 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Swactor — Getting Started\n",
"\n",
"This notebook walks through the basics of the swactor actor runtime from Python."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from swactor import Runtime"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Single-threaded: spawn, send, tick\n",
"\n",
"The simplest way to use swactor is with `tick()` — manually stepping the runtime one tick at a time."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def echo(ctx, msg):\n",
" ctx.send(msg[\"reply_to\"], f\"hello, {msg['name']}!\")\n",
"\n",
"rt = Runtime()\n",
"addr = rt.spawn(echo)\n",
"inbox = rt.inbox()\n",
"\n",
"rt.send(addr, {\"name\": \"world\", \"reply_to\": inbox.addr})\n",
"rt.tick()\n",
"\n",
"print(inbox.try_recv())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Multi-threaded: background runtime\n",
"\n",
"For real workloads you can run the runtime on background threads with `RuntimeConfig`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import time\n",
"from swactor import Runtime, RuntimeConfig\n",
"\n",
"def echo(ctx, msg):\n",
" ctx.send(msg[\"reply_to\"], f\"hello, {msg['name']}!\")\n",
"\n",
"rt = Runtime(RuntimeConfig(num_threads=2))\n",
"addr = rt.spawn(echo)\n",
"inbox = rt.inbox()\n",
"handle = rt.run()\n",
"\n",
"for name in [\"alice\", \"bob\", \"charlie\"]:\n",
" handle.send(addr, {\"name\": name, \"reply_to\": inbox.addr})\n",
" time.sleep(0.05) # give the runtime a moment\n",
" print(inbox.try_recv())\n",
"\n",
"handle.shutdown()\n",
"handle.join()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"name": "python",
"version": "3.9.0"
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View file

@ -7,5 +7,8 @@ name = "swactor"
version = "0.1.0"
requires-python = ">=3.9"
[dependency-groups]
dev = ["jupyter", "ipykernel"]
[tool.maturin]
features = ["python"]

2452
uv.lock

File diff suppressed because it is too large Load diff