PEP new assert idiom

Fábio Mendes niels_bohr at uol.com.br
Sat Nov 6 16:36:00 EST 2004


I'm sorry if it's an replicate. Either my e-mail program is messing with
things or the python-list sent my msg to /dev/null. I couldn't find
anything related in previous PEP's, so here it goes a very early draft
for a new "assert" syntax:

This was inspired in Ruby's assert syntax. I'm not familiar with Ruby at
all, so the chances are that this piece of code is broken, but I think
the idea is very obvious. In Ruby, assert is simply a method which gets
a block argument:

>>> assert 'Errormsg' {
>>>     statement 1
>>>     statement 2
>>>     (...)
>>>     statement n
>>> }

This elegant syntax is NOT equivalent to python's not so ellegant:

>>> erromsg = 'Errormsg'
>>> assert statement 1, errormsg 
>>> assert statement 2, 'errormsg
>>> (...)
>>> assert statement n, errormsg

In Ruby, the Assertion error is raised if executing statement 1, then 2,
then 3... etc raises an error. This is a subtle thingm the error COULD
NOT be raised if each statement is executed alone, as each statement may
have side effects which make the order of execution relevant. To
suceccefully emulate this behaviour, the python programmer have to
resort to a even more cumbersome solution:

>>> foo = lambda : (statement 1) and (statement 2) ... (statement n)
>>> assert foo, 'Errormsg'

My proposal is to add the following syntax to the language:

>>> assert (statement 1), (statement 2), ... (statement n), 'Errormsg'

Or, if the user prefers, the traditional comma rules also applies:

>>> assert \
>>>     statement1,
>>>     statement2,
>>>     (...) 
>>>     statement n,
>>>     'Errormsg'

This simple syntax change introduces a very useful idiom for unittesting
and may equally be useful in other kinds of code. The most problematic
issue, I see, is the potential ambiguity a assert usage:

>>> assert statement 1, ..., statement n, string

As the 'Errormsg' argument is optional, it could be interpreted either
as being the statement (n + 1) or as the errormsg. This is not a
non-issue as the following syntax is valid in the current implementation
and is very useful:

>>> st = ''
>>> assert st
Traceback 
   ....
AssertionError

This is useful to assert that a string is not empty. My proposal is that
assert will always check all statements, (including the eventual error
message) and issue AssertError exceptions if find any problem. This will
catch only empty strings. If the last argument is a string, and an a
False statement was found, it will print the last argument in the shell.

The only piece of code I see would be broken in the new implementation
is:

>>> assert statement, ''

This will always raise an exception in the new implementation on the
opposition to the current behaviour in which the exception is raised
only if 'statement' is false, returning an empty error message. I don't
see any use for this pattern of code and is very unlikelly anyone has
ever implemented it, so I guess nobody would mind breaking this.

I'm interested to write a formal PEP if I receive good feedback from the
community, but I never wrote a PEP before, and (the worst problem) my
english is not so good. Anyone helps?

Thanks,
Fabio



More information about the Python-list mailing list