"""Data structures responsible for keeping track of mutations to a :class:`Value` or :class:`Collection`"""
from .scalar import ref
from .scalar.value import Nil
from .state import State
from .uri import URI
[docs]class Chain(State):
"""Data structure responsible for keeping track of mutations to a :class:`Value` or :class:`Collection`."""
__uri__ = URI(State) + "/chain"
def __new__(cls, form):
if ref.is_ref(form):
return State.__new__(cls)
elif isinstance(form, State):
class _Chain(cls, type(form)):
def __json__(self):
return cls.__json__(self)
return State.__new__(_Chain)
else:
raise ValueError(f"Chain subject must be a State, not {form}")
def __init__(self, form):
# in this case, the type of form is significant
# so we can't call State.__init__ because it will discard the type of the form
if isinstance(form, URI):
self.__uri__ = form
elif ref.is_ref(form) and hasattr(form, "__uri__"):
self.__uri__ = URI(form)
self.__form__ = form
[docs] def set(self, value):
"""Update the value of this `Chain`."""
return ref.Put(URI(self), None, value)
# TODO: delete these overrides
def _get(self, name, key=None, rtype=State):
op_ref = ref.Get(URI(self).append(name), key)
rtype = Nil if rtype is None else rtype
return rtype(form=op_ref)
def _put(self, name, key=None, value=None):
return Nil(ref.Put(URI(self).append(name), key, value))
def _post(self, name, params, rtype=State):
op_ref = ref.Post(URI(self).append(name), params)
rtype = Nil if rtype is None else rtype
return rtype(form=op_ref)
def _delete(self, name, key=None):
return Nil(ref.Delete(URI(self).append(name), key))
[docs]class Block(Chain):
"""A :class:`Chain` which keeps track of the entire update history of its subject."""
__uri__ = URI(Chain) + "/block"
[docs]class Sync(Chain):
"""
A :class:`Chain` which keeps track of only the current transaction's operations,
in order to recover from a transaction failure (e.g. if the host crashes).
"""
__uri__ = URI(Chain) + "/sync"