calendaring_sync.store.memory module#

A store that keeps everything in memory, and can hand its data to a keeper to save.

class calendaring_sync.store.memory.MemoryStore(*, keeper=None)[source]#

Bases: StateStore

A store held in memory, lost when the process ends unless a keeper saves it.

Each transaction works on its own view of the data: a read on the data the last write committed, a write on a copy of it, which becomes the committed data only when the transaction ends normally. So a read in one thread runs while another thread writes, and sees the data as it was when the read started. Lookups scan every record, so it suits test data and small stores; use SQLiteStore for large ones.

Parameters:

keeper (MemoryKeeper | None) – Where to save the data, such as a file, so the next process can load it. None keeps it only in memory.

Raises:

StoreError – If the keeper can’t load the data, as its error() says.

Examples

A keeper that saves the data as pickled bytes, and a second store loaded from them:

>>> import pickle
>>> from calendaring_sync import Changed, ChangeSet, MemoryKeeper, MemoryStore, Replica
>>> class Pickled(MemoryKeeper):
...     def __init__(self, saved=None):
...         self.saved = saved
...     def load(self):
...         return pickle.loads(self.saved) if self.saved else None
...     def save(self, data):
...         self.saved = pickle.dumps(data)
>>> keeper = Pickled()
>>> listing = ChangeSet(
...     "work", None, "t1", {"a": Changed("v1", "fp-a", b"Team meeting")}, full_listing=True
... )
>>> with Replica(MemoryStore(keeper=keeper)).session(
...     "work", fingerprint_scheme="sha256", media_type="text/plain"
... ) as session:
...     session.ingest(listing)
>>> store = MemoryStore(keeper=Pickled(keeper.saved))
>>> Replica(store).find_record("work", "a").content
b'Team meeting'
class calendaring_sync.store.memory.MemoryKeeper[source]#

Bases: ABC

Keeps a MemoryStore’s data somewhere else, such as in a file.

Pass one to MemoryStore. It loads the data once, when the store opens, and saves it each time a write commits; reads come from memory. If save() raises, the write fails and the store keeps the data it saved last, as long as save() doesn’t stop halfway: write to a new file and then replace the old one, for example.

What MemoryData holds can change between releases, so data a keeper saved with one release may not load in another. Keep sync state that has to outlive an upgrade in SQLiteStore, whose file a newer release reads.

abstractmethod load()[source]#

Return the data saved last, or None for a store with nothing saved yet.

Return type:

MemoryData | None

abstractmethod save(data)[source]#

Keep the data a write commits, in place of what was saved before.

Return type:

None

error(exc)[source]#

Return the store error for an exception load() or save() raised.

Turn the failures of the storage underneath, such as a full disk, into StoreError; anything this returns None for is reported as a bug.

Return type:

StoreError | None

class calendaring_sync.store.memory.MemoryData[source]#

Bases: object

Everything a MemoryStore holds, as one object.

A MemoryKeeper saves and loads it whole. It’s made of plain containers holding the library’s frozen dataclasses, so it pickles; what’s inside isn’t part of the API.

Last updated on 2026-11-11.