aspect-oriented programming

Pedro Rodriguez pedro_rodriguez at club-internet.fr
Tue Jan 22 10:29:18 EST 2002


"Mark McEahern" <marklists at mceahern.com> wrote:

> Pedro Rodriguez <pedro_rodriguez at club-internet.fr> wrote in message
> news:<pan.2002.01.13.11.22.54.248401.9857 at club-internet.fr>...
> 
>> Pre/Post/Around methods : I posted a simple implementation for this, à
>> la AspectJ (Java) and AspectR (Ruby). And comparing with AspectJ, I am
>> sure Python can provide that kind of implementation in simple and
>> elegant way, in comparison with the compiler and language modification
>> AspectJ introduces.
>>
>> This is an example of a patch to the current problem in Python 2.2...
> 
> Pedro, I'm very delighted to find the sample code (reposted at the
> bottom of this message) you posted previously showing an implemention of
> Aspect.  As you noted, the sample implementation does not work with
> new-style classes:
> 
>   class A(object):
>       def f(self, x):
>           print "real f", x
> 
>   aspect.wrap_around("around_advice", A, "f") a = A() a.f(1)
> 
> Did you have a fix for that?
> 

Now I have ;) Shameless-ly using Alex Martelli remark on nested scopes.
They are used here to do the closure on wrapper functions, no need for
the 'new' module in this case.

This works with python 2.1.x if nested scopes are set, and python 2.2 

BTW, I added also the ability to give more than one method name to be
wrapped in a class.

Next step : metaclasses as pointed by Alex ???

--------------------------------------------------------------------------
# XXX Python 2.1.X from __future__ import nested_scopes

class Aspect:
    def wrap_around(self, adviceName, cls, *methodNames):
        self.__wrap(AdviceAround, adviceName, cls, *methodNames)

    def wrap_before(self, adviceName, cls, *methodNames):
        self.__wrap(AdviceBefore, adviceName, cls, *methodNames)

    def wrap_after(self, adviceName, cls, *methodNames):
        self.__wrap(AdviceAfter, adviceName, cls, *methodNames)

    def __wrap(self, adviceClass, adviceName, cls, *methodNames):
        adviceMethod = getattr(self, adviceName)
        for methodName in methodNames:
            origMethod = getattr(cls, methodName)
            advice = adviceClass(adviceMethod, origMethod, methodName)
            setattr(cls, methodName, advice)


def AdviceAround(adviceMethod, origMethod, methodName):
    def wrap_around_method(*args, **kwargs):
        inst = args[0]
        adviceMethod(origMethod, methodName, inst, *args, **kwargs)

    return wrap_around_method

def AdviceBefore(adviceMethod, origMethod, methodName):
    def wrap_before_method(*args, **kwargs):
        inst = args[0]
        adviceMethod(origMethod, methodName, inst, *args, **kwargs)
        origMethod(*args, **kwargs)

    return wrap_before_method

def AdviceAfter(adviceMethod, origMethod, methodName):
    def wrap_after_method(*args, **kwargs):
        inst = args[0]
        origMethod(*args, **kwargs)
        adviceMethod(origMethod, methodName, inst, *args, **kwargs)

    return wrap_after_method
--------------------------------------------------------------------------


Regards,
-- 

Pedro









More information about the Python-list mailing list