![]() |
Some explanations on the aspects module |
Some explanations on the aspects module1. The main parts
2. Defining a PointcutWhen you want to weave an aspect on an entire class, or module, you will directly use the weave_methods or weave_module methods. But, when you want to weave an aspect only in a part of the class (i.e. not on all methods), then what you'll have to do is to create a PointCut's instance, and then call the weave_pointcut method. A PointCut (in this package), is basically a dictionnary with instances or classes as keys, and the list of method's names which you want weave an aspect on. As PointCut inherits the 'dict' Python base type, you can directly defines its keys and values, though it is recommended to use the provided methods :
When the pointcut is created, then you just have to weave the aspect on it by doing :
weaver.weave_pointcut(pointcut, aspect_class)
3. A simple use case(Taken from logger_example.py) :
# Import the weaver and the aspect to use
from logilab.aspects.weaver import weaver
from logilab.aspects.lib.logger import LoggerApsect
import sys
stack = StackImpl()
# Push an element on the stack, the method call is not traced
stack.push("an element")
# Weave aspect code (log will be done on sys.stderr)
weaver.weave_methods(stack, LoggerAspect, sys.stderr)
# Push an other element, method call will now be traced
stack.push("another element")
# Unweave logger aspect
weaver.unweave(stack, LoggerAspect)
# Now, call methods aren't traced anymore
stack.push("a third element")
In this example, we have weaved an aspect on a given instance. As a consequence, other instances of the same class will not be aspected. The best way of weaving all class instances, is to weave the aspect directly on the class, not on the instances. The syntax is exactly the same :
weaver.weave_methods(StackImpl, LoggerAspect, sys.stderr)
4. Creating your own aspectsFor now, it's only possible to wrap methods, not attribute accesses. To create a new aspect, you must define a class which inherits from AbstractAspect (in aspects.core), and define before(), after() and around() methods. Note that you can choose to override only one of this three methods since the default behaviour is to "simply pass". It is important, when overriding the around method to explicitly call self._proceed(...) which is the effective call to the wrapped method. Let's write a simple aspect which will write BEFORE before the method call and AFTER after.
from logilab.aspects.core import AbstractAspect
class SimpleAspect(AbstractAspect):
def before(self, wobj, context, *args, **kwargs):
"""Before method
"""
print "BEFORE ",context['method_name']
def after(self, wobj, context, *args, **kwargs):
"""After method.
print the return value
"""
print "AFTER ",self.method_name,", return value is ", context['ret_v']
This example is quite simple, and is not really useful, but it should show how to define your own aspects. Here is some information on the above code:
IMPORTANT : The weaver is a Singleton that holds all informations related to the weaving, for instance which method is weaved, which aspect it's weaved with, etc.. When an aspect is weaved on a method, the weaver will look is that aspect has already been instantiated, and in that case, it will use that aspect's instance to weave code around the method. This will soon be changed because it can be unconvenient. (aspects behave a bit like Singleton). 5. Examples of aspects provided by the moduleThe aspects module contains some useful aspects like :
6. More information about AOPHere is a set of useful links for Aspect Oriented Programming:
7. DownloadThe aspect aspects module can be downloaded from Logilab's ftp site. You will find the source distribution and some debian packages. To install it from the source distribution, just type python setup.py install after having unzipped the archive. 8. FeedbackPlease send any comment, patch or question to the python-projects mailing-list. |