lacing.store.mapping#
MappingStore — an IntervalAnnotationStore persisted to any MutableMapping.
Where SqliteStore owns a file, MappingStore
owns nothing: the caller injects the persistence as a MutableMapping (a
plain dict, a dol JsonFiles / Files store, an application’s
“mall” entry, an S3-backed mapping, …). An app that already keeps its data
in mappings can hand one to lacing as its annotation graph, so there is no
second persistence path beside the one it already has.
Layout inside the mapping#
One key per annotation:
str(annotation.id)(a UUID string) ->annotation.model_dump(mode="json"), the same JSON shape every other lacing surface (server, MCP, op-log) uses for anAnnotation.Tiers under one reserved key (
tiers_key, default"__lacing_tiers__"):{"tiers": [<Tier.to_wire()>, ...]}. The key can never collide with an annotation key because a UUID string is exactly 36 characters of hex and hyphens.
The mapping holds JSON-ready dicts by default. That is what a plain
dict and dol’s JsonFiles both want (JsonFiles does the
json.dumps itself). For a mapping that stores bytes or str (a raw
Files store, a blob bucket), pass codec=JSON_BYTES_CODEC or
JSON_STR_CODEC, or your own MappingCodec.
The interval index is MemoryStore’s: the whole
mapping is loaded into it on construction and every mutation is written
through to the mapping first and applied to the index only if that write
succeeded. All Allen-relation queries are the in-memory ones; there is no
re-implementation here.
Lifecycle#
close() is a harmless no-op that leaves the store usable (write-through
means there is nothing to flush, and the mapping is not ours to close).
Concurrency#
Single writer, no locking. Unlike SqliteStore there is no cross-process
lock: the index is a snapshot taken at construction, so a second
MappingStore over the same mapping (in this or another process) does not
see the first one’s later writes, and two writers can overwrite each other’s
tier registry. Serialise writers yourself, or open one store per process
lifetime. Keys foreign to the layout (anything that is neither a UUID string
nor tiers_key) make construction raise rather than be silently skipped, so
point the store at a mapping (or a sub-mapping) dedicated to it.
Module Attributes
Store the JSON-ready dict itself ( |
|
Store UTF-8 JSON |
|
Store JSON |
Classes
|
How a JSON-ready |
|
An |
- lacing.store.mapping.DICT_CODEC = (<function <lambda>>, <function <lambda>>)#
Store the JSON-ready dict itself (
dict, dolJsonFiles). The default.
- lacing.store.mapping.JSON_BYTES_CODEC = (<function <lambda>>, <function <lambda>>)#
Store UTF-8 JSON
bytes(a raw dolFilesstore, a blob bucket).
- lacing.store.mapping.JSON_STR_CODEC = (<function dumps>, <function <lambda>>)#
Store JSON
str.
- class lacing.store.mapping.MappingCodec(encode, decode)[source]#
Bases:
NamedTupleHow a JSON-ready
dictis turned into what the mapping stores, and back.
- class lacing.store.mapping.MappingStore(mapping, *, codec=(<function <lambda>>, <function <lambda>>), tiers_key='__lacing_tiers__')[source]#
Bases:
MemoryStoreAn
IntervalAnnotationStorepersisted to an injectedMutableMapping.>>> from lacing.store import MappingStore >>> backing = {} >>> store = MappingStore(backing) >>> len(backing) # nothing written until something is added 0
Reopening over the same mapping sees the same annotations and tiers.
Raises
ValueErroron a duplicate annotation id (asSqliteStoredoes) and when an annotation is assigned under a key that is not its own interval; both would otherwise not survive a reload.