Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

Ditto Python SDK

An asyncio-native Python binding for Ditto — a cross-platform, peer-to-peer database that syncs data with and without internet connectivity. Install it, read and write with DQL, and Ditto automatically syncs changes to other devices over Bluetooth LE, P2P Wi-Fi, LAN, and the cloud.

The distribution is named dittolive-ditto; you import it as ditto.

Docs DQL PyPI Portal

Public Preview. This is an early preview release. The API may change before a stable release, and it is published as a pre-release — see Installation.

Installation

python3 -m pip install --pre dittolive-ditto

--pre is required while the SDK is in preview (the published versions are pre-releases such as 5.2.0.dev0). Requires Python 3.10+.

Published wheels are platform-specific and bundle the matching native library (libdittoffi) — there is nothing else to install or build.

Preview wheels are currently published for macOS on Apple Silicon and Linux on x86_64 and arm64 (manylinux_2_35 — glibc 2.35+); more platforms are on the way.

Getting Started

Ditto.open(...) is both awaitable and an async context manager. The context manager form closes the peer for you:

import asyncio
from ditto import Ditto, DittoConfig, DittoConfigConnect


async def main() -> None:
    config = DittoConfig(
        database_id="your-database-id",
        connect=DittoConfigConnect.small_peers_only(),
        persistence_directory="./ditto-data",
    )

    async with Ditto.open(config) as peer:
        await peer.store.execute(
            "INSERT INTO cars DOCUMENTS (:car)",
            {"car": {"_id": "car1", "make": "Tesla", "color": "red"}},
        )
        with await peer.store.execute("SELECT * FROM cars") as result:
            for item in result:
                print(item.value)


asyncio.run(main())

The equivalent explicit form (close() is async because shutdown may wait for native work):

peer = await Ditto.open(config)
try:
    ...
finally:
    await peer.close()

DittoConfigConnect.small_peers_only() runs fully offline / local + peer-to-peer. To sync through a Ditto server (Big Peer), use DittoConfigConnect.server(...) — see Sync and Connecting to a Ditto Server.

Store and Queries (DQL)

All reads and writes go through DQL, executed on peer.store. execute() is async and returns a QueryResult you iterate for document values. The snippets below run inside the async with Ditto.open(config) as peer: block from Getting Started; each result owns native resources, so wrap it in with await …: (as the read below does) when you keep it:

# Create / upsert
await peer.store.execute(
    "INSERT INTO cars DOCUMENTS (:car) ON ID CONFLICT DO UPDATE",
    {"car": {"_id": "car1", "make": "Tesla", "color": "red"}},
)

# Update
await peer.store.execute(
    "UPDATE cars SET color = :color WHERE _id = :id",
    {"color": "blue", "id": "car1"},
)

# Read
with await peer.store.execute("SELECT * FROM cars WHERE color = :color",
                              {"color": "blue"}) as result:
    cars = [item.value for item in result]

# Delete: writes a tombstone that propagates removal to peers
# (use EVICT instead to drop a document only from the local store)
await peer.store.execute("DELETE FROM cars WHERE _id = :id", {"id": "car1"})

Reactive Observers

Register an observer to be called with the current result set whenever documents matching a query change locally or arrive from a peer:

def on_change(result):
    for item in result:
        print("cars changed:", item.value)


observer = peer.store.register_observer("SELECT * FROM cars", on_change)
# ... later, to stop receiving updates (close() alone does not stop delivery):
observer.cancel()

The handler may be a sync or async function, and is delivered on the event loop that registered it.

Sync

Sync is off until you start it. peer.sync.start() brings up the transports; register_subscription(...) tells Ditto which documents to sync from other peers (the argument must be a SELECT query):

peer.sync.start()
subscription = peer.sync.register_subscription("SELECT * FROM cars")
# ... later:
subscription.cancel()

Syncing with other peers or a Ditto server requires a license. For offline / small-peers-only use you can set an offline token obtained from the Ditto Portal:

peer.set_offline_only_license_token("your-offline-license-token")

Connecting to a Ditto Server

Connecting through a server (DittoConfigConnect.server(...)) requires setting an authentication expiration handler before starting sync — otherwise sync.start() raises DittoExpirationHandlerMissingError:

from datetime import timedelta
from ditto import Ditto, DittoConfig, DittoConfigConnect

config = DittoConfig(
    database_id="your-database-id",
    connect=DittoConfigConnect.server("https://your-app.cloud.ditto.live"),
)

async with Ditto.open(config) as peer:
    def on_expiring(ditto: Ditto, remaining: timedelta) -> None:
        # Obtain a fresh token and call `ditto.auth.login(...)`.
        ...

    peer.auth.expiration_handler = on_expiring
    peer.sync.start()

Also Available

The SDK surfaces the rest of Ditto's v5 API through the same peer. All of these are importable from the top-level ditto package:

  • Presence — observe the live mesh with peer.presence.register_observer(handler), where handler(graph: PresenceGraph) is called on each change.
  • Transactions — group reads/writes with peer.store.transaction(...).
  • Attachments — store and fetch large binaries via peer.store.new_attachment(...) and peer.store.fetch_attachment(...).
  • Transports — configure Bluetooth LE, LAN, AWDL, Wi-Fi Aware, and WebSocket via DittoConfig / the transport_config types (BluetoothLEConfig, DittoLanConfig, WifiAwareConfig, …).
  • Disk usage, logging, and typed errorsDiskUsageObserver, DittoLogger / LogLevel, and the Ditto*Error hierarchy.

See the Ditto documentation for concepts (mesh networking, data handling, sync) and the DQL reference.

Native Library Discovery

Wheel installs need no configuration. If you are working from a source checkout instead, point the loader at a compatible libdittoffi with DITTOFFI_LIB_PATH (the file or a directory containing it) or DITTOFFI_SEARCH_PATH (platform-separated directories). Importing ditto never loads the native library; it loads on first use of a native API.

Concurrency and Resource Ownership

  • Native callbacks are delivered on the asyncio event loop that registered them; handlers may be sync or async.
  • Result and observer objects own native resources — close them promptly or use their context-manager support. Ditto.close() is async.
  • Ditto's native runtime and logger hold process-global state, so tests must run sequentially (pytest-xdist is intentionally unsupported).
  • A Ditto handle must not cross a process fork. Use multiprocessing.get_context("spawn") and open a fresh Ditto in each worker.

Resources

License

Ditto is commercial software. See ditto.com for licensing.

Download files

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

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

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

dittolive_ditto-5.2.0.dev0-py3-none-manylinux_2_35_x86_64.whl (21.0 MB view details)

Uploaded Python 3manylinux: glibc 2.35+ x86-64

dittolive_ditto-5.2.0.dev0-py3-none-manylinux_2_35_aarch64.whl (20.8 MB view details)

Uploaded Python 3manylinux: glibc 2.35+ ARM64

dittolive_ditto-5.2.0.dev0-py3-none-macosx_12_0_arm64.whl (17.5 MB view details)

Uploaded Python 3macOS 12.0+ ARM64

File details

Details for the file dittolive_ditto-5.2.0.dev0-py3-none-manylinux_2_35_x86_64.whl.

File metadata

File hashes

Hashes for dittolive_ditto-5.2.0.dev0-py3-none-manylinux_2_35_x86_64.whl
Algorithm Hash digest
SHA256 c61cd25a2a885fed4e39f46886ff7d8ee9260faaadec32a6cc99afd53a208c89
MD5 be7b9eb903c2498978c4d9d6406541c5
BLAKE2b-256 b39214f43d858947a5cdae2e74703e324d2b35123bd799c38fdbdc1130fb32df

See more details on using hashes here.

Provenance

The following attestation bundles were made for dittolive_ditto-5.2.0.dev0-py3-none-manylinux_2_35_x86_64.whl:

Publisher: python-sdk-publish.yml on getditto/ditto

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

File details

Details for the file dittolive_ditto-5.2.0.dev0-py3-none-manylinux_2_35_aarch64.whl.

File metadata

File hashes

Hashes for dittolive_ditto-5.2.0.dev0-py3-none-manylinux_2_35_aarch64.whl
Algorithm Hash digest
SHA256 ad0c881ca44394d2d695e6d8dc67b9581a9a7998841da669164d8512b5bf22fb
MD5 a9387d04aa81b34be3154214d49e2db1
BLAKE2b-256 14337774aed5a981a654a1d13dcef2ee35118ad05dec4bb07451deec16c9d06d

See more details on using hashes here.

Provenance

The following attestation bundles were made for dittolive_ditto-5.2.0.dev0-py3-none-manylinux_2_35_aarch64.whl:

Publisher: python-sdk-publish.yml on getditto/ditto

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

File details

Details for the file dittolive_ditto-5.2.0.dev0-py3-none-macosx_12_0_arm64.whl.

File metadata

File hashes

Hashes for dittolive_ditto-5.2.0.dev0-py3-none-macosx_12_0_arm64.whl
Algorithm Hash digest
SHA256 f783104fadf0034b7fe6bed999386491423ea0f33e1d2674e936b903ae604c56
MD5 f699ea79b9c860d1ab3329fdfed9bf99
BLAKE2b-256 a0b3270a159554fdc99ecf2509a926386cd23d7e760375718709ca4637f57597

See more details on using hashes here.

Provenance

The following attestation bundles were made for dittolive_ditto-5.2.0.dev0-py3-none-macosx_12_0_arm64.whl:

Publisher: python-sdk-publish.yml on getditto/ditto

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

Release history Release notifications | RSS feed

This release

5.2.0.dev0 This release

3 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