Initial Commit
commit
10246f0713
|
@ -0,0 +1,2 @@
|
|||
.DS_Store
|
||||
*.pyc
|
|
@ -0,0 +1,62 @@
|
|||
|
||||
def getter(attrib):
|
||||
return lambda self, *args, **kwargs: getattr(object.__getattribute__( self, "_o"), attrib)(*args, **kwargs)
|
||||
|
||||
|
||||
class InterceptedProxy:
|
||||
_special_names=[
|
||||
'__abs__', '__add__', '__and__', '__call__', '__cmp__', '__coerce__',
|
||||
'__contains__', '__delitem__', '__delslice__', '__div__', '__divmod__',
|
||||
'__eq__', '__float__', '__floordiv__', '__ge__', '__getitem__',
|
||||
'__getslice__', '__gt__', '__hash__', '__hex__', '__iadd__', '__iand__',
|
||||
'__idiv__', '__idivmod__', '__ifloordiv__', '__ilshift__', '__imod__',
|
||||
'__imul__', '__int__', '__invert__', '__ior__', '__ipow__', '__irshift__',
|
||||
'__isub__', '__iter__', '__itruediv__', '__ixor__', '__le__', '__len__',
|
||||
'__long__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__',
|
||||
'__neg__', '__oct__', '__or__', '__pos__', '__pow__', '__radd__',
|
||||
'__rand__', '__rdiv__', '__rdivmod__', '__reduce__', '__reduce_ex__',
|
||||
'__repr__', '__reversed__', '__rfloorfiv__', '__rlshift__', '__rmod__',
|
||||
'__rmul__', '__ror__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__',
|
||||
'__rtruediv__', '__rxor__', '__setitem__', '__setslice__', '__sub__',
|
||||
'__truediv__', '__xor__', 'next',
|
||||
]
|
||||
|
||||
def _get_proxy_cls(cls,obj):
|
||||
ocls = obj.__class__
|
||||
ns = {}
|
||||
|
||||
for n in InterceptedProxy._special_names:
|
||||
if (hasattr(ocls, n)):
|
||||
ns[n] = getter(n)
|
||||
return type( "InterceptedProxy(%s)" % (ocls.__name__,), (cls,), ns )
|
||||
|
||||
def __new__(cls,obj,listener):
|
||||
pcls = InterceptedProxy._get_proxy_cls(cls,obj)
|
||||
|
||||
inst = object.__new__( pcls )
|
||||
object.__setattr__( inst, "_o", obj)
|
||||
object.__setattr__( inst, "_l", listener)
|
||||
|
||||
return inst
|
||||
|
||||
def __getattribute__(self,name):
|
||||
v = getattr( object.__getattribute__( self, "_o"), name )
|
||||
return v
|
||||
|
||||
def __setattr__(self,name,value):
|
||||
o = object.__getattribute__( self, "_o")
|
||||
setattr( o, name, value )
|
||||
object.__getattribute__( self, "_l").notify("__setattr__",o,name,value)
|
||||
|
||||
def __delattr__(self,name):
|
||||
delattr( object.__getattribute__( self, "_o"), name )
|
||||
|
||||
def __nonzero__(self):
|
||||
return bool(object.__getattribute__(self, "_o"))
|
||||
def __str__(self):
|
||||
return str(object.__getattribute__(self, "_o"))
|
||||
def __repr__(self):
|
||||
return repr(object.__getattribute__(self, "_o"))
|
||||
def __dir__(self):
|
||||
return dir( object.__getattribute__(self, "_o") )
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
from objectbroker.persistence import Persistence,NoPersistence
|
||||
from objectbroker.objectstore import DiscObjectStore
|
||||
from objectbroker.objectbroker import ObjectBroker
|
||||
from objectbroker.aquisition import Aquisition, AquisitionProxy
|
||||
from objectbroker.Proxy import InterceptedProxy
|
||||
|
|
@ -0,0 +1,161 @@
|
|||
import collections
|
||||
|
||||
__doc__ = """Einfache Objekt Aquisition für Python."""
|
||||
|
||||
class Aquisition:
|
||||
"""Markiert ein Objekt als Ziel von Aquisition durch AquisitionProxy"""
|
||||
pass
|
||||
|
||||
|
||||
def caller(inst,a):
|
||||
return lambda *args,**kwargs: a.__func__(inst,*args,**kwargs)
|
||||
|
||||
def call(self,method,*args,**kwargs):
|
||||
m = getattr(object.__getattribute__( self, "_o"), method)
|
||||
if hasattr(m,"__func__"):
|
||||
return m.__func__(self,*args,**kwargs)
|
||||
else:
|
||||
return m(*args,**kwargs)
|
||||
|
||||
def getter(attrib):
|
||||
return lambda self, *args, **kwargs: call(self,attrib,*args, **kwargs)
|
||||
|
||||
if hasattr(m, "__func__"):
|
||||
return lambda self, *args, **kwargs: m.__func__(self, *args, **kwargs)
|
||||
else:
|
||||
return lambda self, *args, **kwargs: m(*args, **kwargs)
|
||||
|
||||
|
||||
class AquisitionProxy:
|
||||
"""Basisobjekt für Aquisition."""
|
||||
_special_names=[
|
||||
'__abs__', '__add__', '__and__', '__call__', '__cmp__', '__coerce__',
|
||||
'__contains__', '__delitem__', '__delslice__', '__div__', '__divmod__',
|
||||
'__eq__', '__float__', '__floordiv__', '__ge__', '__getitem__',
|
||||
'__getslice__', '__gt__', '__hash__', '__hex__', '__iadd__', '__iand__',
|
||||
'__idiv__', '__idivmod__', '__ifloordiv__', '__ilshift__', '__imod__',
|
||||
'__imul__', '__int__', '__invert__', '__ior__', '__ipow__', '__irshift__',
|
||||
'__isub__', '__iter__', '__itruediv__', '__ixor__', '__le__', '__len__',
|
||||
'__long__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__',
|
||||
'__neg__', '__oct__', '__or__', '__pos__', '__pow__', '__radd__',
|
||||
'__rand__', '__rdiv__', '__rdivmod__', '__reduce__', '__reduce_ex__',
|
||||
'__repr__', '__reversed__', '__rfloorfiv__', '__rlshift__', '__rmod__',
|
||||
'__rmul__', '__ror__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__',
|
||||
'__rtruediv__', '__rxor__', '__setitem__', '__setslice__', '__sub__',
|
||||
'__truediv__', '__xor__', 'next',
|
||||
]
|
||||
|
||||
def _get_proxy_cls(cls,obj):
|
||||
ocls = obj.__class__
|
||||
ns = {}
|
||||
_methods = {}
|
||||
|
||||
for n in AquisitionProxy._special_names:
|
||||
if (hasattr(ocls, n)):
|
||||
ns[n] = getter(n)
|
||||
|
||||
return type( "AProxy(%s)" % (ocls.__name__,), (cls,), ns )
|
||||
|
||||
|
||||
def __new__(cls,obj,p = None,aq_name=None,aq_root=None):
|
||||
pcls = AquisitionProxy._get_proxy_cls(cls,obj)
|
||||
|
||||
inst = object.__new__( pcls )
|
||||
|
||||
_methods = {}
|
||||
for n in dir(obj):
|
||||
# print("AQ_ATTR: %s" % (n,))
|
||||
a = getattr(obj,n)
|
||||
if isinstance( a, collections.Callable ) and hasattr( a, "__func__" ): # and not hasattr( AquisitionProxy, n ):
|
||||
# print("AQ_METHOD: %s = %s" % (n,a))
|
||||
_methods[n] = caller(inst,a)
|
||||
|
||||
object.__setattr__( inst, "_methods", _methods )
|
||||
object.__setattr__( inst, "_o", obj)
|
||||
object.__setattr__( inst, "_p", p)
|
||||
object.__setattr__( inst, "_aq_name", aq_name)
|
||||
|
||||
if (aq_root is None):
|
||||
aq_root = inst
|
||||
|
||||
object.__setattr__( inst, "_aq_root", aq_root)
|
||||
|
||||
return inst
|
||||
|
||||
def __getattribute__(self,name):
|
||||
v = None
|
||||
# print("AQN: %s" % (name,))
|
||||
|
||||
if name.startswith("_aq_"):
|
||||
if (name == "_aq_parent"):
|
||||
return object.__getattribute__( self, "_p")
|
||||
# return AquisitionProxy( p, self, aq_name=p._aq_name, aq_root=self._aq_root )
|
||||
if (name == "_aq_name"):
|
||||
n = object.__getattribute__( self, "_aq_name")
|
||||
if n is None:
|
||||
return "/"
|
||||
return n
|
||||
if (name == "_aq_object"):
|
||||
return object.__getattribute__( self, "_o")
|
||||
|
||||
return object.__getattribute__( self, name )
|
||||
|
||||
_methods = object.__getattribute__(self,"_methods")
|
||||
if name in _methods:
|
||||
return _methods[name]
|
||||
|
||||
try:
|
||||
v = getattr( object.__getattribute__( self, "_o"), name )
|
||||
except AttributeError as ae:
|
||||
try:
|
||||
print("AQN_PARENT: %s %s" % (object.__getattribute__( self, "_p"), name))
|
||||
v = getattr( object.__getattribute__( self, "_p"), name)
|
||||
if (isinstance(v, AquisitionProxy)):
|
||||
v = object.__getattribute__( v, "_o" )
|
||||
except AttributeError as ae2:
|
||||
raise ae2
|
||||
|
||||
if isinstance( v, Aquisition ):
|
||||
v = AquisitionProxy( v, self, aq_name=name, aq_root=self._aq_root )
|
||||
|
||||
return v
|
||||
|
||||
def __setattr__(self,name,value):
|
||||
setattr( object.__getattribute__( self, "_o"), name, value )
|
||||
|
||||
def __delattr__(self,name):
|
||||
delattr( object.__getattribute__( self, "_o"), name )
|
||||
|
||||
def __nonzero__(self):
|
||||
return bool(object.__getattribute__(self, "_o"))
|
||||
def __str__(self):
|
||||
return str(object.__getattribute__(self, "_o"))
|
||||
def __repr__(self):
|
||||
return repr(object.__getattribute__(self, "_o"))
|
||||
|
||||
def __dir__(self):
|
||||
return dir( object.__getattribute__(self, "_o") )
|
||||
|
||||
def dir(self,cls):
|
||||
realcls = object.__getattribute__( self, "__class__" )
|
||||
|
||||
ls = []
|
||||
|
||||
for an in dir(self):
|
||||
if issubclass( getattr( self, an ).__class__, cls):
|
||||
ls.append(an)
|
||||
|
||||
if issubclass(realcls,AquisitionProxy):
|
||||
p = object.__getattribute__( self, "_p")
|
||||
if not p is None:
|
||||
for an in AquisitionProxy.dir(p, cls):
|
||||
if not an in ls:
|
||||
ls.append( an )
|
||||
|
||||
return ls
|
||||
|
||||
def _aq_path(self):
|
||||
if (self._aq_name is None) or (self._aq_parent is None):
|
||||
return ""
|
||||
return "%s/%s" % (self._aq_parent._aq_path(),self._aq_name)
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
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"] = {}
|
||||
|
||||
|
||||
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)):
|
||||
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)
|
||||
|
||||
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
|
||||
self.__store[ s["pid"] ] = pickle.dumps(s)
|
||||
del self.__unsaved[n]
|
||||
|
||||
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
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
import os
|
||||
|
||||
class DiscObjectStore:
|
||||
"""DiscObjectStore ist ein Mapping Objekt, welches ein Verzeichnis im Dateisystem als Speicher nutzt und somit persistent zwischen Programmstarts arbeitet"""
|
||||
def __init__(self,path = "./objects"):
|
||||
self._path = path
|
||||
self.check()
|
||||
|
||||
def check(self):
|
||||
if not os.path.exists( self._path ):
|
||||
os.makedirs( self._path )
|
||||
|
||||
def __contains__(self, name):
|
||||
return os.path.exists( "%s/%s" % (self._path, name))
|
||||
|
||||
def __getitem__(self, name):
|
||||
f = open("%s/%s" % (self._path, name), "rb")
|
||||
v = f.read()
|
||||
f.close()
|
||||
return v
|
||||
|
||||
def __setitem__(self, name, value):
|
||||
f = open("%s/%s" % (self._path, name), "wb")
|
||||
v = f.write(value)
|
||||
f.close()
|
|
@ -0,0 +1,11 @@
|
|||
import uuid
|
||||
|
||||
class Persistence:
|
||||
|
||||
def _persistence_id(self):
|
||||
if not hasattr(self, "__persistence_id__"):
|
||||
setattr( self, "__persistence_id__", uuid.uuid4().hex )
|
||||
return getattr( self, "__persistence_id__" )
|
||||
|
||||
class NoPersistence:
|
||||
pass
|
Loading…
Reference in New Issue