From: Frank T. <ft...@ne...> - 2001-10-27 04:12:48
|
I'm fairly new to AOP, and was thinking about implementing my own toolkit for AOP and getting a project on SF for it, but I looked around and found your project partly-started, so I thought I'd nudge in and see what's happening. I've looked at AspectJ, and I really like its model of doing things. Consequently, I've started implementing a small black-box (run-time) aop module for Python aspects. Just now I've looked at AspectR, and found that it would be trivially easy to create something as advanced as AspectR (read: not very advanced), but its not going to be hard to make it decently (though not nearly as powerful as AspectJ, which has the advantage of analyzing and recompiling code). So, if you guys are still alive I'd like to start contributing my aspects implementation to Pythius since you have front-end ideas for AOP, like code-metrics (and that's great!). Aspects would be great to have on the backend (obviously, or else you wouldn't be thinking of putting them with Pythius). I'm attaching my rough implementation test code. Below is some ideas on the design I'm starting with: class Pointcut: |--MethodPointcut |--SetattrPointcut |-- ... (more pointcuts we provide) Pointcut instantiations know about integrating into certain types of code. For instance, the MethodPointcut knows how to put after/before hooks around a method. You can instantiate a MethodPointcut with: mypointcut = MethodPointcut(myclass.mymethod) class Aspect: |--MyLoggingAspect |--MyOtherAspect |--... (more aspects defined by user) There is an abstract class Aspect, which users writing aspects subclass from. Abstract methods include "after", "before", etc. Right now, my implementation just passes these calls off to the Pointcut to install the user-desired before/after code. The aspect gets "turned on" when an object of the class is initialized (e.g., it happens in an object constructor). Below is an example user-defined aspect that used in the attached code: class Logging(Aspect): """Just a sample test Aspect""" def __init__(self): addition = MethodPointcut(Student.add) self.before(addition, self.log) self.after(addition, self.log) self.around(addition, self.bad_add) def log(self, method, varargs, kwargs, full_kwargs): print "logged %s being called with %s, %s, %s" \ % (method, varargs, kwargs, full_kwargs) def notify(self, method, varargs, kwargs, full_kwargs, rv): print "when %s came back, it gave %s" % (method, rv) def bad_add(self, obj, a, b): if a == b: rv = a+b print "Doubling stuff is easy; %s+%s=%s :)" % (a, b, rv) return self.proceed() rv = a+b+1 print ("I'm not very good at math, because I think %s+%s=%s :(" % (a, b, rv) ) return rv As you can see, each "triggered" method (log, notify) takes parameters that give it the environment which it is triggered in. Current issues that are addressing me would be how to provide support for combining contexts, like AspectJ does, handling something like "when method X is called inside of method Y". Everything I've thought of so far has been without much outside input, so I'd love to discuss ideas, so let me know what you think. -- Frank Tobin http://www.neverending.org/~ftobin/ |