Source code for mincepy.refs

"""References module"""
from typing import Optional

from . import exceptions
from . import types
from . import records

__all__ = ('ObjRef',)


[docs]class ObjRef(types.SavableObject): """A reference to an object instance""" TYPE_ID = records.SnapshotId.TYPE_ID IMMUTABLE = True _obj = None _sid = None # type: Optional[records.SnapshotId] _loader = None def __init__(self, obj=None): super().__init__() assert not (obj is not None and types.is_primitive(obj)), \ "Can't create a reference to a primitive type" self._obj = obj def __bool__(self) -> bool: """Test if this is a null reference""" return self._obj is not None or self._sid is not None def __str__(self) -> str: desc = ["ObjRef('"] if self._obj is not None: desc.append(str(self._obj)) else: desc.append(str(self._sid)) desc.append("')") return "".join(desc) def __repr__(self) -> str: return "ObjRef({})".format(self._obj if self._obj is not None else self._sid) def __call__(self, update=False): """Get the object being referenced. If update is called then the latest version will be loaded from the historian""" if self._obj is None: # This means we were loaded and need to load the object if self._sid is None: raise RuntimeError("Cannot dereference a None reference") # Cache the object self._obj = self._loader.load(self._sid) assert self._obj is not None, "Loader did not load object" self._sid = None self._loader = None elif update: try: self._historian.sync(self._obj) except exceptions.NotFound: pass # Object must never have been saved and is therefore up to date return self._obj def __eq__(self, other) -> bool: if not isinstance(other, ObjRef): return False if self._obj is not None: return id(self._obj) == id(other._obj) return self._sid == other._sid
[docs] def yield_hashables(self, hasher): if self._obj is not None: yield from hasher.yield_hashables(id(self._obj)) else: # This will also work if ref is None yield from hasher.yield_hashables(self._sid)
[docs] def save_instance_state(self, saver): if self._obj is not None: ref = saver.ref(self._obj) else: ref = self._sid if ref is not None: return ref.to_dict() return None
[docs] def load_instance_state(self, saved_state, loader): super(ObjRef, self).load_instance_state(saved_state, loader) # Rely on class default values for members if saved_state is not None: if isinstance(saved_state, list): # Legacy version self._sid = records.SnapshotId(*saved_state) else: # New version is dict self._sid = records.SnapshotId(**saved_state) self._loader = loader
HISTORIAN_TYPES = (ObjRef,)