[pypy-svn] r40766 - in pypy/dist/pypy/lib: . app_test
afayolle at codespeak.net
afayolle at codespeak.net
Mon Mar 19 13:37:34 CET 2007
Author: afayolle
Date: Mon Mar 19 13:37:24 2007
New Revision: 40766
Modified:
pypy/dist/pypy/lib/aop.py
pypy/dist/pypy/lib/app_test/test_aop.py
Log:
implementation of around call advice
Modified: pypy/dist/pypy/lib/aop.py
==============================================================================
--- pypy/dist/pypy/lib/aop.py (original)
+++ pypy/dist/pypy/lib/aop.py Mon Mar 19 13:37:24 2007
@@ -97,14 +97,14 @@
def weave_at_execution(self, node, tjp):
"""weaving around a function execution moves the body of the
function to an inner function called
- __aoptarget_<funcname>_<id>, and generate the following code:
- return __aop__(id, __aoptarget_<funcname>_<id>)
+ __aoptarget_<id>__, and generate the following code:
+ return __aop__(id, __aoptarget_<id>__)
"""
debug("WEAVE around execution")
p = parser
id = __aop__.register_joinpoint(self.woven_code, tjp)
statement = node.code
- newname = '__aoptarget_%s_%s__' % (node.name, id)
+ newname = '__aoptarget_%s__' % (id)
newcode = p.ASTStmt([p.ASTFunction(node.decorators,
newname,
node.argnames,
@@ -119,11 +119,21 @@
node.decorators = None
node.code = newcode
+ debug('newnode: %s', node)
return node
def weave_at_call(self, node, tjp):
- debug("WEAVE around execution")
- raise NotImplementedError("abstract method")
+ debug("WEAVE around call")
+ p = parser
+ id = __aop__.register_joinpoint(self.woven_code, tjp)
+ newnode = make_aop_call_for_around_call(id,
+ node.node.varname,
+ node.args,
+ node.star_args,
+ node.dstar_args
+ )
+ debug('newnode: %s', newnode)
+ return newnode
def weave_at_initialization(self, node, tjp):
raise NotImplementedError("abstract method")
@@ -142,6 +152,7 @@
statement_list = node.code.nodes
statement_list.insert(0, make_aop_call(id))
node.code.nodes = statement_list
+ debug('newnode: %s', node)
return node
@log_exc
@@ -171,7 +182,7 @@
newnode = p.ASTSubscript(call,
p.OP_APPLY,
p.ASTConst(1))
- debug('%r', newnode)
+ debug('newnode: %s', newnode)
return newnode
def weave_at_initialization(self, node, tjp):
@@ -192,6 +203,7 @@
statement = node.code
tryfinally = parser.ASTTryFinally(statement, make_aop_call(id))
node.code = tryfinally
+ debug('newnode: %s', node)
return node
@log_exc
@@ -222,6 +234,7 @@
def weave_at_static(self, node, tjp):
debug("WEAVE introduce!!!")
pass # XXX WRITEME
+ debug('newnode: %s', node)
return node
@@ -516,8 +529,10 @@
woven_code, (aspect, joinpoint, arguments) = self.joinpoints[id]
joinpoint.func = target
debug('target_locals = %s', target_locals)
- if target_locals is not None:
+ if type(target_locals) is dict:
joinpoint._arguments = (), dict([(n, target_locals[n]) for n in joinpoint._argnames or ()])
+ elif type(target_locals) is tuple:
+ joinpoint._arguments = target_locals, {}
if result is not _UndefinedResult:
joinpoint._result = result
args = (aspect, joinpoint,) + arguments
@@ -548,7 +563,21 @@
# helper functions
def make_aop_call(id, targetname=None, discard=True, resultcallfuncnode=None):
"""return an AST for a call to a woven function
- id is the integer returned when the advice was stored in the registry"""
+
+ id is the integer returned when the advice was stored in the
+ registry
+
+ targetname is the name of the function that will be run when
+ jointpoint.proceed() is called by the advice
+
+ if discard is True, the call is wrapped in an ASTDiscard node,
+ otherwise an ASTReturn node is used
+
+ If resultcallfuncnode is not None, it is expected to be an
+ ASTCallFunc node which will be inserted as an argument in the aop
+ call, so that the function is called and its return value is
+ passed to the __aop__ instance.
+ """
p = parser
arguments = [p.ASTConst(id),]
if targetname is not None:
@@ -573,6 +602,38 @@
None # *kwargs
)
)
+def make_aop_call_for_around_call(id, targetname, target_args, target_starargs, target_dstar_args):
+ """return an AST for a call to a woven function
+
+ id is the integer returned when the advice was stored in the
+ registry
+
+ targetname is the name of the function that will be run when
+ jointpoint.proceed() is called by the advice
+
+ target_args, target_starargs, target_dstar_args are the values of the original ASTCallFunc
+ """
+ debug('make... %s %s %s %s %s', id, targetname, target_args, target_starargs, target_dstar_args)
+ p = parser
+ arguments = [p.ASTConst(id),]
+ if targetname is not None:
+ arguments.append(p.ASTName(targetname))
+ else:
+ arguments.append(p.ASTName('None'))
+
+ callargs = [p.ASTList(target_args)]
+
+
+ arguments.append(p.ASTTuple(callargs))
+
+
+ debug('arguments: %s', arguments)
+ return p.ASTCallFunc(p.ASTName('__aop__'),
+ arguments,
+ None, # *args
+ None # *kwargs
+ )
+
# debugging visitor
class Debug(parser.ASTVisitor):
Modified: pypy/dist/pypy/lib/app_test/test_aop.py
==============================================================================
--- pypy/dist/pypy/lib/app_test/test_aop.py (original)
+++ pypy/dist/pypy/lib/app_test/test_aop.py Mon Mar 19 13:37:24 2007
@@ -220,3 +220,34 @@
sample_aop_code.clean_module('aop_after_call')
+ def test_simple_aspect_around_call(self):
+ from aop import PointCut, Aspect, around
+ from app_test import sample_aop_code
+ __aop__._clear_all()
+ sample_aop_code.write_module('aop_around_call')
+ class AspectTest:
+ __metaclass__ = Aspect
+ def __init__(self):
+ self.executed_before = 0
+ self.executed_after = 0
+ @around(PointCut(func='bar').call())
+ def advice_around_call(self, tjp):
+ print '>>>in', tjp.arguments()
+ self.executed_before += 1
+ args, kwargs = tjp.arguments()
+ tjp.proceed(*args, **kwargs)
+ self.executed_after += 1
+ self.result = tjp.result()
+ print '<<<out'
+ return tjp.result()
+
+ aspect = AspectTest()
+ from app_test import aop_around_call
+ assert aspect.executed_before == 0
+ assert aspect.executed_after == 0
+ answ = aop_around_call.foo(1,2)
+ assert aspect.executed_before == 1
+ assert aspect.executed_after == 1
+ assert aspect.result == 42
+ assert answ == 47
+ sample_aop_code.clean_module('aop_around_call')
More information about the Pypy-commit
mailing list