accordsync
The Accord client for Python: local-first writes, background sync, conflicts and refusals.
A Python program becomes an Accord device like a phone or a browser: it writes to its own SQLite
database at once, online or not, and syncs with any Accord server (TypeScript, PHP or Python). It
speaks the same protocol and merges by the same rules as
@accordsync/client. Python 3.11+.
pip install accordsync
Open the client
Declare the same schema as your server, then open the client with SQLite storage and the HTTP transport.
from accordsync import (
AccordClient,
HttpTransport,
SqliteStorage,
conflict,
counter,
define_schema,
lww,
set_,
)
schema = define_schema(
{"dossier": {"agent": lww(), "visits": counter(), "docs": set_(), "status": conflict()}}
)
def get_token() -> str:
return my_auth.current_jwt() # your app's auth; called before every request
accord = AccordClient.open(
schema=schema,
storage=SqliteStorage("accord.db"),
transport=HttpTransport("https://sync.example.com", get_token=get_token),
)
Leave device_id unset: the client generates one from a secure random source and stores it.
SqliteStorage takes a path or an open sqlite3.Connection; its tables are prefixed accord_, so
they can share your program's database. MemoryStorage keeps nothing on disk (tests).
Write, then sync
Writes apply locally and are saved before they return. Sync on demand, or in the background.
accord.assign("dossier:91", "agent", "awa")
accord.inc("dossier:91", "visits", 1)
accord.add("dossier:91", "docs", "photo-1.jpg")
accord.sync() # one round: push the pending writes, pull everyone else's
accord.start() # or sync in a background thread: after writes, every 30 s, backoff on errors
print(accord.read("dossier:91")) # {'agent': 'awa', 'visits': 1, 'docs': ['photo-1.jpg']}
print(accord.status().pending) # writes not yet acknowledged by the server
accord.close() # stops background sync and closes the storage
Events and refusals
off = accord.on("change", lambda records: print("changed:", records))
accord.on("refused", lambda r: print(f"refused {r.record}.{r.field}: {r.reason}"))
accord.on("error", lambda e: print("sync failed, retrying:", e))
The events are change (records whose local state changed), refused (a write the server refused,
already rolled back on this device: tell the user), synced, resync and error. on() returns a
function that unsubscribes. Listeners run on the thread that caused the event.
Conflicts
A conflict() field written concurrently on two devices keeps both values until someone decides.
for c in accord.conflicts():
print(c.record, c.field, [v.value for v in c.values])
accord.resolve(c.record, c.field, c.values[0].value)
While conflicted, read() shows the field as {"conflicted": [{"value": …, "opId": …}, …]}; once
resolved, as {"value": …}.
Same behaviour as TypeScript
The merge core (accordsync-core) passes the shared
golden vectors in every delivery order and reproduces the TypeScript core's random scenarios byte for
byte. The repository's interop/ harness runs this client against the real TypeScript server, alone
and together with TypeScript devices over a network that loses requests and responses, and checks
every device ends with identical data.
Docs: accord.benhattab.pro/docs/python · Source: crossben/accordsync-python · Licence: Apache-2.0
Metadata
Release files for accordsync 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| accordsync-0.3.0.tar.gz | 26.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| accordsync-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 45.7 kB
Release files / accordsync-0.3.0.tar.gz
| Download URL | accordsync-0.3.0.tar.gz |
|---|---|
| Size | 26.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b841a789386346745f7a61a392ecb6d7b93e449cf4f1e5652f90465cdc019879
|
|
BLAKE2b-256 checksum How to use checksums |
0e1e21b9c9d0bfafb0e2bd1e3bf2637bee19a1db156b060dd3d5f96cdd379a4a
|
| 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 Oct 7, 2026.
Transparency logRelease files / accordsync-0.3.0-py3-none-any.whl
| Download URL | accordsync-0.3.0-py3-none-any.whl |
|---|---|
| Size | 19.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
bbe7c368401bbee028115991bdd910550c5235ae0b530280acb71fb5ce75bce5
|
|
BLAKE2b-256 checksum How to use checksums |
6c62617123d0991a27b582c2d8ea3056f0b2ba9f0cedf48479fea2f9cab85b31
|
| 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 Oct 7, 2026.
Transparency log