Source code for stackholm.storage

from typing import (
    Any,
    Dict,
    Optional,
    Protocol,
    Tuple,
    Type,
    TypeVar,
    cast,
    runtime_checkable,
)

from stackholm.context import Context
from stackholm.state import State


__all__ = (
    'Storage',
)


STATE_T = TypeVar('STATE_T', bound=State)


[docs]@runtime_checkable class Storage( Protocol[STATE_T], ): """ Storage is a container for the state of a stack. **Built-in Implementations:** - :class:`~stackholm.storages.asgiref_local.asgiref_local_storage.ASGIRefLocalStorage` - :class:`~stackholm.storages.contextvar.contextvar_storage.ContextVarStorage` - :class:`~stackholm.storages.optimized_list.optimized_list_storage.OptimizedListStorage` - :class:`~stackholm.storages.thread_local.thread_local_storage.ThreadLocalStorage` **Creating a new implementation:** An implementation of this protocol can be developed using the generic feature of the class. .. code-block:: python class MyStorage(Storage[MyState]): ... """
[docs] def create_context_class( self, name: Optional[str] = None, bases: Optional[Tuple[Type]] = None, namespace: Optional[Dict[str, Any]] = None, ) -> Type[Context]: """ Creates and returns a new context class. The created class will be bound to the storage. .. caution:: If the parameter `bases` is provided, it must include :class:`.Context` or at least one of its subclass as the first element. .. hint:: - https://www.python.org/download/releases/2.3/mro/ :param name: The name of the class. (Default: `'Context'`) :param bases: The base classes of the class. (Default: `(Context,)`) :param namespace: The namespace of the class. (Default: `{}`) """ name = name or 'Context' bases = bases or (Context,) namespace = namespace or {} namespace['_storage'] = self context_class = cast(Type[Context], type(name, bases, namespace)) assert issubclass(context_class, Context), 'Context class must be a subclass of stackholm.Context' # noqa return context_class
[docs] def get_state(self) -> STATE_T: """ Returns the state of the storage. """ raise NotImplementedError()
[docs] def set_state( self, state: STATE_T, ) -> None: """ Sets the state of the storage. :param state: The :class:`.State` instance to set. """ raise NotImplementedError()
@property def state(self) -> STATE_T: """ Returns the state of the storage. """ return self.get_state()
[docs] def push_context( self, context: Context, ) -> int: """ Pushes a new context to the storage. Returns the index of the pushed context. .. seealso:: - :meth:`.State.push_context` :param context: The :class:`.Context` instance to push. """ return self.state.push_context(context)
[docs] def pop_context( self, index: int = -1, ) -> Optional[Context]: """ Pops and returns a context from the storage. If the stack is empty, returns `None`. .. seealso:: - :meth:`.State.pop_context` :param index: The index of the context to pop. (Default: `-1`) """ return self.state.pop_context(index)
[docs] def get_last_context(self) -> Optional[Context]: """ Returns the latest context in the stack. .. seealso:: - :meth:`.State.get_last_context` """ return self.state.get_last_context()
[docs] def add_checkpoint( self, key: str, context_index: int, ) -> None: """ Adds a checkpoint to the storage. .. seealso:: - :meth:`.State.add_checkpoint` :param key: The partition key of the checkpoint. :param context_index: The index of the context. """ self.state.add_checkpoint(key, context_index)
[docs] def remove_checkpoint( self, key: str, context_index: int, ) -> None: """ Removes a checkpoint from the storage. .. seealso:: - :meth:`.State.remove_checkpoint` :param key: The partition key of the checkpoint. :param context_index: The index of the context. """ self.state.remove_checkpoint(key, context_index)
[docs] def get_nearest_checkpoint(self, key: str) -> Optional[Context]: """ Returns the latest context in the partition with the given partition key. .. seealso:: - :meth:`.State.get_nearest_checkpoint` :param key: The partition key of the checkpoint. """ return self.state.get_nearest_checkpoint(key)