Metadata-Version: 2.2
Name: pyaeron
Version: 0.1.0
Summary: CPython 3.12–3.15 bindings for the Aeron C client
Keywords: aeron,messaging,ipc,udp
Author: pyaeron contributors
License: Apache-2.0
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: C
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: Python :: 3.15
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Topic :: System :: Networking
Requires-Python: <3.16,>=3.12
Provides-Extra: test
Requires-Dist: pytest>=8; extra == "test"
Description-Content-Type: text/markdown

# pyaeron

CPython 3.12–3.15 bindings for the [Aeron](https://github.com/aeron-io/aeron) C
client. Implemented against the Python C API (no pybind11).

## Offer contract

```python
result = publication.offer(payload)
if result:                          # True — message was appended
    ...
elif result is pyaeron.BACK_PRESSURED:
    idle.idle()
elif result is pyaeron.NOT_CONNECTED:
    ...
# ADMIN_ACTION is also a falsy OfferCode (retry)
# PublicationClosed / MaxPositionExceeded are raised
```

`bool(BACK_PRESSURED)`, `bool(NOT_CONNECTED)`, and `bool(ADMIN_ACTION)` are
always `False`. Successful offers return Python `True` (the new stream position
is on `publication.last_position`).

## Zero copy

| payload | path |
|---|---|
| `bytes` | pointer into `ob_sval` |
| `bytearray` | pointer into the bytearray (`PyByteArray_AS_STRING`) |
| C-contiguous `memoryview` | pointer into the view (`PyMemoryView_GET_BUFFER`) |
| ASCII `str` | pointer into compact ASCII data (`PyUnicode_DATA`) |
| non-ASCII `str` | UTF-8 conversion (`PyUnicode_AsUTF8AndSize`, cached on the object) |
| other bytes-like (`array.array`, …) | PEP 3118 `PyObject_GetBuffer` |

## GIL

Idle strategies, `await_connected`, `add_publication` / `add_subscription`
driver waits, and driver/client start-stop drop the GIL. `offer` and `poll`
keep it: they are non-blocking shared-memory operations, and `poll` invokes a
Python fragment handler.

## Examples

Runnable scripts in [`examples/`](examples/):

```bash
python examples/01_ipc_producer_consumer.py   # 1 producer, 1 consumer (IPC)
python examples/02_ipc_multicast.py           # 1 producer, 2 consumers (IPC fan-out)
python examples/03_ipc_rpc.py                 # caller waits for a correlated response
python examples/04_offer_status.py            # True vs falsy OfferCode enums
python examples/05_polling.py                 # poll duty cycle, fragment_limit, assemble
python examples/06_channels.py                # Aeron URI construction and channel params
python examples/07_streams.py                 # same channel, two independent stream IDs
python examples/08_exclusive_publication.py   # 01 with add_exclusive_publication
python examples/09_buffer_protocol.py         # offer() buffer-protocol payloads
python examples/10_lifecycle.py               # full session: connect through close
python examples/11_images.py                  # two Images; poll one session
```

```python
import pyaeron

with pyaeron.Aeron(embedded=True) as aeron:
    sub = aeron.add_subscription(pyaeron.IPC_CHANNEL, 10)
    pub = aeron.add_publication(pyaeron.IPC_CHANNEL, 10)
    pub.await_connected()

    result = pub.offer(b"hello")
    if result is True:
        def on_fragment(buf, header):
            print(bytes(buf), header.session_id)
        sub.poll(on_fragment)
```

`embedded=True` launches an in-process C media driver in a unique temp
directory. Point `dir=` at an existing driver if you already run `aeronmd`.

`IPC_CHANNEL` is Aeron's URI `"aeron:ipc"` — shared-memory IPC on one
machine, [not a pyaeron invention](https://github.com/aeron-io/aeron/wiki/Channel-Configuration).

## Build

Requires CMake ≥ 3.30, a C11 compiler, and CPython 3.12–3.15.

```bash
git submodule update --init --recursive
pip install -e ".[test]"
pytest
```

Aeron itself is vendored as `third_party/aeron` (`https://github.com/aeron-io/aeron.git`).

## Benchmarks

One-in-flight RPC (ping/pong) latency for C vs Python and IPC vs localhost UDP:

```bash
python benchmarks/run.py --quick
python benchmarks/run.py --net 10g,100g --quick   # rain → butterfly, 10GbE and ConnectX-5 100GbE
```

See [`benchmarks/README.md`](benchmarks/README.md).
