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

Reply via email to