from . import store, lib, index
from .store import storedesc
-__all__ = ["simple", "multi", "compound"]
+__all__ = ["simple", "multi", "compound", "idlink"]
class cursor(lib.closable):
def __init__(self, bk, st):
self.idx = None
self.lk = threading.Lock()
- def index(self):
+ def index(self, tx):
with self.lk:
if self.idx is None:
- self.idx = self.indextype(self.store.db(), self.name, self.typ)
+ self.idx = self.indextype(self.store.db(), self.name, self.typ, tx=tx)
return self.idx
def get(self, **kwargs):
- return cursor(self.index().get(**kwargs), self.store)
+ return cursor(self.index(None).get(**kwargs), self.store)
def get1(self, *, check=False, default=KeyError, **kwargs):
with self.get(**kwargs) as cursor:
def __init__(self, store, indextype, name, datatype, default):
super().__init__(store, indextype, name, datatype)
self.default = default
- self.mattr = "__idx_%s_new" % name
- self.iattr = "__idx_%s_cur" % name
+ self.mattr = "__ival_%s" % name
def __get__(self, obj, cls):
if obj is None: return self
def register(self, id, obj, tx):
val = self.__get__(obj, None)
- self.index().put(val, id, tx=tx)
- tx.postcommit(lambda: setattr(obj, self.iattr, val))
+ 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().remove(getattr(obj, self.iattr), id, tx=tx)
- tx.postcommit(lambda: delattr(obj, self.iattr))
+ 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 = self.__get__(obj, None)
- ival = getattr(obj, self.iattr)
+ ival = self.store.icache[obj, self]
if val != ival:
- idx = self.index()
+ idx = self.index(tx)
idx.remove(ival, id, tx=tx)
idx.put(val, id, tx=tx)
- tx.postcommit(lambda: setattr(obj, self.iattr, val))
+ tx.postcommit(lambda: self.store.icache.__setitem__((obj, self), val))
+
+ def loaded(self, id, obj, tx):
+ val = self.__get__(obj, None)
+ tx.postcommit(lambda: self.store.icache.__setitem__((obj, self), val))
class multi(descbase):
def __init__(self, store, indextype, name, datatype):
def register(self, id, obj, tx):
vals = frozenset(self.__get__(obj, None))
- idx = self.index()
+ idx = self.index(tx)
for val in vals:
idx.put(val, id, tx=tx)
- tx.postcommit(lambda: setattr(obj, self.iattr, vals))
+ tx.postcommit(lambda: self.store.icache.__setitem__((obj, self), vals))
def unregister(self, id, obj, tx):
- idx = self.index()
- for val in getattr(obj, self.iattr):
+ idx = self.index(tx)
+ for val in self.store.icache[obj, self]:
idx.remove(val, id, tx=tx)
- tx.postcommit(lambda: delattr(obj, self.iattr))
+ tx.postcommit(lambda: self.store.icache.__delitem__((obj, self)))
def update(self, id, obj, tx):
vals = frozenset(self.__get__(obj, None))
- ivals = getattr(obj, self.iattr)
+ ivals = self.store.icache[obj, self]
if vals != ivals:
- idx = self.index()
+ idx = self.index(tx)
for val in ivals - vals:
idx.remove(val, id, tx=tx)
for val in vals - ivals:
idx.put(val, id, tx=tx)
- tx.postcommit(lambda: setattr(obj, self.iattr, vals))
+ 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
- self.iattr = "__idx_%s_cur" % name
def minim(self, *parts):
return self.typ.minim(*parts)
def register(self, id, obj, tx):
val = tuple(part.__get__(obj, None) for part in self.parts)
- self.index().put(val, id, tx=tx)
- tx.postcommit(lambda: setattr(obj, self.iattr, val))
+ 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().remove(getattr(obj, self.iattr), id, tx=tx)
- tx.postcommit(lambda: delattr(obj, self.iattr))
+ 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 = getattr(obj, self.iattr)
+ ival = self.store.icache[obj, self]
if val != ival:
- idx = self.index()
+ idx = self.index(tx)
idx.remove(ival, id, tx=tx)
idx.put(val, id, tx=tx)
- tx.postcommit(lambda: setattr(obj, self.iattr, val))
+ 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)