+ tx.postcommit(lambda: self.store.icache.__setitem__((obj, self), val))
+
+ def loaded(self, id, obj, tx):
+ vals = frozenset(self.__get__(obj, None))
+ tx.postcommit(lambda: self.store.icache.__setitem__((obj, self), vals))
+
+class compound(base):
+ def __init__(self, indextype, name, *parts):
+ super().__init__(parts[0].store, indextype, name, index.compound(*(part.typ for part in parts)))
+ self.parts = parts
+
+ def minim(self, *parts):
+ return self.typ.minim(*parts)
+ def maxim(self, *parts):
+ return self.typ.maxim(*parts)
+
+ def get(self, *, partial=None, **spec):
+ if partial is not None:
+ return super().get(ge=self.minim(*partial), le = self.maxim(*partial), **spec)
+ else:
+ return super().get(**spec)
+
+ def register(self, id, obj, tx):
+ val = tuple(part.__get__(obj, None) for part in self.parts)
+ self.index(tx).put(val, id, tx=tx)
+ tx.postcommit(lambda: self.store.icache.__setitem__((obj, self), val))
+
+ def unregister(self, id, obj, tx):
+ self.index(tx).remove(self.store.icache[obj, self], id, tx=tx)
+ tx.postcommit(lambda: self.store.icache.__delitem__((obj, self)))
+
+ def update(self, id, obj, tx):
+ val = tuple(part.__get__(obj, None) for part in self.parts)
+ ival = self.store.icache[obj, self]
+ if val != ival:
+ idx = self.index(tx)
+ idx.remove(ival, id, tx=tx)
+ idx.put(val, id, tx=tx)
+ tx.postcommit(lambda: self.store.icache.__setitem__((obj, self), val))
+
+ def loaded(self, id, obj, tx):
+ val = tuple(part.__get__(obj, None) for part in self.parts)
+ tx.postcommit(lambda: self.store.icache.__setitem__((obj, self), val))
+
+class idlink(object):
+ def __init__(self, name, atype):
+ self.atype = atype
+ self.battr = "__idlink_%s" % name
+
+ def __get__(self, obj, cls):
+ if obj is None: return self
+ ret = self.atype.store.get(getattr(obj, self.battr))
+ assert isinstance(ret, self.atype)
+ return ret
+
+ def __set__(self, obj, val):
+ assert isinstance(val, self.atype)
+ setattr(obj, self.battr, val.id)
+
+ def __delete__(self, obj):
+ delattr(obj, self.battr)