fleche.storage.destructuring
Classes
Helper class that provides a standard way to create an ABC using |
|
Helper class that provides a standard way to create an ABC using |
|
Helper class that provides a standard way to create an ABC using |
|
Common base for record-shaped value markers (dataclasses, attrs). |
|
Per-field marker for stdlib |
|
Per-field marker for |
|
Structural protocol for value storages that expose a reference-graph edge query. |
|
Mixin that recursively destructures collections on save/load. |
Module Contents
- class fleche.storage.destructuring.Digested[source]
Bases:
abc.ABCHelper class that provides a standard way to create an ABC using inheritance.
- abstractmethod underlying()[source]
Return plain underlying value, ie. list/dict/etc of nested values or their partial digests
- abstractmethod mend(storage: DestructuringMixin)[source]
- class fleche.storage.destructuring.DigestedIterable[source]
Bases:
DigestedHelper class that provides a standard way to create an ABC using inheritance.
- underlying()[source]
Return plain underlying value, ie. list/dict/etc of nested values or their partial digests
- mend(storage: DestructuringMixin) list | tuple[source]
- class fleche.storage.destructuring.DigestedDict[source]
Bases:
DigestedHelper class that provides a standard way to create an ABC using inheritance.
- underlying()[source]
Return plain underlying value, ie. list/dict/etc of nested values or their partial digests
- mend(storage: DestructuringMixin) dict[source]
- class fleche.storage.destructuring.DigestedFields[source]
Bases:
DigestedCommon base for record-shaped value markers (dataclasses, attrs).
Subclasses provide
_field_items()to enumerate(name, value)pairs from a live instance;sunder(),mend(), and__digest__()are shared. Field values may be replaced byDigestback-references when they are stored independently.mend()reconstructs the original instance by bypassing__init__/__post_init__, soInitVarandinit=Falsefields (and attrs slots / frozen instances) are all handled uniformly.- underlying()[source]
Return plain underlying value, ie. list/dict/etc of nested values or their partial digests
- mend(storage: DestructuringMixin)[source]
- class fleche.storage.destructuring.DigestedDataclass[source]
Bases:
DigestedFieldsPer-field marker for stdlib
dataclassesinstances.
- class fleche.storage.destructuring.DigestedAttrs[source]
Bases:
DigestedFieldsPer-field marker for
attrs-decorated instances.
- class fleche.storage.destructuring.HasChildDigests[source]
Bases:
ProtocolStructural protocol for value storages that expose a reference-graph edge query.
Any
ValueStoragethat implementschild_digests()satisfies this protocol automatically — no explicit registration or inheritance required. Useisinstance(storage, HasChildDigests)to check at runtime whether the storage supports transitive reachability walks.- child_digests(key: fleche.digest.Digest) set[fleche.digest.Digest][source]
Return the set of digests directly referenced by the entry at key.
- Raises:
KeyError – if key is not present in the storage.
- class fleche.storage.destructuring.DestructuringMixin[source]
Bases:
fleche.storage.base.ValueStorageMixin that recursively destructures collections on save/load.
Place before a
ValueMixinin the MRO to add destructuring behavior. Lists, tuples, and dicts are broken apart so each element is stored independently; on load the original structure is reassembled.Example
>>> from fleche.storage.base import ValueMixin >>> from fleche.storage.memory import MemoryBackend >>> @dataclass(frozen=True) ... class MyValueStorage(DestructuringMixin, ValueMixin, MemoryBackend): ... >>> vm = MyValueStorage(storage={}) >>> key = vm.save([1, [2, 3]]) >>> vm.load(key) == [1, [2, 3]] True
- _intern_rec(value: Any, key: fleche.digest.Digest | None = None) tuple[Any, int | float][source]
Post-order traversal: recurse to leaves, decide inline-vs-store on the way back up.
Returns
(result, depth)where result is the plain value whendepth < remaining_depth(the element is inlined in its parent’sDigestedwrapper) or aDigestwhen the element was written to storage separately. Every node in the structure is visited exactly once (O(n)), unlike a separate depth-counting pass.
- save(value: Any, key: fleche.digest.Digest | None = None) fleche.digest.Digest[source]
- load(key: fleche.digest.Digest | str) Any[source]
- _raw_sub_digests(raw: Any) set[fleche.digest.Digest][source]
Direct digest children of a raw stored entry.
A raw entry is what
super().loadreturns — i.e. what was written to the underlying backend beforemend()rewires sub-digests back into their parent container. OnlyDigestedwrappers carry child references; scalars and plain (non-destructured) containers return an empty set.
- child_digests(key: fleche.digest.Digest | str) set[fleche.digest.Digest][source]
Direct digest children of the raw entry stored at key.
Bypasses
mend(), so destructured sub-references are returned as opaqueDigestkeys rather than being followed. Intended for reference-graph traversals (GC, debugging) where loading the mended value would flatten the structure we need to inspect.- Raises:
KeyError – if key is not present in the underlying backend.
- count_reuses() collections.Counter[fleche.digest.Digest][source]
Return a counter of how many times each stored key is referenced as a sub-component.
Scans every raw entry and tallies
Digestback-references found insideDigestedIterableandDigestedDictwrappers. A count of0means the key is not pointed to by any other stored value (i.e. a top-level entry). A count greater than1indicates a sub-value shared between multiple parent containers.- Returns:
A
Countermapping eachDigestkey to the number of times it is referenced by other stored entries.
Example
>>> from fleche.storage.memory import ValueMemory >>> ds = ValueMemory(storage={}) >>> shared = [2, 3] >>> _ = ds.save([1, shared]) >>> _ = ds.save([4, shared]) >>> hits = ds.count_reuses() >>> hits[ds.save(shared)] # [2, 3] is referenced by both outer lists 2