473,320 Members | 1,961 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,320 software developers and data experts.

Pre/Postconditions with decorators

My humble attempt to model pre/postconditions with
decorators :-) It's also my first experiment
with decorators.
If you have any ideas or thoughts on how to
improve the code snippet, I'll be happy to
learn more.

Enjoy :-)

def condition(pretext,posttext=""):
precode=compile(pretext or "True","","eval")
postcode=compile(posttext or "True","","eval")

# function -> decorated(function)
def decorate_condition(function):
# FIXME: Does not work with wrapped functions
argcount=function.func_code.co_argcount
var=function.func_code.co_varnames[0:argcount]

# arguments -> closure(assertion)
def evaluate_condition(*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)]
# key-arguments to value
kargs_seq=[(k,v) for k,v in kargs.itervalues()]
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 evaluate_condition

return decorate_condition

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

@condition("list(seq) is not None","sum(seq)==result")
def my_sum(seq):
tmp=0
for element in seq:
tmp+=element
return tmp

print sqrt(1.2)
print my_sum([1,2,3])
Jul 18 '05 #1
7 3296
On 6 Jan 2005 13:33:42 -0800, Rittersporn <ri*********@gmail.com> wrote:
@condition("number>0 and number<2","result>=0")
def sqrt(number):
import math
return math.sqrt(number)

@condition("list(seq) is not None","sum(seq)==result")
def my_sum(seq):
tmp=0
for element in seq:
tmp+=element
return tmp

print sqrt(1.2)
print my_sum([1,2,3])


I think it would be nicer to have the pre and post conditions being compilable.

@condition((list(seq) is not None for seq in args), (sum(seq)==result
for ((seq,), result) in (args, result))

or something silly like that.

Personally, I'd prefer this:
@precondition(list(seq) is not None for seq in args)
@postcondition(sum(seq)==result for ((seq,), result) in (args, result))

(this is, of course, using the framehack lambda replacement presented
in a thread about a week ago).

Stephen.
Stephen.
Jul 18 '05 #2
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 #3
> 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... ;-)


I posted my module on http://rafb.net/paste/results/voZYTG78.html and its unit test on
http://rafb.net/paste/results/MYxMQW95.html. Any feedback will be appreciated.

George
Jul 18 '05 #4
Thank you very much. It is really a very elegant piece of code :-)

Eiffel (language) has both type checking and design by contract.
Python lacks both.
Your module tackles type checking, I
tried to execute arbitrary code before
and after function execution to realize
runtime assertions.

I wonder if this should be separated in a Python
"checker"-module.
Both are part of the interface "contract".

Ciao

Jul 18 '05 #5
Eiffel (language) has both type checking and design by contract.
Python lacks both.


Actually, Python is strongly typed. It's just dynamically instead of
statically typed.

Skip
Jul 18 '05 #6
On Fri, 7 Jan 2005 20:01:50 +0200, George Sakkis <gs*****@rutgers.edu> wrote:
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... ;-)


I posted my module on http://rafb.net/paste/results/voZYTG78.html and its unit test on
http://rafb.net/paste/results/MYxMQW95.html. Any feedback will be appreciated.


Okay, nice.

Unresolved Problems:
1) How do you handle duck types, i.e. a method that accepts StringIO,
cStringIO or any other object that has a .readlines(), .seek() and
..read() method?
2) How do you turn off the type checking for production code?

Otherwise I quite like it. Please publish it somewhere.

Stephen.
Jul 18 '05 #7
Stephen Thorne <st************@gmail.com> writes:
Unresolved Problems:
1) How do you handle duck types, i.e. a method that accepts StringIO,
cStringIO or any other object that has a .readlines(), .seek() and
.read() method?
That should really be done through having those classes inherit a
file-operations mixin, or else through interfaces (which might get
added to Python).
2) How do you turn off the type checking for production code?


It should be left on. Leaving it in for development and turning it
off for production is like wearing a parachute during ground training
and taking it off once you're in the air.
Jul 18 '05 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: Michael Sparks | last post by:
Anyway... At Europython Guido discussed with everyone the outstanding issue with decorators and there was a clear majority in favour of having them, which was good. From where I was sitting it...
17
by: daishi | last post by:
For what it's worth: As far as I know, the proposed @decorator syntax will be the first time that two logical lines of python with the same indentation will not be independent of one another....
8
by: Michele Simionato | last post by:
Decorators can generate endless debate about syntax, but can also be put to better use ;) Actually I was waiting for decorators to play a few tricks that were syntactically too ugly to be even...
4
by: RebelGeekz | last post by:
Just my humble opinion: def bar(low,high): meta: accepts(int,int) returns(float) #more code Use a metadata section, no need to introduce new messy symbols, or mangling our beloved visual...
2
by: Guido van Rossum | last post by:
Robert and Python-dev, I've read the J2 proposal up and down several times, pondered all the issues, and slept on it for a night, and I still don't like it enough to accept it. The only reason...
0
by: Anthony Baxter | last post by:
To go along with the 2.4a3 release, here's an updated version of the decorator PEP. It describes the state of decorators as they are in 2.4a3. PEP: 318 Title: Decorators for Functions and...
0
by: Rittersporn | last post by:
# 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...
11
by: Helmut Jarausch | last post by:
Hi, are decorators more than just syntactic sugar in python 2.x and what about python 3k ? How can I find out the predefined decorators? Many thanks for your help, Helmut Jarausch
2
by: Andrew West | last post by:
Probably a bit of weird question. I realise decorators shouldn't be executed until the function they are defined with are called, but is there anyway for me to find all the decorates declared in a...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
0
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.