Description:
Aspects can be used to add some extra behavior to functions or methods. This behavior is added at runtime and can be useful for things like logging, tracking references and even security.
Source: Text Source
import sys
class Aspect(object):
"""Aspect defines the aspect interface that should be implemented by
aspects.
"""
def __init__(self, method):
"""This method takes the optional arguments given to the
weave_method() function.
"""
pass
def before(self):
"""Code executed before the weaved method is executed.
"""
pass
def after(self, retval, exc):
"""Code executed after the weaved methid has been executed.
"""
pass
def weave_method(method, advice_class, *advice_args, **advice_kwargs):
advice = advice_class(method, *advice_args, **advice_kwargs)
advice_before = advice.before
advice_after = advice.after
def invoke_advice(*args, **kwargs):
advice_before()
try:
retval = method(*args, **kwargs)
except Exception, e:
advice_after(None, e)
raise
else:
advice_after(retval, None)
return retval
try:
class_ = method.im_class
except:
method.func_globals[method.func_name] = invoke_advice
else:
setattr(class_, method.__name__, invoke_advice)
return invoke_advice
class LoggerAspect(Aspect):
def __init__(self, method):
self.method = method
def before(self):
print 'entering', self.method
def after(self, retval, exc):
print 'leaving', self.method,
if exc:
print 'with exception %s(%s)' % (exc.__class__, exc)
else:
print 'with return value', retval
class ReferenceAspect(Aspect):
"""This reference keeps track of objects created by a method.
A weak reference to those objects is created and appended to reflist.
"""
def __init__(self, method, reflist):
self.method = method
self.reflist = reflist
def after(self, retval, exc):
import weakref
if retval:
self.reflist.append(weakref.ref(retval))
if __name__ == '__main__':
def test_func(arg1, arg2):
print 'test_func(): arg1:', arg1, ', arg2:', arg2
weave_method(test_func, LoggerAspect)
print 'testing test_func()'
test_func('a', 'b')
class TestClass(object):
def test_meth(self, arg1, arg2):
print 'TestClass.test_meth(): arg1:', arg1, ', arg2:', arg2
def test_exc(self):
raise ValueError, 'HELP'
weave_method(TestClass.test_meth, LoggerAspect)
weave_method(TestClass.test_exc, LoggerAspect)
tc = TestClass()
tc.test_meth(1, 2)
try:
tc.test_exc()
except ValueError, e:
print 'Caught expected exception', e
import traceback
traceback.print_exc()
else:
raise 'HUH'
Discussion:
I use this aspects module mainly for debugging. You can keep track of items using the ReferenceAspect (if you create your objects using some sort of factory). The LoggerAspect is handy if you want to know when a certain function or method is called.
|