Skip to main content

macula-py

CI License Python GitHub Sponsors

Macula

A Python node on the macula 12 mesh, over macula-go's C ABI


Status, 2026-09-26: on the macula 12 wire: ML-DSA-87 identities (as the ML-DSA-87 + RSA-PSS-4096 composite in pq_hybrid, the fleet's profile), ML-KEM hybrid key exchange, signed requests. Calls and streams by direct dial, serving (under an org or in a node's own namespace), publish/subscribe, the DHT and node-served content are tested against two in-process macula 12 stations on every CI run. 0.1.0 spoke the retired classical wire and cannot reach the current fleet.

What is this?

A Python SDK for the Macula mesh: a node's key, a pool of links to stations it pins by node_id, calls and streams that reach a provider by direct dial, serving procedures, publish/subscribe, the DHT and node-served content, all as asyncio coroutines.

Macula is a federated mesh for sovereign application networks. A station relays and holds the DHT; a node is anything else that joins, and this package is a node.

It is a binding, not a reimplementation. The protocol lives in macula-go, which exports it as a C ABI (cabi/macula.h, contract in cabi/CONTRACT.md) shared by every SDK not written in Go. macula-py loads that library with ctypes, so the wire, the post-quantum handshake and the signing rules are the ones macula-go already checks byte for byte against macula itself.

Install

pip install macula-py

Wheels exist for Linux x86-64 and arm64 (glibc 2.28 or later), macOS 13 or later on Apple silicon and Intel, and Windows x86-64. Each carries macula-go's library; nothing compiles at install time and there are no runtime Python dependencies. On any other platform pip finds no wheel.

Quick start

import asyncio

from macula_py import NodeKey, Pool, Seed

STATION = Seed("station-fi-helsinki.macula.io", 4433,
               "004d1f470097ccf8826ce291900e882fdb1f20375e53901facaec0f23eb4efd8")
REALM = "abb81b5a614b63551b400b810648c0c8a78efad845442630c94b46cc95d2fcd1"  # io.macula
REALM_KEY = "..."  # io.macula's public realm key, hex


async def main() -> None:
    key = await NodeKey.load_or_create("node.key")  # pq_hybrid; the puzzle takes a second
    async with await Pool.connect(key, [STATION], realm_trust={REALM: REALM_KEY}) as pool:
        print(await pool.call(REALM, "mcl-echo/echo", "hello"))


asyncio.run(main())

A seed is pinned: the station must prove the node_id you give. A realm's key decides which advertisements in it you trust; procedures in a node's own namespace (~<node_id>/<name>, see Pool.own_procedure) need none.

The API

NodeKey generate, load, load_or_create, save, node_id, public_key, profile, sign, verify, free
Pool.connect seeds, realm_trust, and the pool's tuning; async with closes it
calls call, providers
serving serve(realm, procedure, handler): handler(request) returns the result, directly or as an awaitable; an exception reaches the caller as a ProviderError of code handler_error
streams open_stream, serve_stream; a Stream has send, send_value, close_send, reply, abort, close, recv, and iterates its frames
pub/sub publish, subscribe; a Subscription iterates its events, or next(timeout_ms)
content share_content, unshare_content, get_content
DHT find_record, find_records, find_records_by_type, put_record

Payloads are what macula's wire carries: str, int within int64, float, None, bytes, lists and dicts with str keys. There is no boolean on the wire: send 1 and 0. A Python bool is refused before it leaves, since Python treats it as an int.

Every networked method is a coroutine, and each native call runs on a thread of its own, so long waits never starve other calls. The methods that take timeout_ms, and every wait for an event, a served call or a stream frame, carry a cancel token: cancelling the task (or asyncio.wait_for timing out) ends the native call at once. The rest (publish, subscribe, serve, stop, close, and a stream's sends and ends) are short native calls without one; cancelling stops the waiting and the call runs to its end.

Errors are typed: ProviderError, RelayError, StreamError, NotSharedError, ContentUnavailableError, MaculaTimeoutError (also a TimeoutError), InvalidArgumentError (also a ValueError), ClosedError, RefusedError, all MaculaError.

Development

Needs Go 1.27 and a C compiler to build macula-go's library locally.

python -m venv .venv && .venv/bin/pip install -e ".[dev]"
eval "$(scripts/build_native.sh)"   # the library and teststation, from abi/MACULA_GO_REF
.venv/bin/pytest

abi/macula.h is macula-go's header at the ref in abi/MACULA_GO_REF; tests/test_abi_declarations.py holds the ctypes declarations to it function for function, and build_native.sh refuses a header that differs from the ref's.

scripts/live_check.sh runs tests/live/ against one fleet station (helsinki and io.macula by default) with a key made for the run and never saved. It publishes once and puts nothing in the DHT. CI never runs it.

A v* tag publishes to PyPI through Trusted Publishing, using only macula-go's released libraries, each checked against the release's SHA256SUMS and its build provenance attestation.

License

Apache-2.0. See LICENSE.


Built on macula-go, for Python -- sponsor the work if this saved you some time

Release files for macula-py 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distributions (wheels)

Table of built distributions (wheels) for macula-py 0.2.0
File
macula_py-0.2.0-py3-none-win_amd64.whl Python 3 none Windows x86-64 Details
macula_py-0.2.0-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl Python 3 none Linux glibc 2.17+ ARM64, Linux glibc 2.28+ ARM64 Details
macula_py-0.2.0-py3-none-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl Python 3 none Linux glibc 2.5+ x86-64, Linux glibc 2.28+ x86-64 Details
macula_py-0.2.0-py3-none-macosx_13_0_x86_64.whl Python 3 none macOS 13.0+ x86-64 Details
macula_py-0.2.0-py3-none-macosx_13_0_arm64.whl Python 3 none macOS 13.0+ ARM64 Details

Total release size: 16.5 MB

Release files / macula_py-0.2.0-py3-none-win_amd64.whl

Download URL macula_py-0.2.0-py3-none-win_amd64.whl
Size 3.4 MB
Tags Python 3 Windows x86-64
SHA-256 checksum
How to use checksums
9215b5f9785f1914735956a4206940da5ab270d47920a21f212befcbe737a020
BLAKE2b-256 checksum
How to use checksums
c78d5baa3b2d6044d897d6057b9e633c610853bf64d43403708e539845361209
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 Sep 26, 2026.

Transparency log

Release files / macula_py-0.2.0-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl

Download URL macula_py-0.2.0-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
Size 3.1 MB
Tags Linux glibc 2.17+ ARM64 Linux glibc 2.28+ ARM64 Python 3
SHA-256 checksum
How to use checksums
46d6ebf68b7cbad3fad7830d1f351c2ae841b3d4491dd25f5505f41ca768a78f
BLAKE2b-256 checksum
How to use checksums
02f7304a9866432558ca0954840fc5809dfd89f224bb06682f5d820571944ed0
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 Sep 26, 2026.

Transparency log

Release files / macula_py-0.2.0-py3-none-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl

Download URL macula_py-0.2.0-py3-none-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
Size 3.5 MB
Tags Linux glibc 2.28+ x86-64 Linux glibc 2.5+ x86-64 Python 3
SHA-256 checksum
How to use checksums
fb69aaa69cbca52fe8dab8f1a0f3d23d783c7f71aca61c91ae3b0d858a99081e
BLAKE2b-256 checksum
How to use checksums
05563b0ad87a75be1c273c034dbb294e4cf9361f7e3a769755cf9f787ddd66a8
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 Sep 26, 2026.

Transparency log

Release files / macula_py-0.2.0-py3-none-macosx_13_0_x86_64.whl

Download URL macula_py-0.2.0-py3-none-macosx_13_0_x86_64.whl
Size 3.4 MB
Tags Python 3 macOS 13.0+ x86-64
SHA-256 checksum
How to use checksums
00906e9d24abd5aeea06a9c71bf526a4a1db98357af9c6bc393d7e9429ec7c4e
BLAKE2b-256 checksum
How to use checksums
e07ec5546867c7679ccde105ab936def6915bc6568771b8e5e2c9ed8ebeffab7
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 Sep 26, 2026.

Transparency log

Release files / macula_py-0.2.0-py3-none-macosx_13_0_arm64.whl

Download URL macula_py-0.2.0-py3-none-macosx_13_0_arm64.whl
Size 3.1 MB
Tags Python 3 macOS 13.0+ ARM64
SHA-256 checksum
How to use checksums
d4517bd7db927dfe046d1fcba96859692d9035e07014b78db15fe3ffb423a212
BLAKE2b-256 checksum
How to use checksums
8cec49530a00d976373ba975ae32c795bc86db8342cd283089cd100d7fe91041
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 Sep 26, 2026.

Transparency log

Release history Release notifications | RSS feed

0.3.0

5 release files

This release

0.2.0 This release

5 release files

0.1.0

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