Issue46972
This issue tracker has been migrated to GitHub,
and is currently read-only.
For more information,
see the GitHub FAQs in the Python's Developer Guide.
Created on 2022-03-10 09:44 by tfish2, last changed 2022-04-11 14:59 by admin. This issue is now closed.
Messages (6) | |||
---|---|---|---|
msg414837 - (view) | Author: Thomas Fischbacher (tfish2) | Date: 2022-03-10 09:44 | |
The Python reference says: (1) https://docs.python.org/3/library/exceptions.html#concrete-exceptions exception AssertionError Raised when an assert statement fails. (2) https://docs.python.org/3/reference/simple_stmts.html#the-assert-statement "assert ..." is equivalent to "if __debug__: ..." From this, one can infer the guarantee "the -O flag will suppress AssertionError exceptions from being raised". However, there is code in the Python standard library that does a direct "raise AssertionError" (strictly speaking, in violation of (1)), and it is just reasonable to assume that other code following the design of that would then also want to do a direct "raise AssertionError". This happens e.g. in many methods defined in: unittest/mock.py The most appropriate fix here may be to change the documentation to not say: === exception AssertionError Raised when an assert statement fails. === but instead: === exception AssertionError An assert[{add reference to `assert` definition}] statement fails, or a unit testing related assert{...}() callable detects an assertion violation. === |
|||
msg414838 - (view) | Author: Eric V. Smith (eric.smith) * ![]() |
Date: 2022-03-10 10:42 | |
The documentation doesn't say that assert statements are the only place AssertionError is raised, so I don't think it's incorrect. > From this, one can infer the guarantee "the -O flag will suppress AssertionError exceptions from being raised". I don't think that follows from what the documentation says. It's only talking about assert statements. This is equivalent to StopIteration: it is commonly raised by exhausting iterators, but it can be raised elsewhere. Or KeyError: the docs say "Raised when a mapping (dictionary) key is not found in the set of existing keys", but I've raised them in my own code. > An assert[{add reference to `assert` definition}] statement fails, or a unit testing related assert{...}() callable detects an assertion violation. I think that's also misleading, and not an improvement. Why focus just on testing? It can certainly be raised elsewhere. If anything, I think maybe add a note at the top of the list of Concrete Exceptions saying these are common ways these exceptions are raised, but they can be raised elsewhere. But I'm -0 on such a change. |
|||
msg414841 - (view) | Author: Thomas Fischbacher (tfish2) | Date: 2022-03-10 11:12 | |
The documentation of exceptions in the reference is one of the places that makes the life of users substantially harder than it ought to be, since the documentation appears to not have been written with the intent to give guarantees that users can expect correctly written code to follow. I would argue that "The reference documentation for X states that it gets raised under condition Y" generally should be understood as "this is a guarantee that also includes the guarantee that it is not raised under other conditions in correctly written code". Other languages often appear to be somewhat stricter w.r.t. interpreting the reference documentation as binding for correct code - and for Python, having this certainly would help a lot when writing code that can give binding guarantees. |
|||
msg414843 - (view) | Author: Eric V. Smith (eric.smith) * ![]() |
Date: 2022-03-10 12:33 | |
> I would argue that "The reference documentation for X states that it gets raised under condition Y" generally should be understood as "this is a guarantee that also includes the guarantee that it is not raised under other conditions in correctly written code". That's definitely not the case in Python, though. |
|||
msg414844 - (view) | Author: Serhiy Storchaka (serhiy.storchaka) * ![]() |
Date: 2022-03-10 12:40 | |
I concur with Eric. The existing documentation looks pretty clear to me. Any exception can be raised explicitly, no need to repeat this. And unittest.TestCase methods do not raise AssertionError. They raise TestCase.failureException, which by default is set to AssertionError. It is specified in the corresponding module documentation. |
|||
msg415937 - (view) | Author: Thomas Fischbacher (tfish2) | Date: 2022-03-24 12:15 | |
Addendum Serhiy, I agree that my assessment was incorrect. It actually is unittest/mock.py that has quite a few 'raise AssertionError' that are not coming from an 'assert' keyword statement. At a deeper level, the problem here is as follows: Every programming language has to make an awkward choice: either it excludes some authors ("must be forklift certified"), or it adds a lot of bureaucratic scaffolding to have some mechanisms that allow code authors to enforce API contracts (as if this would help to "keep out the tide" of unprincipled code authors), or it takes a more relaxed perspective - as also Perl did - of "we are all responsible users" / "do not do this because you are not invited, not because the owner has a shotgun". I'd call this third approach quite reasonable overall, but then the understanding is that "everybody treats documentation as binding and knows how to write good documentation". After all, we need to be able to reason about code, and in order to do that, it matters to have guarantees such as for example: "Looking up a nonexistent key for a mapping by evaluating the_mapping[the_key] can raise an exception, and when it does, that exception is guaranteed to be an instance of KeyError". Unfortunately, Python on the one hand emphasizes "responsible behavior" - i.e. "people know how to write and read documentation, and the written documentation creates a shared understanding between its author and reader", but on the other hand is often really bad at properly documenting its interfaces. If I had to name one thing that really needs fixing with Python, it would be this. |
History | |||
---|---|---|---|
Date | User | Action | Args |
2022-04-11 14:59:57 | admin | set | github: 91128 |
2022-03-24 12:15:47 | tfish2 | set | messages: + msg415937 |
2022-03-10 12:40:35 | serhiy.storchaka | set | status: open -> closed nosy: + serhiy.storchaka messages: + msg414844 resolution: not a bug stage: resolved |
2022-03-10 12:34:00 | eric.smith | set | nosy:
+ docs@python messages: + msg414843 assignee: docs@python components: + Documentation |
2022-03-10 11:12:00 | tfish2 | set | messages: + msg414841 |
2022-03-10 10:42:05 | eric.smith | set | nosy:
+ eric.smith messages: + msg414838 |
2022-03-10 09:44:46 | tfish2 | create |