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") -- http://mail.python.org/mailman/listinfo/python-list