calendaring_sync.objects.record module#

A record: everything the core stores about one object.

calendaring_sync.objects.record.SyncedCopy: TypeAlias = calendaring_sync.objects.change.Changed | calendaring_sync.objects.edit.LocalEdit | calendaring_sync.objects.conflict.Conflict#

A copy of an object that a record can be synced to.

class calendaring_sync.objects.record.RecordState(*values)[source]#

Bases: StrEnum

The five states a record can be in.

SYNCED = 'synced'#

Matches the server’s copy.

PENDING = 'pending'#

Holds a pending edit.

IN_FLIGHT = 'in_flight'#

Its push was claimed, and how it ended isn’t known yet.

CONFLICT = 'conflict'#

Holds an open conflict.

REMOVED = 'removed'#

Gone from the server, kept until it’s purged or the object comes back, on the server or as a create at its id.

class calendaring_sync.objects.record.Record(local_key, scope, object_id, state, version, fingerprint, content, containers, logical_key, synced_at, last_entry, edit=None, conflict=None, claims=0)[source]#

Bases: object

What the store keeps about one object on the server.

From version to logical_key, the fields hold the synced copy: the object as your application and the server last agreed on it. Your pending edit is kept beside it in edit, and the server’s newer copy, when it conflicts with your edit, in conflict. A record in conflict therefore holds all three versions of the object: the synced copy, yours, and the server’s.

local_key#

The local key the core gave the record. It never changes, and is never given to another record.

Type:

int

scope#

The id of the scope the record belongs to.

Type:

str

object_id#

The object id, or None until the server assigns one to an object you created.

Type:

str | None

state#

The record’s state.

Type:

RecordState

version#

The version the server gave the synced copy, or None. While the record is in conflict, the server holds a newer copy, whose version is conflict.remote_version; server_version gives whichever is current.

Type:

str | None

fingerprint#

The fingerprint of content, or None after a fingerprint scheme change until the object is listed again.

Type:

str | None

content#

The content of the synced copy, the bytes the server sent, in the scope’s media type. None for an object you created that the server doesn’t have yet.

Type:

bytes | None

containers#

The containers of the synced copy.

Type:

frozenset[str]

logical_key#

The logical key of the synced copy, if it has one.

Type:

str | None

synced_at#

When an ingest last applied a change to the record, or None if none has.

Type:

datetime | None

last_entry#

The number of the last change feed entry about the record, 0 if there’s none.

Type:

int

edit#

The record’s pending edit, held while it’s pending, in flight or in conflict, and None otherwise.

Type:

LocalEdit | None

conflict#

The server’s copy in an open conflict, held while the record is in conflict, and None otherwise.

Type:

Conflict | None

claims#

How many times a push of the record was claimed. How a push ended only counts while no later claim has been made.

Type:

int

classmethod new(scope_id, object_id=None)[source]#

Return a record the store doesn’t hold yet, with nothing synced.

Its local_key is 0 until a store’s insert_record() gives it one; fill in the rest with synced_to(), or with an edit.

Examples

>>> from calendaring_sync import Record
>>> record = Record.new("work", "a")
>>> record.local_key, record.object_id, record.content
(0, 'a', None)
Return type:

Self

with_copy(copy, at)[source]#

Return the record whose synced copy is copy, synced at at.

Its state, edit and conflict stay as they are. copy is one of:

  • a change from the server, at its version

  • your edit, once the server applied it, with no version: the server may store it rewritten, so the next ingest brings its version

  • a conflict’s server side, at its version

Examples

>>> from datetime import UTC, datetime
>>> from calendaring_sync import Changed, Record
>>> change = Changed("v2", "fp-a2", b"Team meeting, moved")
>>> moved = Record.new("work", "a").with_copy(change, datetime(2026, 11, 2, tzinfo=UTC))
>>> moved.version, moved.content
('v2', b'Team meeting, moved')
Return type:

Self

synced_to(copy, at)[source]#

Return the record synced to copy, with no edit or conflict left.

copy is what with_copy() takes.

Examples

>>> from datetime import UTC, datetime
>>> from calendaring_sync import Changed, Record
>>> change = Changed("v1", "fp-a", b"Team meeting")
>>> Record.new("work", "a").synced_to(change, datetime(2026, 11, 2, tzinfo=UTC)).state
<RecordState.SYNCED: 'synced'>
Return type:

Self

removed_at(at)[source]#

Return the record once its object is gone from the server, with nothing left to push.

It keeps its synced copy, so a reader of the change feed can still see what was removed.

Examples

>>> from datetime import UTC, datetime
>>> from calendaring_sync import Record
>>> Record.new("work", "a").removed_at(datetime(2026, 11, 2, tzinfo=UTC)).state
<RecordState.REMOVED: 'removed'>
Return type:

Self

property is_create: bool#

Whether the record is an object you created that the server doesn’t have yet.

property is_refused: bool#

Whether the server refused this record’s edit.

That’s an edit refused for its logical key, or any edit the server didn’t allow. The conflict then holds no copy of the server’s object.

property is_refused_for_key: bool#

Whether the server refused this record’s create or change for its logical key.

Another object holds that key, and once it stops holding it, the edit is pending again.

property is_refused_existing: bool#

Whether the server refused this record’s change or delete of an object it has.

The server then still holds the synced copy.

property server_version: str | None#

The version of the server’s copy, None if the store knows none.

That’s the conflict’s while the record is in conflict, but the synced one for a change or delete the server refused, and None once the server removed the object.

property server_logical_key: str | None#

The logical key of the server’s copy, None if the server holds none.

It comes from the same copy as server_version, and a create the server doesn’t have has none.

property server_containers: frozenset[str]#

The containers of the server’s copy, empty if the server holds none.

They come from the same copy as server_version.

Last updated on 2026-11-11.