Initial Commit

master
Harald Wolff 2018-03-09 11:52:20 +01:00
commit 10246f0713
7 changed files with 382 additions and 0 deletions

2
.gitignore vendored 100644
View File

@ -0,0 +1,2 @@
.DS_Store
*.pyc

View File

@ -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") )

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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()

View File

@ -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