You can decorate each function with a cake decorator, something like
@transaction def insertData(self):
and the transaction is a decorator that you define to wrap the function with pre and post. Yes, you have to do this for every function. Here is an example
def transaction(f): def pre(): print "pre transaction" def post(): print "post transaction" def wrapped(*args): pre() f(*args) post() return wrapped class Foo(object): def __init__(self): print "instantiating" def doFoo(self): print "doing foo" @transaction def doBar(self, value): print "doing bar "+str(value) @transaction def foofunc(): print "hello" foofunc() f=Foo() f.doFoo() f.doBar(5)
.
stefanos-imac:python borini$ python decorator.py pre transaction hello post transaction instantiating doing foo pre transaction doing bar 5 post transaction
An alternative is to use a metaclass, for example:
import types class DecoratedMetaClass(type): def __new__(meta, classname, bases, classDict): def pre(): print "pre transaction" def post(): print "post transaction" newClassDict={} for attributeName, attribute in classDict.items(): if type(attribute) == types.FunctionType: def wrapFunc(f): def wrapper(*args): pre() f(*args) post() return wrapper newAttribute = wrapFunc(attribute) else: newAttribute = attribute newClassDict[attributeName] = newAttribute return type.__new__(meta, classname, bases, newClassDict) class MyClass(object): __metaclass__ = DecoratedMetaClass def __init__(self): print "init" def doBar(self, value): print "doing bar "+str(value) def doFoo(self): print "doing foo" c = MyClass() c.doFoo() c.doBar(4)
This is pure black magic, but it works.
stefanos-imac:python borini$ python metaclass.py pre transaction init post transaction pre transaction doing foo post transaction pre transaction doing bar 4 post transaction
Usually you do not want to decorate __init__
, and you can only decorate these methods with a special name, so you might want to replace
for attributeName, attribute in classDict.items(): if type(attribute) == types.FunctionType:
with something like
for attributeName, attribute in classDict.items(): if type(attribute) == types.FunctionType and "trans_" in attributeName[0:6]:
Thus, only methods called trans_whatever will be processed.