Skip to main content

Add your description here

Project description

SpiriSynq

SpiriSynq keeps Python dataclass instances in sync across processes, machines, and languages over a Zenoh pub/sub network. Define a typed dataclass, point multiple instances at the same topic, and field changes flow between them automatically.

from dataclasses import dataclass
from SpiriSynq.syncable_objects import SyncableObject

@dataclass
class Telemetry(SyncableObject):
    altitude: float = 0.0
    battery: int = 100

# Process A — owns the data
t = Telemetry("drone/telemetry", synq_authoritive=True)
t.altitude = 42.5  # published to the network automatically

# Process B — mirrors it
mirror = Telemetry.from_topic("drone/telemetry")
print(mirror.altitude)  # 42.5

Installation

pip install SpiriSynq

Requires Python 3.13+. A Zenoh router is optional for local use — peers discover each other directly.

How it works

Each syncable field maps to a Zenoh key expression <topic>/<field>. When a field changes, psygnal fires a signal, SpiriSynq serialises the new value to YAML, and publishes it. All subscribers on the same topic receive the update and apply it in-place without echo-looping it back.

Nested dataclass fields sync at the sub-field level: a change to robot.gps.latitude publishes to <topic>/gps/latitude, not <topic>/gps. Inherit from SubSyncableDataclass to make a nested type fully evented without Zenoh overhead; alternatively, use @dataclass(frozen=True) for immutable value objects that are replaced atomically.

Authoritative vs mirror

Sync is bidirectional — every instance both publishes its own changes and receives changes from others. synq_authoritive controls only the queryable side:

  • Authoritative (synq_authoritive=True): registers Zenoh queryables for full-state rehydration on connect, @remote_method RPCs, and schema/discovery endpoints. Sets the base topic prefix from the hostname.
  • Mirror (default): publishes and receives field changes just like an authoritative instance, but forwards RPC calls to the authoritative node rather than running them locally.
# Both sides can write — sync is bidirectional
counter = Counter("myapp/counter", synq_authoritive=True)
mirror = Counter.from_topic("myapp/counter")
mirror.value = 99  # received by counter

Remote methods

@remote_method exposes a method as a Zenoh queryable. Mirrors call it transparently — the call is routed to the authoritative node and the return value is sent back.

from SpiriSynq.remote_callables import remote_method

@dataclass
class Robot(SyncableObject):
    status: str = "idle"

    @remote_method
    def arm(self, mode: str = "auto") -> str:
        self.status = "armed"
        return f"armed in {mode} mode"

# From a mirror — works exactly like a local call
robot = Robot.from_topic("fleet/robot1")
result = robot.arm(mode="manual")  # "armed in manual mode"

Generator and async generator methods are supported. The mirror receives a regular Python generator that streams values as each reply arrives.

Custom timeouts: robot.arm.timeout(5.0)(mode="manual").

Discovery

from SpiriSynq.session import current_session

session = current_session.get()
for metadata in session.list_topics():
    print(metadata["topic"], metadata["classes"])

# Filter by type
for metadata in session.list_topics(type_filter="Robot"):
    robot = Robot.from_topic(metadata["topic"])

Cross-language compatibility

The wire format is plain Zenoh with YAML payloads. Any node that implements the SpiriSynq protocol — four mandatory queryables and per-field puts — is a first-class participant. No library required on the other end.

Key configuration options

Field Default Purpose
synq_authoritive False Register queryables; answer rehydration and RPC calls
synq_publish True Publish local changes to the network
synq_receive True Apply incoming changes from the network
sync_lazy_publish False Skip publishing when no subscribers are present
synq_auto_start True Call sync() automatically on construction

Docs

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

spirisynq-0.1.1.tar.gz (54.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

spirisynq-0.1.1-py3-none-any.whl (40.7 kB view details)

Uploaded Python 3

File details

Details for the file spirisynq-0.1.1.tar.gz.

File metadata

  • Download URL: spirisynq-0.1.1.tar.gz
  • Upload date:
  • Size: 54.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for spirisynq-0.1.1.tar.gz
Algorithm Hash digest
SHA256 0985c4bc309ac22c1d3c7bcd69566f23551ebed366c4f8ccf084e7bb98f489f2
MD5 e6d8aca72a78b82af67407452e6bf1f9
BLAKE2b-256 54d1823a49fe55ef8884b03ecca91b93fc230c832f59262a7c59636b0ad18957

See more details on using hashes here.

Provenance

The following attestation bundles were made for spirisynq-0.1.1.tar.gz:

Publisher: publish.yml on spiri-robotics/SpiriSynq

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file spirisynq-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: spirisynq-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 40.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for spirisynq-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 ddcffafa059bcfa07699259231e42ee667fca4055e0c7b9c8c2e9f0f7b085eb2
MD5 42aef48dca3e9a09e112c68c9d80363e
BLAKE2b-256 871e14f62b07b81a2b765907767198bd8ea2174dc112c9b3d84d5c021ac3e061

See more details on using hashes here.

Provenance

The following attestation bundles were made for spirisynq-0.1.1-py3-none-any.whl:

Publisher: publish.yml on spiri-robotics/SpiriSynq

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page