I can't solve your problem, but I can at least explain why I think its hard. foo doesn't have any closed over variables. Some of its locals have to live in cells, so that pre and post can see them in their closures.
>>> foo.func_code.co_cellvars ('x', 'y') Now the only way that I know of to get a local variable to be put in a cell, where you can then plug it into a func_closure, it to write a function which a contains a function with a closure. Moreover, this requires that the function signatures really match to work. Consider >>> def test(*arg, **args): ... def inner(): ... print x ... return inner ... >>> f = test(x=5) >>> f() Traceback (most recent call last): File "<interactive input>", line 1, in ? File "<interactive input>", line 3, in inner NameError: global name 'x' is not defined Since x isn't a named argument of test, the compiler just assumes that its a global. This means that your contract function is going to have to build a string and exec to make the newf so its arguments match foo exactly. Of course the compiler is really finicky about exec, when there are free variables around, and I don't claim to understand the rules. alain wrote: > Hi, > > I have a problem with closures. > I am trying to implement yet another design by contract decorator which > would look like the following: > <pre> > def contract(f): > def newf(*args, **kw): > import new > precondition = new.function(f.func_code.co_consts[1], > f.func_globals,'pre', > f.func_defaults, > f.func_closure) > precondition() > result=f(*args, **kw) > postcondition=new.function(f.func_code.co_consts[2],globals()) > postcondition(result) > return result > return newf > @contract > def foo(x,y,g=2,z=1): > def pre(): > assert x>1 and 0<y<100 > def post(result): > assert result >0 > print 'main' > return x+y+z*g > > print foo(2,5,4,69) > <pre> > > The problem is that i get the following error message on line 7: > TypeError: arg 5 (closure) must be tuple > > f.func_closure is indeed empty while > f.func_code.co_consts[1].co_freevars is logically equal to ('x','y'). > > Thanks for responding > > Alain > -- http://mail.python.org/mailman/listinfo/python-list