WIP
parent
b0ab3694e3
commit
60f402ceee
|
@ -0,0 +1,112 @@
|
|||
import weakref
|
||||
import collections
|
||||
|
||||
from objectbroker.Persistence import Persistence,NoPersistence
|
||||
|
||||
class Serializer:
|
||||
"""Base class for object serialization with support for persistence"""
|
||||
|
||||
def __init__(self, objStore, objCache = weakref.WeakValueDictionary() ):
|
||||
self.__objStore = objStore
|
||||
self.__objCache = objCache
|
||||
|
||||
|
||||
def serialize(self, o):
|
||||
slist = {}
|
||||
state = self.objectToState( o, slist )
|
||||
self.__objStore.save(state, slist)
|
||||
|
||||
def unserialize(self, pid):
|
||||
o = self.objectFromCache( pid )
|
||||
if o is None:
|
||||
state = self.__objStore.load( pid )
|
||||
o = self.stateToObject( state )
|
||||
return o
|
||||
|
||||
def objectToState(self, o, states = {} ):
|
||||
"""Create a state dict for an object <o>.
|
||||
Returns the state dict.
|
||||
After method returns, <states> will contain entries for all referenced persistent objects."""
|
||||
|
||||
if not isinstance(o, Persistence):
|
||||
raise TypeError("needs to be based on Persistence class to be used as persistent object")
|
||||
|
||||
if Persistence._persistence_id( o ) in states:
|
||||
return states[ Persistence._persistence_id( o ) ]
|
||||
|
||||
state = {}
|
||||
state["pid"] = Persistence._persistence_id( o )
|
||||
state["module"] = o.__class__.__module__
|
||||
state["class"] = o.__class__.__name__
|
||||
state["fields"] = {}
|
||||
state["pfields"] = {}
|
||||
|
||||
nopersistence = self.collectClassAttribute(o.__class__,"NOPERSIST")
|
||||
persistnone = self.collectClassAttribute(o.__class__,"PERSISTNONE")
|
||||
|
||||
states[ state["pid"] ] = state
|
||||
|
||||
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] = a
|
||||
elif n in persistnone:
|
||||
state["fields"][n] = None
|
||||
elif (isinstance( a, Persistence)):
|
||||
state["pfields"][n] = self.objectToState( a, states )["pid"]
|
||||
else:
|
||||
state["fields"][n] = a
|
||||
|
||||
return state
|
||||
|
||||
def stateToObject(self, state):
|
||||
"""Returns an object that is constructed of the given state.
|
||||
If the cache already holds a reference to an object with the same persistence id,
|
||||
this reference is returned without any alternation of the object."""
|
||||
|
||||
o = self.objFromCache( state["pid"] )
|
||||
if not o is None:
|
||||
return o
|
||||
|
||||
m = __import__(state["module"],fromlist=[state["class"]])
|
||||
cls = getattr(m, state["class"] )
|
||||
o = cls.__new__(cls)
|
||||
|
||||
objToCache( o, state["pid"] )
|
||||
|
||||
for n in state["fields"]:
|
||||
setattr( o, n, state["fields"][n] )
|
||||
|
||||
for n in state["pfields"]:
|
||||
setattr( o, n, self.stateToObject( state["pfields"][n] ))
|
||||
|
||||
return o
|
||||
|
||||
def objFromCache(self, pid):
|
||||
if not self.__objCache is None:
|
||||
if pid in self.__objCache:
|
||||
return self.__objCache[ pid ]
|
||||
return None
|
||||
|
||||
def objToCache(self, o, pid = None):
|
||||
if pid is None:
|
||||
pid = Persistence._persistence_id( o )
|
||||
|
||||
if not self.__objCache is None:
|
||||
if not pid in self.__objCache:
|
||||
self.__objCache[ pid ] = o
|
||||
|
||||
def collectClassAttribute(self, c, name, default = set() ):
|
||||
collection = default
|
||||
classes = (self.__class__,) + self.__class__.__bases__
|
||||
|
||||
for clazz in classes:
|
||||
if hasattr(clazz, name):
|
||||
if isinstance( collection, dict ):
|
||||
collection.update( getattr( clazz, name ) )
|
||||
else:
|
||||
collection = collection + getattr( clazz, name )
|
||||
|
||||
return collection
|
|
@ -0,0 +1,20 @@
|
|||
from objectbroker.Serializer import Serializer
|
||||
|
||||
import os
|
||||
import os.path
|
||||
|
||||
class XMLSerializer(Serializer):
|
||||
|
||||
def __init__(self, path, objCache = None):
|
||||
Serializer.__init__(self, objCache)
|
||||
|
||||
def serialize(self, o):
|
||||
raise Exception("Serializer needs to be subclassed")
|
||||
|
||||
def unserialize(self, bytes):
|
||||
raise Exception("Serializer needs to be subclassed")
|
||||
|
||||
def serializeState(self, state){
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
import xml.etree.ElementTree as ET
|
||||
import pickle
|
||||
import os
|
||||
import os.path
|
||||
import base64
|
||||
|
||||
class XMLStore:
|
||||
|
||||
def __init__(self, path, splitFiles = None):
|
||||
if splitFiles is None:
|
||||
splitFiles = path is None or os.path.isdir( path )
|
||||
|
||||
self.__path = path
|
||||
self.__split = splitFiles
|
||||
|
||||
self.__xml = None
|
||||
|
||||
def save(self, state, persistentStates = {}, xml = None):
|
||||
print("save(self,{0},{1})".format(state,persistentStates))
|
||||
|
||||
po = ET.Element("PersistentObject")
|
||||
po.attrib["id"] = state["pid"]
|
||||
po.attrib["class"] = state["class"]
|
||||
po.attrib["module"] = state["module"]
|
||||
|
||||
for field in state["fields"]:
|
||||
attr = ET.SubElement(po,"Attribute")
|
||||
attr.attrib["name"] = field
|
||||
attr.attrib["protocol"] = "pickle"
|
||||
attr.text = base64.b64encode( pickle.dumps(state["fields"][field]) ).decode("utf-8")
|
||||
|
||||
for pfield in state["pfields"]:
|
||||
attr = ET.SubElement(po,"Attribute")
|
||||
attr.attrib["name"] = pfield
|
||||
attr.attrib["protocol"] = "persistence"
|
||||
attr.text = state["pfields"][pfield]
|
||||
|
||||
if xml is None:
|
||||
xml = ET.Element("PersistentObjects")
|
||||
xml.attrib["root"] = state["pid"]
|
||||
|
||||
xml.append( po )
|
||||
|
||||
for pstate in persistentStates:
|
||||
ps = persistentStates[ pstate ]
|
||||
if not ps == state:
|
||||
self.save( ps, xml = xml )
|
||||
|
||||
self.__xml = xml
|
||||
|
||||
def load(self, pid):
|
||||
pass
|
||||
|
||||
def lastXml(self):
|
||||
return self.__xml
|
|
@ -1,6 +1,10 @@
|
|||
from objectbroker.persistence import Persistence,NoPersistence
|
||||
from objectbroker.objectstore import DiscObjectStore
|
||||
from objectbroker.objectbroker import ObjectBroker
|
||||
from objectbroker.aquisition import Aquisition, AquisitionProxy
|
||||
from objectbroker.Persistence import Persistence,NoPersistence
|
||||
|
||||
from objectbroker.Serializer import Serializer
|
||||
from objectbroker.XMLStore import XMLStore
|
||||
|
||||
from objectbroker.ObjectStore import DiscObjectStore
|
||||
from objectbroker.ObjectBroker import ObjectBroker
|
||||
from objectbroker.Aquisition import Aquisition, AquisitionProxy
|
||||
from objectbroker.Proxy import InterceptedProxy
|
||||
|
||||
|
|
Loading…
Reference in New Issue