Re: When to use assert

2014-10-26 Thread Steven D'Aprano
Chris Angelico wrote:

 On Fri, Oct 24, 2014 at 6:49 PM, Steven D'Aprano
 steve+comp.lang.pyt...@pearwood.info wrote:
 addresses = [get_address(name) for name in database]
 assert all(address for address in addresses)
 # ... much later on ...
 for i, address in enumerate(addresses):
 if some_condition():
 addresses[i] = modify(address)
 assert addresses[i]


 will either identify the culprit, or at least prove that neither
 get_address() nor modify() are to blame. Because you're using an
 assertion, it's easy to leave the asserts in place forever, and disable
 them by passing -O to the Python interpreter in production.
 
 The first assertion is fine, assuming that the emptiness of your
 address corresponds to falsiness as defined in Python. (This could be
 safe to assume, if the address is an object that knows how to boolify
 itself.) The second assertion then proves that modify() isn't
 returning nothing, but that might be better done by sticking the
 assertion into modify itself.

Sure. If you can modify the function, getting it to check it's own
post-condition is a good strategy. But you might not be able to do that.
Perhaps you don't have the source code, or its from a third-party library
and you don't want to have to keep hacking your copy every time it's
updated, or you're calling an external library written in Java.

(And yes, there are work-arounds for those scenarios too. Aren't choices
wonderful?)


 And that's what I'm talking about: checking a function's postcondition
 with an assert implies putting that assertion after every call, 

There's no rule that you have to use an assertion after *every* call to a
function. If you can check the post-condition inside the function, that's
great. If you can't, then use your judgement. More asserts are not
necessarily better, just as more unit tests are not necessarily better.

You have to make a value judgement based on how much you trust the code,
trust your own skills, trust your colleagues who will be maintaining the
code in your absence, versus the maximum density of asserts per line of
other code.


 and 
 anything that you have to do every time you call a function belongs
 inside that function. Imagine writing this kind of defensive code, and
 then having lots of places that call modify()... and missing the
 assert in some of them. Can you trust what you're getting back?

Well, if the function is perfect, then adding more assertions won't uncover
bugs that aren't there. And if the function is buggy, then adding more
assertions will increase the likelihood that you'll discover those bugs
earlier rather than later. How much do you trust the function?

One test is better than no tests at all, but a thousand tests is not
necessarily better than ten. The same applies to assertions. One might say
that assertions can be considered tests that automatically run every time
you run your code (in debugging mode), rather than needing to remember to
run a special test program.

In the absence of correctness proofs for your code, anything you do (unit
tests, assertions, regression tests, etc.) is just a statistically sampling
of all the potential paths your code might take, hoping to capture bugs. As
any statistician will tell you, eventually you will reach the point of
diminishing returns, where adding more samples isn't worth the cost. That
point will depend on the cost in programmer effort, the performance
implications, and your confidence in the code.

 
 [Aside: it would be nice if Python did it the other way around, and
 [require
 a --debugging switch to turn assertions on. Oh well.]
 
 Maybe. But unless someone actually tests that their assertions are
 being run, there's the risk that they're flying blind and assuming
 that it's all happening. There'll be all these lovely checked
 comments... or so people think. Nobody ever runs the app with
 --debugging, so nobody ever sees anything.

Absolutely. And if you write unit tests but never actually run them, the
same thing applies. You need a process that actually runs the code in
debugging mode, and/or runs the tests.

Or if the unit tests all pass but don't actually do anything useful?

def test_critical_code_path(self):
# Make sure application works correctly.
self.assertTrue(True)

Do I have to link to the DailyWTF showing that some people actually do write
tests like this? Sure, why not :-) 

http://thedailywtf.com/articles/Productive-Testing

Bad programmers can screw up anything.


 Assertions and test suites are complementary, not in opposition, like
 belt and braces. Assertions insure that the code branch will be tested if
 it is ever exercised, something test suites can't in general promise.
 Here's a toy example:

 def some_function(value):
 import random
 random.seed(value)
 if random.random() == 0.25000375:
 assert some_condition
 else:
 pass


 Try writing a unit test that guarantees to test the some_condition
 branch :-)

 

Re: When to use assert

2014-10-26 Thread Chris Angelico
On Sun, Oct 26, 2014 at 8:39 PM, Steven D'Aprano
steve+comp.lang.pyt...@pearwood.info wrote:
 In the absence of correctness proofs for your code, anything you do (unit
 tests, assertions, regression tests, etc.) is just a statistically sampling
 of all the potential paths your code might take, hoping to capture bugs. As
 any statistician will tell you, eventually you will reach the point of
 diminishing returns, where adding more samples isn't worth the cost. That
 point will depend on the cost in programmer effort, the performance
 implications, and your confidence in the code.

That's about the size of it, I guess. How much testing versus how much
time actually spent coding?

I'm pretty sure a lot of my code has the wrong ratio... I'm just not
sure, for a lot of the code, which direction it's wrong :)

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: When to use assert

2014-10-24 Thread Steven D'Aprano
Dan Stromberg wrote:

 I like to use assertions and if cond: raise ValueError('foo') a lot.
 
 I think Eiffel may be the poster-child for a language with
 pre-conditions, post-conditions and assertions.

Yes. I don't think Eiffel is the only language with explicit support for
testing invariants, but it's probably the best known one.

https://archive.eiffel.com/doc/online/eiffel50/intro/language/invitation-07.html

Others include Ada2012, Mercury, D, Perl6, Cobra, Clojure, and others. Cobra
is especially interesting as the syntax is heavily influenced by Python's.

http://cobra-language.com/trac/cobra/wiki/Contracts


 I think you're in good company - a lot of developers don't use assertions
 much.

You in this context is Chris Angelico.


 I like assertions, because they tend to stop bugs pretty quickly.  If
 you have 3 functions, one calling another calling another, assertions
 in each can keep you from having to backtrack among them when
 debugging, instead going directly to the problem's source.

Yes, the purpose of assertions is to help errors be discovered as close to
the cause as possible, rather than somewhere much later on. Consider:

addresses = [get_address(name) for name in database]
# ... much later on ...
for i, address in enumerate(addresses):
if some_condition():
addresses[i] = modify(address)
# ... much later on ...
for address in list_of_addresses:
process_non_empty_address(address)

where you can't easily modify or check the get_address() and modify()
functions. If you have a failure in process_non_empty_address, due to a
violation of the address must not be empty invariant, which function is
to blame?

You could wrap them and find out that way:

from somewhere import get_address as _get_addr

def get_address(*args, **kwargs):
result = _get_addr(*args, **kwargs)
if not result:
raise RuntimeError(bug in get_address)
return result


and under some circumstances that's a good strategy, but often you just want
to determine which function is violating the constraint, fix that one, and
leave the other unmodified.

addresses = [get_address(name) for name in database]
assert all(address for address in addresses)
# ... much later on ...
for i, address in enumerate(addresses):
if some_condition():
addresses[i] = modify(address)
assert addresses[i]


will either identify the culprit, or at least prove that neither
get_address() nor modify() are to blame. Because you're using an assertion,
it's easy to leave the asserts in place forever, and disable them by
passing -O to the Python interpreter in production.

[Aside: it would be nice if Python did it the other way around, and require
a --debugging switch to turn assertions on. Oh well.]


 This is the job of a test suite.
 
 Test suites are great, and I can't really question your reliance on
 them.  I love having lots of automated tests.  But for the reason I
 described above, I still like having lots of assertions.

Assertions and test suites are complementary, not in opposition, like belt
and braces. Assertions insure that the code branch will be tested if it is
ever exercised, something test suites can't in general promise. Here's a
toy example:

def some_function(value):
import random
random.seed(value)
if random.random() == 0.25000375:
assert some_condition
else:
pass


Try writing a unit test that guarantees to test the some_condition
branch :-)

[Actually, it's not that hard, if you're willing to monkey-patch the random
module. But you may have reasons for wanting to avoid such drastic
measures.]

I don't know what value will cause some_function() to take the
some_condition branch, but I know that if it ever takes that branch, the
assert will guard it, regardless of whether or not I've written a unit test
to cover that situation.


 You don't pepper your code with
 assertions to the effect that I just pushed something onto my queue,
 it should now have this item in it; you create a test case for it,
 and verify your function there. In the rest of the code, you trust
 that your test suite passes, and don't waste time with assertions.
 
 I wouldn't test that a value was added to a queue immediately after
 adding it.  That's excessive, and may even require an abstraction
 violation.
 
 But if, for example, I have a string with 3 known-good values, I'll
 if/elif/elif/else, and make the else raise an AssertionError.  The
 assertion should never fire, but if the code changes, it could, and if
 there's a typo somewhere, it could then too.

I like this style:

assert x in (a, b, c)
if x == a:
do_this()
elif x == b:
do_that()
else:
assert x == c
do_something_else()


Why do I prefer that? To defend against future code changes. Defensive
programming can defend not only against bugs in the current code, but also
bugs in *future* code. Consider this common case:

# x is either a or b.
if x == a:
do_this()
elif x == b:
do_that()
else:  # x must 

Re: When to use assert

2014-10-24 Thread Chris Angelico
On Fri, Oct 24, 2014 at 6:49 PM, Steven D'Aprano
steve+comp.lang.pyt...@pearwood.info wrote:
 addresses = [get_address(name) for name in database]
 assert all(address for address in addresses)
 # ... much later on ...
 for i, address in enumerate(addresses):
 if some_condition():
 addresses[i] = modify(address)
 assert addresses[i]


 will either identify the culprit, or at least prove that neither
 get_address() nor modify() are to blame. Because you're using an assertion,
 it's easy to leave the asserts in place forever, and disable them by
 passing -O to the Python interpreter in production.

The first assertion is fine, assuming that the emptiness of your
address corresponds to falsiness as defined in Python. (This could be
safe to assume, if the address is an object that knows how to boolify
itself.) The second assertion then proves that modify() isn't
returning nothing, but that might be better done by sticking the
assertion into modify itself.

And that's what I'm talking about: checking a function's postcondition
with an assert implies putting that assertion after every call, and
anything that you have to do every time you call a function belongs
inside that function. Imagine writing this kind of defensive code, and
then having lots of places that call modify()... and missing the
assert in some of them. Can you trust what you're getting back?

 [Aside: it would be nice if Python did it the other way around, and require
 a --debugging switch to turn assertions on. Oh well.]

Maybe. But unless someone actually tests that their assertions are
being run, there's the risk that they're flying blind and assuming
that it's all happening. There'll be all these lovely checked
comments... or so people think. Nobody ever runs the app with
--debugging, so nobody ever sees anything.

 Assertions and test suites are complementary, not in opposition, like belt
 and braces. Assertions insure that the code branch will be tested if it is
 ever exercised, something test suites can't in general promise. Here's a
 toy example:

 def some_function(value):
 import random
 random.seed(value)
 if random.random() == 0.25000375:
 assert some_condition
 else:
 pass


 Try writing a unit test that guarantees to test the some_condition
 branch :-)

 [Actually, it's not that hard, if you're willing to monkey-patch the random
 module. But you may have reasons for wanting to avoid such drastic
 measures.]

Easy. You craft a test case that passes the right argument, and then
have the test case test itself. You will want to have a script that
figures out what seed value to use:

def find_seed(value):
import random
for seed in range(100): # Restrict to not-too-many tries
random.seed(seed)
if random.random() == value: return seed

I didn't say it'd be efficient to run, but hey, it's easy. I've no
idea how many bits of internal state the default Python RNGs use, but
testing a million seeds took a notable amount of time, so I told it to
fail after that many. (And I didn't find one that gave that result.)

But actually, it would be really simple to monkey-patch. And in any
non-toy situation, there's probably something more significant being
tested here... unless you really are probing a random number generator
or something, in which case you probably know more about its
internals.

 I like this style:

 assert x in (a, b, c)
 if x == a:
 do_this()
 elif x == b:
 do_that()
 else:
 assert x == c
 do_something_else()

If all your branches are simple function calls, I'd be happy with a
KeyError instead of an AssertionError or RuntimeError.

{a:do_this, b:do_that, c:do_something_else}[x]()

I was talking to a student this week who had a long if/elif chain that
translated keywords into values, something like this:

def get_whatever_value(kwd):
if kwd == 'value_should_be_50':
return 50
elif kwd == 'value_wants_to_be_75':
return 75
elif kwd == 'one_hundred':
return 100

There was no 'else' clause, so in the event of an incorrect keyword,
it would return None. Now, I could have advised adding an else
ValueError or an assertion, but my preferred technique here is a
simple dict lookup. Simpler AND guarantees that all inputs are
checked.

 Or is that insufficiently paranoid?

 With good tests, you're probably fine.

 Is it possible to be too paranoid when it comes to tests?

Yeah, it is. I said earlier about checking that len() returns an
integer. The only way[1] for len(some_object) to return a non-integer
is for someone to have shadowed len, and if you're asserting to see if
someone's maliciously shadowing builtins, you *really* need a hobby.
But hey. Maybe asserting *is* your hobby!

ChrisA

[1] Cue the response pointing out some way that it'll return something
else. I wasn't able to break it, though.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: When to use assert

2014-10-22 Thread Steven D'Aprano
Chris Angelico wrote:

 On Wed, Oct 22, 2014 at 12:44 PM, Steven D'Aprano
 steve+comp.lang.pyt...@pearwood.info wrote:
 def do_something(instance_or_id):
 instance = Model.get(instance_or_id)
 assert isinstance(instance, Model)
 # Code that assumes that instance is an object of type Model


 That means that the logic for what is acceptable as a Model is all in one
 place, namely the Model.get method, and callers don't need to care about
 the pre-condition argument is a Model or an integer ID, they only need
 to care about the post-condition result of get() is a Model.
 
 And at that point, the assertion is redundant, on par with:
 
 a = len(seq)
 assert isinstance(a, int)
 
 because you shouldn't have to assert what's part of a function's
 guarantee.

That depends on how well you trust the function, how paranoid you are, and
whether you wish to include a checked comment, among other considerations.
I'd prefer to write the above than:

a = len(seq)
# At this point, a is an int.

because comments inside code that aren't checked are technically known
as lies http://import-that.dreamwidth.org/956.html. Ha ha only serious.

I wouldn't write such a comment for len() since I would expect anyone
reading the code to know what len() does, but the same doesn't necessarily
apply for every function call I make.

Checking the post-condition of a built-in like len() is too paranoid for my
tastes, as len() enforces the rule that __len__() methods return a
non-negative integer, and there are millions of lines of Python code around
the world calling len(). Somebody surely have noticed by now if len()
violated that post-condition. But for a function from my own code base,
where I might only have dozens of users (oh to have that many!) and fewer
unit tests than perhaps I ought to, I might not be quite so confident that
the assertion was redundant. To err is human, and so there are occasions
when it is appropriate to trust but verify.

As I wrote:

This is why assert can be divisive. Since we can vary in our 
confidence about the correctness of code, one person's useful 
assertion may be another person's useless runtime test.

http://import-that.dreamwidth.org/676.html


-- 
Steven

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: When to use assert

2014-10-22 Thread Chris Angelico
On Thu, Oct 23, 2014 at 2:49 AM, Steven D'Aprano
steve+comp.lang.pyt...@pearwood.info wrote:
 Chris Angelico wrote:

 And at that point, the assertion is redundant, on par with:

 a = len(seq)
 assert isinstance(a, int)

 because you shouldn't have to assert what's part of a function's
 guarantee.

 That depends on how well you trust the function, how paranoid you are, and
 whether you wish to include a checked comment, among other considerations.
 I'd prefer to write the above than:

 a = len(seq)
 # At this point, a is an int.

 because comments inside code that aren't checked are technically known
 as lies http://import-that.dreamwidth.org/956.html. Ha ha only serious.
 ...
 Checking the post-condition of a built-in like len() is too paranoid for my
 tastes...

 As I wrote:

 This is why assert can be divisive. Since we can vary in our
 confidence about the correctness of code, one person's useful
 assertion may be another person's useless runtime test.

I agree that the assert is preferable to the comment. But maybe my
level of paranoia is just lower than most people's, as I wouldn't
bother checking the post-conditions of pretty much anything. Do you
put these assertions every time you call the function? Every time
you're depending on its return value? At what point should you stop
writing Python code and start using a language with a lot more
boilerplate and checking (I believe Haskell fits that, though I'm not
overly familiar with the language)?

This is the job of a test suite. You don't pepper your code with
assertions to the effect that I just pushed something onto my queue,
it should now have this item in it; you create a test case for it,
and verify your function there. In the rest of the code, you trust
that your test suite passes, and don't waste time with assertions.

Or is that insufficiently paranoid?

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: When to use assert

2014-10-22 Thread Dan Stromberg
On Wed, Oct 22, 2014 at 9:01 AM, Chris Angelico ros...@gmail.com wrote:
 On Thu, Oct 23, 2014 at 2:49 AM, Steven D'Aprano
 steve+comp.lang.pyt...@pearwood.info wrote:
 Chris Angelico wrote:
 I agree that the assert is preferable to the comment. But maybe my
 level of paranoia is just lower than most people's, as I wouldn't
 bother checking the post-conditions of pretty much anything. Do you
 put these assertions every time you call the function? Every time
 you're depending on its return value? At what point should you stop
 writing Python code and start using a language with a lot more
 boilerplate and checking (I believe Haskell fits that, though I'm not
 overly familiar with the language)?

I like to use assertions and if cond: raise ValueError('foo') a lot.

I think Eiffel may be the poster-child for a language with
pre-conditions, post-conditions and assertions.

I think you're in good company - a lot of developers don't use assertions much.

I like assertions, because they tend to stop bugs pretty quickly.  If
you have 3 functions, one calling another calling another, assertions
in each can keep you from having to backtrack among them when
debugging, instead going directly to the problem's source.

 This is the job of a test suite.

Test suites are great, and I can't really question your reliance on
them.  I love having lots of automated tests.  But for the reason I
described above, I still like having lots of assertions.

 You don't pepper your code with
 assertions to the effect that I just pushed something onto my queue,
 it should now have this item in it; you create a test case for it,
 and verify your function there. In the rest of the code, you trust
 that your test suite passes, and don't waste time with assertions.

I wouldn't test that a value was added to a queue immediately after
adding it.  That's excessive, and may even require an abstraction
violation.

But if, for example, I have a string with 3 known-good values, I'll
if/elif/elif/else, and make the else raise an AssertionError.  The
assertion should never fire, but if the code changes, it could, and if
there's a typo somewhere, it could then too.

 Or is that insufficiently paranoid?

With good tests, you're probably fine.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: When to use assert

2014-10-21 Thread Anton
On Saturday, November 16, 2013 11:35:50 PM UTC-8, Steven D'Aprano wrote:
 The question of when to use the assert statement comes up occasionally, 
 
 usually in response to somebody misusing it, so I thought I'd write a 
 
 post describing when and why to use assertions, and when not to.
 
 
 
 For those who aren't aware of it, Python's assert checks a condition, 
 
 if it is true it does nothing, and if it is false it raises an 
 
 AssertionError with an optional error message. For example:
 
 
 
 py x = 23
 
 py assert x  0, x is not zero or negative
 
 py assert x%2 == 0, x is not an even number
 
 Traceback (most recent call last):
 
   File stdin, line 1, in module
 
 AssertionError: x is not an even number
 
 
 
 
 
 Many people use asserts as a quick and easy way to raise an exception if 
 
 an argument is given the wrong value. But this is wrong, dangerously 
 
 wrong, for two reasons. The first is that AssertionError is usually the 
 
 wrong error to give when testing function arguments. You wouldn't write 
 
 code like this:
 
 
 
 if not isinstance(x, int):
 
 raise AssertionError(not an int)
 
 
 
 you'd raise TypeError instead. assert raises the wrong sort of 
 
 exception.
 
 
 
 But, and more dangerously, there's a twist with assert: it can be 
 
 compiled away and never executed, if you run Python with the -O or -OO 
 
 optimization flags, and consequently there is no guarantee that assert 
 
 statements will actually be run. When using assert properly, this is a 
 
 feature, but when assert is used inappropriately, it leads to code that 
 
 is completely broken when running with the -O flag.
 
 
 
 When should use assert? In no particular order, assertions should be used 
 
 for:
 
 
 
 * defensive programming;
 
 * runtime checks on program logic;
 
 * checking contracts (e.g. pre-conditions and post-conditions);
 
 * program invariants; and 
 
 * checked documentation.
 
 
 
 (It's also acceptable to use assert when testing code, as a sort of quick-
 
 and-dirty poor man's unit testing, so long as you accept that the tests 
 
 simply won't do anything if you run with the -O flag. And I sometimes use 
 
 assert False in code to mark code branches that haven't been written 
 
 yet, and I want them to fail. Although raise NotImplementedError is 
 
 probably better for that, if a little more verbose.)
 
 
 
 Opinions on assertions vary, because they can be a statement of 
 
 confidence about the correctness of the code. If you're certain that the 
 
 code is correct, then assertions are pointless, since they will never 
 
 fail and you can safely remove them. If you're certain the checks can 
 
 fail (e.g. when testing input data provided by the user), then you dare 
 
 not use assert since it may be compiled away and then your checks will be 
 
 skipped.
 
 
 
 It's the situations in between those two that are interesting, times when 
 
 you're certain the code is correct but not *quite* absolutely certain. 
 
 Perhaps you've missed some odd corner case (we're all only human). In 
 
 this case an extra runtime check helps reassure you that any errors will 
 
 be caught as early as possible rather than in distant parts of the code.
 
 
 
 (This is why assert can be divisive. Since we vary in our confidence 
 
 about the correctness of code, one person's useful assert is another 
 
 person's useless runtime test.)
 
 
 
 Another good use for asserts is checking program invariants. An invariant 
 
 is some condition which you can rely on to be true unless a bug causes it 
 
 to become false. If there's a bug, better to find out as early as 
 
 possible, so we make a test for it, but we don't want to slow the code 
 
 down with such tests. Hence assert, which can be turned on in development 
 
 and off in production.
 
 
 
 An example of an invariant might be, if your function expects a database 
 
 connection to be open when it starts, and promises that it will still be 
 
 open when it returns, that's an invariant of the function:
 
 
 
 def some_function(arg):
 
 assert not DB.closed()
 
 ... # code goes here
 
 assert not DB.closed()
 
 return result
 
 
 
 
 
 Assertions also make good checked comments. Instead of writing a comment:
 
 
 
 # when we reach here, we know that n  2
 
 
 
 you can ensure it is checked at runtime by turning it into an assert:
 
 
 
 assert n  2
 
 
 
 Assertions are also a form of defensive programming. You're not 
 
 protecting against errors in the code as it is now, but protecting 
 
 against changes which introduce errors later. Ideally, unit tests will 
 
 pick those up, but let's face it, even when tests exist at all, they're 
 
 often incomplete. Build-bots can be down and nobody notices for weeks, or 
 
 people forget to run tests before committing code. Having an internal 
 
 check is another line of defence against errors sneaking in, especially 
 
 those which don't noisily fail but cause the code to malfunction and 
 
 return

Re: When to use assert

2014-10-21 Thread Steven D'Aprano
Anton wrote:

 I use ORM and often need to write a function that either takes an id of
 the record or already loaded model object. So I end up writing a piece of
 code like below:
 
 def do_something(instance):
 if isinstance(instance_or_id, int):
 instance = Model.get(instance)
 assert isinstance(instance, Model)
 # Code that assumes that instance is an object of type Model

 do_somthing is not a part of public library, though it is a public
 function, which can and intended to be used by other programmers; and
 assert should never happen if a client uses the function as planned.

I think you mean the assert should never fail.

That seems like a reasonable use for assert, with a proviso below. It's
behaving like a checked comment or a post-condition test: asserting that
Model.get returns a Model instance.

But, the idea of *requiring* Model.get to return a Model instance may be
inadvisable. It goes against duck-typing, and it prevents Model from making
some kinds of implementation changes that might break your post-condition
that get() always returns an instance. For example, it might return a proxy
object instead, and then your assert will fail.


 I 
 wonder if this use-case is controversial to this part:
 
 Many people use asserts as a quick and easy way to raise an exception if
 an argument is given the wrong value. But this is wrong, dangerously
 wrong, for two reasons. The first is that AssertionError is usually the
 wrong error to give when testing function arguments. You wouldn't write
 code like this:
 
 if not isinstance(x, int):
 raise AssertionError(not an int)
 
 you'd raise TypeError instead. assert raises the wrong sort of
 exception.

No, because the nature of the exception depends on the intent of the test
and the audience who is expected to see it. In an ideal world,
AssertionError should never be seen by the end user, or the developer
calling your code (assuming that she obeys the documented requirements of
your code). A failed assert should be considered an internal error, which
the user never sees. Since the failure:

Model.get has stopped returning Model instances

is likely to be an internal problem (oops, I broke the get() method, better
fix that) rather than an expected error, using assert is okay.

What would *not* be okay is something like this:


def do_something(instance_or_id):
if isinstance(instance_or_id, int):
instance = Model.get(instance_or_id)
assert isinstance(instance, Model)
# Code that assumes that instance is an object of type Model


since that fails with (for example) do_something(None): either the assert is
not checked at all, and there will be some mysterious failure deep inside
your code, or the caller will see AssertionError instead of TypeError,
violating user expectations and good design that type errors should raise
TypeError.

A better way to write this might be to have Model.get() responsible for the
error checking, and then just delegate to it:

class Model:
def get(self, obj):
if isinstance(obj, Model):
return obj
elif isinstance(obj, int):
model = Model(do something here)
return model
raise TypeError('expected an int ID or a Model instance')


def do_something(instance_or_id):
instance = Model.get(instance_or_id)
assert isinstance(instance, Model)
# Code that assumes that instance is an object of type Model


That means that the logic for what is acceptable as a Model is all in one
place, namely the Model.get method, and callers don't need to care about
the pre-condition argument is a Model or an integer ID, they only need to
care about the post-condition result of get() is a Model.



-- 
Steven

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: When to use assert

2014-10-21 Thread Chris Angelico
On Wed, Oct 22, 2014 at 12:44 PM, Steven D'Aprano
steve+comp.lang.pyt...@pearwood.info wrote:
 def do_something(instance_or_id):
 instance = Model.get(instance_or_id)
 assert isinstance(instance, Model)
 # Code that assumes that instance is an object of type Model


 That means that the logic for what is acceptable as a Model is all in one
 place, namely the Model.get method, and callers don't need to care about
 the pre-condition argument is a Model or an integer ID, they only need to
 care about the post-condition result of get() is a Model.

And at that point, the assertion is redundant, on par with:

a = len(seq)
assert isinstance(a, int)

because you shouldn't have to assert what's part of a function's guarantee.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: When to use assert

2013-11-18 Thread Robert Day


On 17/11/13 13:33, Roy Smith wrote:
Every once in a while, I'll get into a situation where something is 
happening that I just can't understand. If a given pice of code is 
being called, there's NO WAY the program should be exhibiting the 
behavior it's exhibiting. But, there's also NO WAY that piece of code 
can't be getting called. So, I stick assert 0 in the code an re-run 
the program to see if I get an AssertionError. If I do, then I know 
the code is being run. If I don't then I know it's not. Either way, I 
know more about what's going on than I did before. Once I know what's 
going on, I remove the assert. 


Are assertions the right thing in that case? I'm becoming more and more 
inclined to the idea that if you want to know whether code is getting 
run, you should put a debug log in, and leave it in. That way it's 
easier to track down the next bug (I don't know about others, but when I 
write buggy code I go all-out and put lots of bugs in rather than just one).


Rob
--
https://mail.python.org/mailman/listinfo/python-list


Re: When to use assert

2013-11-18 Thread Oscar Benjamin
On 17 November 2013 13:33, Roy Smith r...@panix.com wrote:

 So, I stick assert 0 in the code an re-run the program to see if I get
 an AssertionError.  If I do, then I know the code is being run.  If I
 don't then I know it's not.  Either way, I know more about what's going
 on than I did before.  Once I know what's going on, I remove the assert.

If the program is invoked from a terminal I would probably go with
'import pdb; pdb.set_trace()' rather than 'assert 0'. Then you can
check much more than whether or not the code is being executed. It's a
bit more to type but I type it so often that I can now type it *really
fast*.


Oscar
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: When to use assert

2013-11-18 Thread Mark Lawrence

On 18/11/2013 09:50, Oscar Benjamin wrote:

On 17 November 2013 13:33, Roy Smith r...@panix.com wrote:


So, I stick assert 0 in the code an re-run the program to see if I get
an AssertionError.  If I do, then I know the code is being run.  If I
don't then I know it's not.  Either way, I know more about what's going
on than I did before.  Once I know what's going on, I remove the assert.


If the program is invoked from a terminal I would probably go with
'import pdb; pdb.set_trace()' rather than 'assert 0'. Then you can
check much more than whether or not the code is being executed. It's a
bit more to type but I type it so often that I can now type it *really
fast*.


Oscar



If I used something that often I'd either cut and paste it or have a key 
combination set up to insert it automatically.  Or get my man to type it 
up for me :)


--
Python is the second best programming language in the world.
But the best has yet to be invented.  Christian Tismer

Mark Lawrence

--
https://mail.python.org/mailman/listinfo/python-list


Re: When to use assert

2013-11-18 Thread Tim Chase
On 2013-11-18 09:50, Oscar Benjamin wrote:
 If the program is invoked from a terminal I would probably go with
 'import pdb; pdb.set_trace()' rather than 'assert 0'. Then you can
 check much more than whether or not the code is being executed.
 It's a bit more to type but I type it so often that I can now type
 it *really fast*.

I do this so much that on my main development machines, I have a line
in my vimrc file

  nnoremap leaderp oimport pdb; pdb.set_trace()esc
  nnoremap leaderP Oimport pdb; pdb.set_trace()esc

which maps the the leader key (defaults to \) followed by p/P to
insert the pdb line below/above the current line.  Saves bunches of
time  hassle.  I'm sure it's equally easy in other quality editors.

-tkc



-- 
https://mail.python.org/mailman/listinfo/python-list


Re: When to use assert

2013-11-17 Thread Tim Chase
On 2013-11-17 07:35, Steven D'Aprano wrote:
 py x = 23
 py assert x  0, x is not zero or negative

This is the worst way to use an assertion:  with a misleading
message ;-)

-tkc


-- 
https://mail.python.org/mailman/listinfo/python-list


Re: When to use assert

2013-11-17 Thread Roy Smith
In article 528871d5$0$29975$c3e8da3$54964...@news.astraweb.com,
 Steven D'Aprano steve+comp.lang.pyt...@pearwood.info wrote:

 * Don't use assert for any error which you expect to recover from.
   In other words, you've got no reason to catch an AssertionError
   exception in production code.

Which leads to another reason for using asserts...

Every once in a while, I'll get into a situation where something is 
happening that I just can't understand.  If a given pice of code is 
being called, there's NO WAY the program should be exhibiting the 
behavior it's exhibiting.  But, there's also NO WAY that piece of code 
can't be getting called.

So, I stick assert 0 in the code an re-run the program to see if I get 
an AssertionError.  If I do, then I know the code is being run.  If I 
don't then I know it's not.  Either way, I know more about what's going 
on than I did before.  Once I know what's going on, I remove the assert.
-- 
https://mail.python.org/mailman/listinfo/python-list



Re: When to use assert

2013-11-17 Thread Steven D'Aprano
On Sun, 17 Nov 2013 06:50:56 -0600, Tim Chase wrote:

 On 2013-11-17 07:35, Steven D'Aprano wrote:
 py x = 23
 py assert x  0, x is not zero or negative
 
 This is the worst way to use an assertion:  with a misleading message
 ;-)


D'oh!


Sorry about that.



-- 
Steven
-- 
https://mail.python.org/mailman/listinfo/python-list


When to use assert

2013-11-16 Thread Steven D'Aprano
The question of when to use the assert statement comes up occasionally, 
usually in response to somebody misusing it, so I thought I'd write a 
post describing when and why to use assertions, and when not to.

For those who aren't aware of it, Python's assert checks a condition, 
if it is true it does nothing, and if it is false it raises an 
AssertionError with an optional error message. For example:

py x = 23
py assert x  0, x is not zero or negative
py assert x%2 == 0, x is not an even number
Traceback (most recent call last):
  File stdin, line 1, in module
AssertionError: x is not an even number


Many people use asserts as a quick and easy way to raise an exception if 
an argument is given the wrong value. But this is wrong, dangerously 
wrong, for two reasons. The first is that AssertionError is usually the 
wrong error to give when testing function arguments. You wouldn't write 
code like this:

if not isinstance(x, int):
raise AssertionError(not an int)

you'd raise TypeError instead. assert raises the wrong sort of 
exception.

But, and more dangerously, there's a twist with assert: it can be 
compiled away and never executed, if you run Python with the -O or -OO 
optimization flags, and consequently there is no guarantee that assert 
statements will actually be run. When using assert properly, this is a 
feature, but when assert is used inappropriately, it leads to code that 
is completely broken when running with the -O flag.

When should use assert? In no particular order, assertions should be used 
for:

* defensive programming;
* runtime checks on program logic;
* checking contracts (e.g. pre-conditions and post-conditions);
* program invariants; and 
* checked documentation.

(It's also acceptable to use assert when testing code, as a sort of quick-
and-dirty poor man's unit testing, so long as you accept that the tests 
simply won't do anything if you run with the -O flag. And I sometimes use 
assert False in code to mark code branches that haven't been written 
yet, and I want them to fail. Although raise NotImplementedError is 
probably better for that, if a little more verbose.)

Opinions on assertions vary, because they can be a statement of 
confidence about the correctness of the code. If you're certain that the 
code is correct, then assertions are pointless, since they will never 
fail and you can safely remove them. If you're certain the checks can 
fail (e.g. when testing input data provided by the user), then you dare 
not use assert since it may be compiled away and then your checks will be 
skipped.

It's the situations in between those two that are interesting, times when 
you're certain the code is correct but not *quite* absolutely certain. 
Perhaps you've missed some odd corner case (we're all only human). In 
this case an extra runtime check helps reassure you that any errors will 
be caught as early as possible rather than in distant parts of the code.

(This is why assert can be divisive. Since we vary in our confidence 
about the correctness of code, one person's useful assert is another 
person's useless runtime test.)

Another good use for asserts is checking program invariants. An invariant 
is some condition which you can rely on to be true unless a bug causes it 
to become false. If there's a bug, better to find out as early as 
possible, so we make a test for it, but we don't want to slow the code 
down with such tests. Hence assert, which can be turned on in development 
and off in production.

An example of an invariant might be, if your function expects a database 
connection to be open when it starts, and promises that it will still be 
open when it returns, that's an invariant of the function:

def some_function(arg):
assert not DB.closed()
... # code goes here
assert not DB.closed()
return result


Assertions also make good checked comments. Instead of writing a comment:

# when we reach here, we know that n  2

you can ensure it is checked at runtime by turning it into an assert:

assert n  2

Assertions are also a form of defensive programming. You're not 
protecting against errors in the code as it is now, but protecting 
against changes which introduce errors later. Ideally, unit tests will 
pick those up, but let's face it, even when tests exist at all, they're 
often incomplete. Build-bots can be down and nobody notices for weeks, or 
people forget to run tests before committing code. Having an internal 
check is another line of defence against errors sneaking in, especially 
those which don't noisily fail but cause the code to malfunction and 
return incorrect results.

Suppose you have a series of if...elif blocks, where you know ahead of 
time what values some variable is expected to have:

# target is expected to be one of x, y, or z, and nothing else.
if target == x:
run_x_code()
elif target == y:
run_y_code()
else:
run_z_code()


Assume that this code is completely correct now. But will it stay 
correct