150 lines
3.4 KiB
Python
150 lines
3.4 KiB
Python
import weakref
|
|
import collections
|
|
import pickle
|
|
|
|
from simplelog import log,LLDEBUGCALL,LLDEBUG,LLINFO,LLERROR
|
|
from objectbroker import Persistence,NoPersistence
|
|
|
|
def dump_state(state):
|
|
print("Persistent ID: %s" % (state["pid"],))
|
|
print("Type: %s.%s" % (state["module"],state["class"]))
|
|
|
|
print("Non-Persistent:")
|
|
for n in state["fields"].keys():
|
|
print("K: %s = %s" % (n,state["fields"][n]))
|
|
|
|
print("Persistent:")
|
|
for n in state["pfields"].keys():
|
|
print("K: %s = %s" % (n,state["pfields"][n]))
|
|
print("")
|
|
|
|
def obj_getstate(o):
|
|
if not isinstance(o, Persistence):
|
|
raise TypeError("obj_getstate() needs Persistence object")
|
|
|
|
state = {}
|
|
state["pid"] = Persistence._persistence_id( o )
|
|
state["module"] = o.__class__.__module__
|
|
state["class"] = o.__class__.__name__
|
|
state["fields"] = {}
|
|
state["pfields"] = {}
|
|
state["pvalues"] = {}
|
|
|
|
nopersistence = getattr(o,"NOPERSIST",())
|
|
|
|
|
|
d = object.__getattribute__(o, "__dict__")
|
|
for n in d.keys():
|
|
a = getattr( o, n )
|
|
if (not isinstance( a, collections.Callable)) or isinstance( a, object ):
|
|
if (isinstance( a, NoPersistence)) or (n in nopersistence):
|
|
state["fields"][n] = None
|
|
elif (isinstance( a, Persistence)):
|
|
state["pvalues"][n] = a
|
|
state["pfields"][n] = Persistence._persistence_id( a )
|
|
else:
|
|
state["fields"][n] = a
|
|
|
|
return state
|
|
|
|
|
|
class ObjectBroker:
|
|
"""ObjectBroker """
|
|
|
|
def __init__(self, store={}):
|
|
self.__store = store
|
|
self.__cache = weakref.WeakValueDictionary()
|
|
self.__unsaved = {}
|
|
|
|
log("ObjectBroker instantiated", LLDEBUGCALL)
|
|
self.check()
|
|
|
|
def save(self,o,recursed=False):
|
|
|
|
if (o in self.__unsaved):
|
|
return
|
|
|
|
state = obj_getstate(o)
|
|
# dump_state( state )
|
|
|
|
self.__cache[ state["pid"] ] = o
|
|
self.__unsaved[o] = state
|
|
|
|
for pn in state["pvalues"]:
|
|
self.save( state["pvalues"][pn], recursed=True )
|
|
|
|
# dump_state(state)
|
|
|
|
if not recursed:
|
|
|
|
for n in list( self.__unsaved.keys() ):
|
|
s = self.__unsaved[n]
|
|
s["pvalues"] = None
|
|
try:
|
|
self.__store[ s["pid"] ] = pickle.dumps(s)
|
|
del self.__unsaved[n]
|
|
except AttributeError as ae:
|
|
log("AttributeError while storing object: %s" % (s,))
|
|
|
|
return state["pid"]
|
|
|
|
def load(self,persistence_id):
|
|
|
|
if (persistence_id in self.__cache):
|
|
o = self.__cache[persistence_id]
|
|
if not o is None:
|
|
return o
|
|
|
|
state = pickle.loads(self.__store[ persistence_id ])
|
|
dump_state(state)
|
|
|
|
m = __import__(state["module"],fromlist=[state["class"]])
|
|
cls = getattr(m, state["class"] )
|
|
|
|
o = cls.__new__(cls)
|
|
|
|
self.__cache[ persistence_id ] = o
|
|
|
|
for n in state["fields"]:
|
|
setattr( o, n, state["fields"][n] )
|
|
|
|
for n in state["pfields"]:
|
|
print("SS: %s = %s" % (n,state["pfields"][n]))
|
|
setattr( o, n, self.load( state["pfields"][n] ))
|
|
|
|
return o
|
|
|
|
|
|
|
|
def remove(self,o=None,persistence_id=None):
|
|
pass
|
|
|
|
def check(self):
|
|
log("ObjectBroker: checking consistency of store",LLINFO)
|
|
|
|
clean = True
|
|
|
|
for uid in dir(self.__store):
|
|
if not uid == "ROOT":
|
|
try:
|
|
state = pickle.loads(self.__store[ uid ])
|
|
for n in state["pfields"]:
|
|
if not state["pfields"][n] in self.__store:
|
|
log("Found Object {0} referencing non-existent {1} = {2}".format(uid,n,state["pfields"][n]))
|
|
clean = False
|
|
except:
|
|
clean = False
|
|
|
|
# if not clean:
|
|
# log("ObjectBroker: consistency check failed!",LLERROR)
|
|
# raise Exception("ObjectBroker not consistent")
|
|
|
|
log("ObjectBroker: consistency check successful",LLINFO)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|