By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
443,965 Members | 1,631 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 443,965 IT Pros & Developers. It's quick & easy.

_Re Pre/Postconditions with decorators

P: n/a
# Google-News won't let be post a follow-up right now!
# Google-Beta-News destroys the formatting :-(
# So I'll start a new thread.

Hi Stephen
I have not read anything about the
"framehack lambda replacement" yet,
but I do compile the pre- and
postconditions. Syntax erros e.g.
will be raised if the module
is compiled. Although I must admit
that your code snippets look more like
compiled code ;-)

Hi Robert
thanks for the link to the Ian Bicking blog.

Hi George,
it would be nice to see how you have tackled
the task.
Maybe we will have a checker
module in Python one day... ;-)

Well, I have attached my latest attempt
to model pre/postconditions (without "framehack
lambda replacement") which does wrap the
original function with a class which delegates
attribute access. Now I can split my
"condition" into pre- and postcondition
and the "tracer" prints the original
function name.
I have also fixed a bug
with keyword arguments.
Major difference compared to
other examples is probably
only that I can refer to function
arguments by name:

class Delegate(object):
def __init__(self,function):
self.function=function
def __getattr__(self,key):
return getattr(self.function,key)
def condition(pretext,posttext=""):
precode=compile(pretext or "True","","eval")
postcode=compile(posttext or "True","","eval")

# function -> decorated(function)
def decorate_condition(function):
argcount=function.func_code.co_argcount
var=function.func_code.co_varnames[0:argcount]
class EvalCond(Delegate):
def __call__(self,*args,**kargs):
# FIXME: check if "var" always contains ordered list of arguments
# map arguments and
args_seq=[(argname,args[pos]) for pos,argname in \
enumerate(var) if (argname not in kargs)]
# key-arguments to value
kargs_seq=[(k,v) for k,v in kargs.iteritems()]
environment=args_seq+kargs_seq

# precondition
assert eval(precode,{},dict(environment)),pretext
tmp=function(*args,**kargs)
environment2=environment+[('result',tmp)]

# postcondition
assert eval(postcode,{},dict(environment2)),posttext
return tmp
return EvalCond(function)
return decorate_condition

def trace(function):
class Trace(Delegate):
def __call__(self,*args,**kargs):
print "enter function %s with " % \
self.function.func_name,args,kargs
result=self.function(*args,**kargs)
print "leave function %s with " % \
self.function.func_name,args,kargs
return result
return Trace(function)

def precondition(prgtext):
return condition(prgtext)

def postcondition(prgtext):
return condition("",prgtext)
@precondition("number>0 and number<2")
@postcondition("result>=0")
def sqrt(number):
import math
return math.sqrt(number)

@trace
@precondition("len(seq)>0 is not None and str(more)")
@postcondition("sum(seq)==result")
def my_sum(seq,more):
tmp=0
for element in seq:
tmp+=element
return tmp

print sqrt(1.2)
print my_sum([1,2,3],more="more")
Jul 18 '05 #1
Share this question for a faster answer!
Share on Google+

This discussion thread is closed

Replies have been disabled for this discussion.