a lightweight object

A Lightweight Approach to Aspect-Oriented Programming in Python

Introduction
Features
Examples
Documentation
Download
(Old pages)

Examples

with_wrap and without_wrap in Python 2.5+

Wrapping methods and functions

aspects.with_wrap(wrap, func[, func]...[, instances]). In Python 2.5 and later you can wrap methods and functions with with_wrap. If you want to execute the wrap when the wrapped method is called through certain instances only, give the list of the instances with "instances" keyword argument.

>>> import aspects
>>> def mywrap(*args, **kwargs):
...     print "mywrap called with args",args
...     retval = yield aspects.proceed(*args, **kwargs)
...     print "mywrap catched return value:", retval
...     yield aspects.return_stop(retval)
... 
>>> def increase(x):
...     return x+1
... 
>>> class c(object):                  
...     def decrease(self, x):
...         return x-1
... 
>>> aspects.with_wrap(mywrap, increase, c.decrease)
[0, 1]
>>> increase(9)
mywrap called with args (9,)
mywrap catched return value: 10
10
>>> c().decrease(43)
mywrap called with args (<__main__.c object at 0xb7de044c>, 43)
mywrap catched return value: 42
42
>>> aspects.without_wrap(mywrap, increase)
<function mywrap at 0xb7a586bc>
>>> increase(9)
10
>>> c().decrease(43)
mywrap called with args (<__main__.c object at 0xb7a61dcc>, 43)
mywrap catched return value: 42
42

Catching exceptions from wrapped functions

>>> import aspects
>>> 
>>> def divide(x,y):
...     return x/y
... 
>>> def suppress_errors(*a, **kw):
...     try:
...         yield aspects.proceed
...     except Exception, e:
...         print "sshh!", e
...         yield aspects.return_stop(None)
... 
>>> aspects.with_wrap(suppress_errors, divide)
0
>>> divide(42, 2)
21
>>> divide(1, 0)
sshh! integer division or modulo by zero
>>> 

Wrapping built-in functions

Built-in functions can be wrapped as well. If a return value is not explicitely given in the wrap, the return value of the wrapped method or function is returned.

>>> import aspects
>>> def mywrap(*a, **kw):
...     print "args:", a, kw
...     rv = yield aspects.proceed(*a, **kw)
...     print "retval:", rv
... 
>>> import os
>>> import sys
>>> aspects.with_wrap(mywrap, os.open, os.close, sys.exit)
[0, 0, 0]
>>> fd=os.open("aspects.py", os.O_RDONLY)
args: ('aspects.py', 0) {}
retval: 3
>>> os.close(fd)
args: (3,) {}
retval: None
>>> sys.exit()
args: () {}

Wrap's execution can be continued

Yielding return_cont runs the wrapped function and returns the arguments and keyword arguments of the next function call. Note that when yielded proceed and return_(cont|stop) are not given parameters, the call arguments and the return value of the wrapped function call are used automatically.

>>> import aspects
>>> def foo(x):
...     print "foo(%s) = %s" % (x, x+42)
...     return x+42
... 
>>> def wrap(*a, **kw):
...     i=0
...     while len(a)>0 and a[0]>0:
...         i+=1
...         print "called",i,"times with arg[0] > 0"
...         yield aspects.proceed
...         a, kw = yield aspects.return_cont
...     yield aspects.proceed
... 
>>> aspects.with_wrap(wrap, foo)
0
>>> foo(1)
called 1 times with arg[0] > 0
foo(1) = 43
43
>>> foo(2)
called 2 times with arg[0] > 0
foo(2) = 44
44
>>> foo(3)
called 3 times with arg[0] > 0
foo(3) = 45
45
>>> foo(-1)
foo(-1) = 41
41
>>> foo(4)
called 1 times with arg[0] > 0
foo(4) = 46
46

wrap_around in Python 2.1+

aspects.wrap_around(method, wrap[, instances]). (This will be deprecated.) In Python 2.1 and later you can wrap methods inside your code. However, functions at module level cannot be wrapped.

>>> import aspects
>>> 
>>> def mywrap(self, *args, **kwargs):
...     print "mywrap called with args",args
...     retval = self.__proceed(*args, **kwargs)
...     print "mywrap catched return value:", retval
...     return retval
... 
>>> class c:
...     def decrease(self, x):
...         return x-1
... 
>>> aspects.wrap_around(c.decrease, mywrap)
0
>>> 
>>> c().decrease(43)
mywrap called with args (43,)
mywrap catched return value: 42
42

Python logo CC-GNU LGPL Valid HTML 4.01 Transitional
Hosted by Tampere University of Technology / Department of Software Systems. Thank you!
Updated 2009-08-01 15:03, Antti Kervinen, ask@cs.tut.fi