fleche.storage.base =================== .. py:module:: fleche.storage.base Attributes ---------- .. autoapisummary:: fleche.storage.base.logger Exceptions ---------- .. autoapisummary:: fleche.storage.base.SaveError fleche.storage.base.AmbiguousDigestError Classes ------- .. autoapisummary:: fleche.storage.base.KeyManagement fleche.storage.base.StorageBackend fleche.storage.base.ValueStorage fleche.storage.base.ValueMixin fleche.storage.base.Digested fleche.storage.base.DigestedIterable fleche.storage.base.DigestedDict fleche.storage.base.DestructuringMixin fleche.storage.base.CallStorage fleche.storage.base.CallMixin Module Contents --------------- .. py:data:: logger .. py:exception:: SaveError Bases: :py:obj:`Exception` Common base class for all non-exit exceptions. .. py:exception:: AmbiguousDigestError Bases: :py:obj:`ValueError` Inappropriate argument value (of correct type). .. py:class:: KeyManagement Bases: :py:obj:`abc.ABC` Abstract base providing key-management helpers for any keyed storage. Subclasses must implement ``list``, ``_evict``, and ``_contains``. The concrete helpers ``evict``, ``contains``, ``expand``, and ``shrink`` are implemented here once and inherited by all storage classes. .. py:method:: list() -> Iterable[fleche.digest.Digest] :abstractmethod: .. py:method:: _evict(key: fleche.digest.Digest) -> None :abstractmethod: .. py:method:: _contains(key: fleche.digest.Digest) -> bool :abstractmethod: .. py:method:: evict(key: fleche.digest.Digest | str) -> None Removes the entry corresponding to the key from the storage. .. py:method:: contains(key: fleche.digest.Digest | str) -> bool .. py:method:: expand(key: fleche.digest.Digest | str) -> fleche.digest.Digest Expands a short-hand digest to the full length one. .. py:method:: shrink(key: fleche.digest.Digest | str) -> fleche.digest.Digest Find the shortest substring that is still an unambiguous reference to the same value. .. py:class:: StorageBackend Bases: :py:obj:`KeyManagement` Primitive backend interface for key-value storage. Backends implement the low-level ``put``/``get``/``_evict``/``list`` operations. Higher-level classes (:class:`ValueMixin`, :class:`CallMixin`) add domain-specific logic on top. .. py:method:: put(value: Any, key: fleche.digest.Digest) -> fleche.digest.Digest :abstractmethod: .. py:method:: get(key: fleche.digest.Digest) -> Any :abstractmethod: .. py:method:: _contains(key: fleche.digest.Digest) -> bool .. py:class:: ValueStorage Bases: :py:obj:`KeyManagement` Abstract domain interface for value storage. .. py:method:: save(value: Any, key: fleche.digest.Digest | None = None) -> fleche.digest.Digest :abstractmethod: .. py:method:: load(key: fleche.digest.Digest | str) -> Any :abstractmethod: .. py:class:: ValueMixin Bases: :py:obj:`ValueStorage`, :py:obj:`StorageBackend` Bridges :class:`ValueStorage` with :class:`StorageBackend` primitives. Implements ``save`` and ``load`` using ``put`` and ``get``. Concrete classes inherit from this and a :class:`StorageBackend` implementation to get a fully functional value storage. .. py:method:: save(value: Any, key: fleche.digest.Digest | None = None) -> fleche.digest.Digest .. py:method:: load(key: fleche.digest.Digest | str) -> Any .. py:class:: Digested Bases: :py:obj:`abc.ABC` Helper class that provides a standard way to create an ABC using inheritance. .. py:method:: underlying() :abstractmethod: Return plain underlying value, ie. list/dict/etc of nested values or their partial digests .. py:method:: __digest__() .. py:method:: mend(storage: DestructuringMixin) :abstractmethod: .. py:method:: sunder(intern: Callable[[Any], tuple[Any, int | float]], value: Any) :classmethod: :abstractmethod: .. py:method:: get(storage, key) :staticmethod: .. py:class:: DigestedIterable Bases: :py:obj:`Digested` Helper class that provides a standard way to create an ABC using inheritance. .. py:attribute:: items :type: list | tuple .. py:method:: underlying() Return plain underlying value, ie. list/dict/etc of nested values or their partial digests .. py:method:: mend(storage: DestructuringMixin) -> list | tuple .. py:method:: sunder(intern: Callable[[Any], tuple[Any, int | float]], value: list | tuple) :classmethod: .. py:class:: DigestedDict Bases: :py:obj:`Digested` Helper class that provides a standard way to create an ABC using inheritance. .. py:attribute:: items :type: dict .. py:method:: underlying() Return plain underlying value, ie. list/dict/etc of nested values or their partial digests .. py:method:: mend(storage: DestructuringMixin) -> dict .. py:method:: sunder(intern: Callable[[Any], tuple[Any, int | float]], value: dict) :classmethod: .. py:class:: DestructuringMixin Bases: :py:obj:`StorageBackend` Mixin that recursively destructures collections on save/load. Place before a concrete :class:`StorageBackend` in 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:: class DestructuringMemory(ValueMixin, DestructuringMixin, Memory): pass dm = DestructuringMemory(storage={}) key = dm.save([1, [2, 3]]) assert dm.load(key) == [1, [2, 3]] .. py:attribute:: remaining_depth :type: int :value: 0 .. py:method:: _intern_rec(value: Any, key: fleche.digest.Digest | None = None) -> tuple[Any, int | float] Post-order traversal: recurse to leaves, decide inline-vs-store on the way back up. Returns ``(result, depth)`` where *result* is the plain value when ``depth < remaining_depth`` (the element is inlined in its parent's :class:`Digested` wrapper) or a :class:`Digest` when the element was written to storage separately. Every node in the structure is visited exactly once (O(n)), unlike a separate depth-counting pass. .. py:method:: put(value: Any, key: fleche.digest.Digest) -> fleche.digest.Digest .. py:method:: get(key: fleche.digest.Digest | Any) -> Any .. py:class:: CallStorage Bases: :py:obj:`KeyManagement` Abstract domain interface for call storage. .. py:method:: save(call: fleche.call.Call) -> fleche.digest.Digest :abstractmethod: .. py:method:: load(key: fleche.digest.Digest | str) -> fleche.call.Call :abstractmethod: .. py:method:: query(template: fleche.call.QueryCall) -> Iterable[fleche.call.Call] :abstractmethod: .. py:method:: transform(func: Callable[[fleche.call.Call], fleche.call.Call] | None = None) -> None Applies a transformation function to all Call objects in the storage. :param func: A function that takes a Call and returns a transformed Call. If None, the identity function is used (useful for re-calculating keys). :type func: Callable[[Call], Call] | None .. py:class:: CallMixin Bases: :py:obj:`CallStorage`, :py:obj:`StorageBackend` Bridges :class:`CallStorage` with :class:`StorageBackend` primitives. Implements ``save``, ``load``, and ``query`` using ``put`` and ``get``, deriving the storage key from the call's lookup key. ``transform`` is inherited from :class:`CallStorage`. Concrete classes inherit from this and a :class:`StorageBackend` implementation to get a fully functional call storage. .. py:method:: save(call: fleche.call.Call) -> fleche.digest.Digest .. py:method:: load(key: fleche.digest.Digest | str) -> fleche.call.Call .. py:method:: query(template: fleche.call.QueryCall) -> Iterable[fleche.call.Call] Find cached calls that 'match' the template. Returns all calls where the given arguments, results or metadata match exactly the stored ones. Values may be given either as they are or as :class:`Digest`. :param template: specification for calls to return; use `None` as wildcard. :type template: Call :returns: an iterable over all matching call objects :rtype: Iterable[Call]