|
|
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
|