Quick start¶
Requirements¶
KlorPy is a single Python package (stdlib + asyncio only), Python ≥ 3.11.
$ cd prototype/python
$ python -m venv .venv && . .venv/bin/activate
$ pip install -e . # klorpy + pytest
Your first choreography¶
Roles are plain objects (A, B, C, …). A choreography is an ordinary
function decorated with @choreography:
from klorpy import A, B, choreography, move, simulate_chor
@choreography
def ping_pong(x):
y = move(x, A, B) # send x from A to B; the result lives at B
return y
result = simulate_chor(ping_pong, {"x": 42})
assert result == {"A": NOOP, "B": 42}
What just happened:
@choreographyread the function's source, analyzed every value's location (here:xis available to both roles,yonly toB),- projected it into one small program per role:
Asendsx,Breceives it and reports the result, and simulate_chorran both projections concurrently, bridged by in-memory queues, and gathered each role's result. Roles with no result getNOOP.
The special operators¶
| Form | Meaning |
|---|---|
A(x) / lift(x, A) |
lift an expression to a role |
copy(x, A, B) |
communicate x A → B; result at {A, B} |
move(x, A, B) |
A → B; result at {B} |
narrow(x, {A}) |
restrict location to {A} |
pack(a, b) / unpack([x, y], t) |
build / destructure tuple values |
if / match / while |
choreographic control flow (see the language pages) |
These special operators are recognized statically from the source — they
never run. Using one outside a @choreography function raises a clear error.
Play one role¶
For a real deployment you run each role separately, against a transport you provide:
from klorpy import play_role
config = {
"role": B.name,
"send": send_fn, # async (loc, value) -> None
"recv": recv_fn, # async (loc) -> value
"locators": {A.name: "...address of A..."},
}
play_role(config, ping_pong, {"x": 99})
The ping_pong role A returns NOOP; role B returns 99.
Run over real TCP¶
See Networking (TCP) for the bundled TcpTransport and a
two-process demo.
Run the examples¶
$ python examples.py # one-process showcase
$ python examples_network.py # A and B in two OS processes over TCP
$ python -m pytest tests/ # the test suite (47 tests)
Failure mode
Everything here validates at definition time. A mistyped choreography
(a value used where it isn't located, a guard that only one role can see, a
tuple moved across roles, …) raises ProjectionError the moment the
decorator runs — never at runtime.