473,732 Members | 2,219 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

PEP new assert idiom

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
Jul 18 '05 #1
28 3591
Fábio Mendes <ni********@uol .com.br> wrote:
...
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

Why isn't this equivalent? Apart from the fact that you keep, here and
elsewhere, using 'statement' where you hopefully mean 'expression' --
you cannot assert a statement, you can only assert an expression.
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
Can you give one Python example where the sequence of asserts would
behave differently from what you propose? I cannot see any.
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'

I assume you mean to call foo, because if you don't, it will surely be
true and the assert will just never trigger.

Now, calling expressions expressions, rather than very confusingly
statements, can you explain how the semantics of this, with foo being
called, would differ from those of

assert exp1 and exp2 and exp3 ... and expN, 'errormsg'

???

My proposal is to add the following syntax to the language:
assert (statement 1), (statement 2), ... (statement n), 'Errormsg'

Again: can you explain how the semantics of this, would differ from
those of:

assert exp1 and exp2 and exp3 ... and expN, 'errormsg'

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


There is no such "traditiona l" rule (or rules) in Python. Both a
statement and an expression can perfectly well end in a comma; the comma
does NOT imply any kind of continuation.
Alex
Jul 18 '05 #2
"Fábio Mendes" <ni********@uol .com.br> wrote in message
news:ma******** *************** *************** @python.org...
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:


Do you have a use case? That is, can you give a plausible example that
shows why your proposal would be useful and how it would work?
Jul 18 '05 #3

"Fábio Mendes" <ni********@uol .com.br> wrote in message
news:ma******** *************** *************** @python.org...
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:
[...]
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


I see two difficulties with it.

First, you can do the same thing (I think) with a
try block around a sequence of statements and
an assert in the except block. This means you
will need a fairly strong use case based on
convenience to add the syntax to the language.
You will have to show that it will be used a lot.

Second, the statement form has the potential to
cause side effects. There is a very strong
community of thought that says that asserts
are debugging or validation statements that
should not cause any behavior change by
removing them. This can be dealt with by
making it some form of block that has its
own local variables that are discarded on
exit.

John Roth

Jul 18 '05 #4
> > >>> erromsg = 'Errormsg'
>> assert statement 1, errormsg
>> assert statement 2, 'errormsg
>> (...)
>> assert statement n, errormsg

Why isn't this equivalent? Apart from the fact that you keep, here and
elsewhere, using 'statement' where you hopefully mean 'expression' --
you cannot assert a statement, you can only assert an expression.


There is only the conceptually subtle difference that in the 1st you
asserts the whole block of expressions, the second you assert each
expression. They're likely to be the same, probably they will be
equivalent in all cases but I can't backup the truth or falsity of that
statement. The pythonic counterpart involves too much typing and is more
error prone.
Now, calling expressions expressions, rather than very confusingly
statements, can you explain how the semantics of this, with foo being
called, would differ from those of

assert exp1 and exp2 and exp3 ... and expN, 'errormsg'


This is very similar to what I'm proposing, with the only inconvinience
that is uglier to type:

assert \
exp1 and \
exp2 and \
...
expn,
'ErrorMsg'

Instead of:

assert \
exp1,
exp2,
...
expn,
'Errormsg'

Well, I realize I didn't expressed my thoughts very clearly and that
it's indeed a very minor change in python's syntax. It won't let anyone
does anything new, IFAIK, but it makes a common pattern of code a little
more beautiful, (and why not? more expressive). If one consider the fact
that it won't break old code (only in one very unlikely case) I don't
see it as a completely unreasonable suggestion. Other people may think
differently though.

Thanks,
Fabio
Jul 18 '05 #5
> I see two difficulties with it.

First, you can do the same thing (I think) with a
try block around a sequence of statements and
an assert in the except block. This means you
will need a fairly strong use case based on
convenience to add the syntax to the language.
You will have to show that it will be used a lot.


I meant expression instead of statement, sorry, that's my fault. It's a
minor cosmetic change I should say, only to avoid long grouping of
expressions with an 'and' operator. It's better expressed as: let the
commas take the place of 'and' in assertion verifications.. . Maybe that
could be extended to other parts of the language, but the only place I
think it would be useful is in assertion statements.

Thanks,
Fabio
Jul 18 '05 #6
[Fábio Mendes]
This is very similar to what I'm proposing, with the only inconvinience
that is uglier to type:

assert \
exp1 and \
exp2 and \
...
expn,
'ErrorMsg'

Instead of:

assert \
exp1,
exp2,
...
expn,
'Errormsg'

Well, I realize I didn't expressed my thoughts very clearly and that
it's indeed a very minor change in python's syntax. It won't let anyone
does anything new, IFAIK, but it makes a common pattern of code a little
more beautiful, (and why not? more expressive). If one consider the fact
that it won't break old code (only in one very unlikely case) I don't
see it as a completely unreasonable suggestion. Other people may think
differently though.


The odds of Guido accepting this proposal are about zero. As you say, it
doesn't do anything new, but it does require altering the grammar. Besides,
TOOWTDI.

Also, Guido tends to not be persuaded by arguments about "too much typing".
This is doubly true is you're talking about replacing an "and" with a comma (big
whoop).

Also, one of the existing alternatives is quite readable:

err = 'Errormsg'
assert exp1, err
assert exp2, err
assert exp3, err

The alternative has the advantage that a failure will point to the exact
expression that failed. The disadvantage is the repetition of the error
message; however, I disagree that your use case is common. Instead, it is
likely more advantageous to have different error messages for each expression.
For example, the following comes from the post condition checks in QR matrix
decomposition:

assert Q.tr().mmul(Q)= =eye(min(m,n)), "Q is not orthonormal"
assert isinstance(R,Up perTri), "R is not upper triangular"
assert R.size==(m,n), "R is does not match the original dimensions"
assert Q.mmul(R)==self , "Q*R does not reproduce the original matrix"

One could link all of these by an "and" or the proposed comma, but then you
end-up with a single, less informative error message, "The QR decomposition
bombed, but I won't tell you why ;-) ".
Raymond Hettinger
Jul 18 '05 #7
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.

The purpose is runtime validation of user data, rather than sanity
checking the program logic. Example: I keep finding myself writing
code like:

x = float(raw_input ('Enter a positive number: '))
assert x > 0, 'number wasn't positive'

This is incorrect because the assert statement is not guaranteed to be
executed. I propose to say instead,

validate x > 0, 'number wasn't positive'

which would do the right thing.

This proposal was reasonably well received when I've posted it before,
but I don't remember if there was any conclusion, and there was no
follow-up. Since we're again talking about PEP's regarding the assert
statement, should I try to put one together for this, in my copious
(hah) free time?
Jul 18 '05 #8
> 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_assert ions = 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:
contractViolati ons.log('invari ant', x)

try:
pre contract block
...
except AssertionError, x:
contractViolati ons.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:
contractViolati ons.log('pos', x)
if error and not contract.fail_s ilently:
raise error, error_msg


The program executes normally, then, if non fatal errors happens,
contracViolatio ns.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
Jul 18 '05 #9
> The alternative has the advantage that a failure will point to the exact
expression that failed. The disadvantage is the repetition of the error
message; however, I disagree that your use case is common. Instead, it is
likely more advantageous to have different error messages for each expression.
For example, the following comes from the post condition checks in QR matrix
decomposition:

assert Q.tr().mmul(Q)= =eye(min(m,n)), "Q is not orthonormal"
assert isinstance(R,Up perTri), "R is not upper triangular"
assert R.size==(m,n), "R is does not match the original dimensions"
assert Q.mmul(R)==self , "Q*R does not reproduce the original matrix"

One could link all of these by an "and" or the proposed comma, but then you
end-up with a single, less informative error message, "The QR decomposition
bombed, but I won't tell you why ;-) ".

You have a good point here. Maybe what I proposed is only a distraction.
We don't want a syntax tailored to every sittuation as it will serve
only for showcase selected programs that express the full elegance of
the language, but to the programmer, it gains the burden of memorizing
the 100 and so operators that makes the language very expressive. Of
course each person will develop a personal dialect, which will make his
code very expressive in a specific domain, but he'll talk to
nobodyelse... For that we have perl. So I guess i'm off this thread, but
someone pointed a PEP for a 'validate' statement which still holds. At
least it will help to elucidate the somewhat confusing meaning of the
assert statement. (you shouldn't use it at runtime?? which level of
optimizations disable it?).

Fabio
Jul 18 '05 #10

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

Similar topics

9
2024
by: Dan Perl | last post by:
Is there a mechanism or an idiom for adding code for debugging so that it can easily be removed in the production code? I am thinking of something similar to the C/C++ preprocessor statements with which you can compile an application with the debug code or without it (the default). Dan
12
2822
by: Siemel Naran | last post by:
What is a good idiom for handling a lazy object? I see 2 good possibilities. Any more, any comments? Which way do people here use? (1) class Thing { public: Thing(double x, double y) : x(x), y(y), calculated(false) { } double operator()() const {
0
8774
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9447
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9181
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8186
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6735
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
4550
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4809
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3261
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
2721
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

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.