PEP new assert idiom

Fábio Mendes niels_bohr at uol.com.br
Sun Nov 7 00:44:50 EST 2004


> Some time ago I found myself proposing a new "Validate" statement,
> which would work exactly like "assert", except:
> 
>   1) it would throw a ValidationError instead of AssertionError
>      if the condition failed
> 
>   2) it would NOT be turned into a no-op by the optimizing compiler.
> 
[...]
This sounds great. I like the validate syntax. This also sounds very
useful to me. If it doesn't go mainstream, it should, at least be a
parameter controlled at runtime:

>>> import validate
>>> validate.always_compile_assertions = True # this name sucks! I know!

Ideally, for me, python would support a decent DPC-like semantics: 

>>> class foo_bar:
>>>   contract, 'invariant':
>>>     assert (something always true), 'Errormsg1'
>>>     assert (more imutable truths), 'Errormsg2'
>>>             
>>>   def foo(self, var1, var2):
>>> 	contract, 'pre':
>>>       # var1 and var2 are avaiable in this scope
>>>       assert expr, 'Error string1'
>>>       assert expr1, expr2, 'Error string2'
>>>         
>>>     contract, 'pos':
>>>       # var1, var2, avaiable. 'old' is 'self' before calling foo 
>>>       # foo.return stands for the output of function foo (or None)
>>>       # foo.error is any the exception the function had trown
>>>       assert self.bar > old.bar 
>>>       assert foo == some result, 'Error string'
>>>       if foo.error == some Exception:
>>>         assert (condition to trow that exception), 'Error'
>>> 
>>>	(function implementation)


The (python) implementation of this syntax can be something like this.
If dbc is enable, foo method becames:

>>> def foo(self, var1, var2):
>>>   try:
>>>     contract invariant block
>>>     ...
>>>   except AssertionError, x:
>>>     contractViolations.log('invariant', x)
>>>
>>>   try:
>>>     pre contract block
>>>     ...
>>>   except AssertionError, x:
>>>     contractViolations.log('pre', x)
>>>   try:
>>>     foo.value = __old_foo(var1, var2)
>>>   finally error, error_msg:
>>>     if error: foo.value = None
>>>     foo.error = error
>>>     try:
>>>       post contract block
>>>      except AssertionError, x:
>>>       contractViolations.log('pos', x)
>>>     if error and not contract.fail_silently: 
>>>       raise error, error_msg

The program executes normally, then, if non fatal errors happens,
contracViolations.report() will print a nice formated report of what was
violated, similar to what unittest module does. This is not pure DBC I
guess, but is nice.

Thanks,
Fabio



More information about the Python-list mailing list