How can I make my assertions smarter?
Michael Hudson
mwh21 at cam.ac.uk
Mon Nov 1 08:35:53 EST 1999
Stuart Hungerford <stuart.hungerford at webone.com.au> writes:
> Hi all,
>
> I'm using some simple functions to implement crude precondition,
> postcondition and invariant checking in Python classes.
>
> (Tim: please be gentle ;-)
>
> Is there some neat way to wrap these tests up so I can print any
> code expression that fails, e.g:
>
> Precondition failed foo.py line 42: spoon.shape == 'bent'
>
> which would appear at line 42 of foo.py as
>
> pre(spoon.shape == 'bent')
Hmm... tricky.
Something like this might work (tho' not with python -O, not that that
should be a problem).
chuck it in a file called "pre.py". It will have problems with line
continutations & stuff, but I did just make it up on the spot (well,
about half an hour of spot; must now do something of some use).
class PreconditionViolation(AssertionError):
def __init__(self,why):
AssertionError.__init__(self,why)
def pre(cond):
if cond:
return
try:
raise ""
except:
import sys
frame = sys.exc_traceback.tb_frame.f_back
lineno = frame.f_lineno
filename = frame.f_code.co_filename
try:
import re
file = open(filename)
for i in range(lineno):
line = file.readline()
match = re.match("\W*(pre\.)?pre\((.*)\);?\W*$",line)
if match is not None:
line = match.group(2)
else:
import string
line = string.strip(line)
except:
line = "<not found>"
line = "line %d of %s: %s"%(lineno,filename,line)
raise PreconditionViolation, line
def checked_sqrt(x):
from math import sqrt
pre(x>=0)
return sqrt(x)
if __name__=='__main__':
print checked_sqrt(2)
print checked_sqrt(-1)
then `python pre.py' gives:
1.41421356237
Traceback (innermost last):
File "pre.py", line 39, in ?
print checked_sqrt(-1)
File "pre.py", line 34, in checked_sqrt
pre(x>=0)
File "pre.py", line 30, in pre
raise PreconditionViolation, line
__main__.PreconditionViolation: line 34 of pre.py: x>=0
but, really, what's wrong with asserts?
Another approach would be to poke around with frame.f_lasti and
decompile the bytecode (!).
> I can see how to use environment variables or global variables to
> selectively enable precondtions etc, although any hints for doing that
> would be appreciated too.
That should be pretty straightforward.
> Thanks in advance,
>
> Stu
HTH,
Michael
More information about the Python-list
mailing list