classification
Title: OverflowError should not happen for integer operations
Type: behavior Stage: resolved
Components: Documentation, Interpreter Core, Library (Lib) Versions: Python 3.4
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: docs@python Nosy List: docs@python, josh.r, python-dev, r.david.murray, skrah, terry.reedy, theme
Priority: normal Keywords:

Created on 2014-05-23 10:34 by theme, last changed 2014-06-16 07:33 by terry.reedy. This issue is now closed.

Messages (10)
msg218957 - (view) Author: (theme) Date: 2014-05-23 10:34
From the documentation at https://docs.python.org/3.4/library/exceptions.html#OverflowError all integer operations should not throw OverflowError no matter what. However, there are so many issues here that describe library functions and built-in functions doing exactly that (just search this website for OverflowError).
This might cause an expected uncaught exception that the cause cannot be deduced after reading the documentation.
There are 2 ways to fix this: either change the documentation, or change something in the core of the interpreter.
Note: I don't know what versions of python this affects, but I have tested this on python 3.4.0 on windows. (the version that was downloadable from www.python.org/downloads/)
msg219004 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2014-05-23 21:18
In 2.7, it was only *long integers* that could not overflow. In both python 2 and 3, the comment only applys to operations on integers and not to integers converted to floats. Perhaps that could be clarified. If have any example from running Python where (long) integer operations raising OverflowError and there is no issue about the bug, please open one. If there are any issues that describe such exceptions as not bugs, please list them also.
msg219024 - (view) Author: (theme) Date: 2014-05-24 04:44
This is a (non-comprehensive) list of issues that describe or imply that OverflowError on integers is normal.

- http://bugs.python.org/issue7267 "Attached patch works around the inital issue (u'{0:c}'.format(256)) by raising OverflowError on int.__format__('c') if the value is not in range(0, 256)."
- http://bugs.python.org/issue20539 "Patch applied to the default branch (but with OverflowError instead of ValueError for large positive inputs)."
- http://bugs.python.org/issue21444 "CPython has historically imposed some artificial implementation specific details in order make the implementation cleaner and faster internally (i.e. a limit on the number of function arguments, sys.maxsize limits, etc.)"
- http://bugs.python.org/issue15988 (No message explicitly telling that OverflowError is the right error to raise. However, it is implied that only the error message, not the error type, should be changed)

There might be other similar issues out there.
Am I opening a can of worms?
msg219032 - (view) Author: Stefan Krah (skrah) * (Python committer) Date: 2014-05-24 10:50
OverflowError vs. ValueError is a debatable issue (msg215873). In my
view ValueError should be raised in most of the cases.

I do not see anything wrong with the docs though, since the link
you posted talks about "arithmetic operations".
msg219069 - (view) Author: (theme) Date: 2014-05-25 02:41
skrah: I am not sure what link are you referring to.
However, no matter which link you are talking about, the documentation still doesn't match the behavior no matter how you interpret it.

Some possible interpretations of the documentation on OverflowError:

- OverflowError is raised only by "arithmetic operations" on non-integers in the strictest sense possible (e.g. +,-,*,/,**) , which does not include library functions. This interpretation seems absurd to me.

- OverflowError is raised by arithmetic operations on "non-integers", where "integers" refer only to python integers, which never overflow, and excludes C integers. This seems pretty awkward, since this implies that the behavior of library functions regarding overflows is implementation-defined (aka undefined behavior) to some extent, and I don't think this is good.

- OverflowError is raised by arithmetic operations on non-integers, which can be initiated by either the user, a user script or a library function. However, the issues linked in msg219024 involve library functions that obviously deals only with integers. Resolving behaviors to match this interpretation seems pretty logical to me, but will most likely cause a lot of implementation issues.
msg219590 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2014-06-02 14:27
Your second bullet item would seem to me to be the obvious interpretation of the docs.  This is, after all, Python, so 'integer' would refer to Python integers and their operations.  So I agree with Stefan that the docs are correct as they stand.  As he also said, there may be places where OverflowError is currently raised that may not be appropriate, especially since we are dealing with a codebase that once had Python integer operations that *could* overflow.
msg219611 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2014-06-02 18:02
I was tempted to close this, but I think there is an issue that 'theme' has implied but not stated clearly enough. The OverflowError entry might be re-written as "Raised when the result of an arithmetic operation involving at least one non-int is too large to be represented. For pairs of ints, MemoryError is raised instead." This much is true. However, the clear implication is that a binary operation on non-ints is the only situation in which OverflowError is raised. But as theme has shown, it is not. In this sense, the doc is incomplete.

Another, unstated, situation is failure of an internal conversion from an int to an internal type. In #20539, #20539, the justification for switching from MemoryError to OverflowError when factorial input grows too large for conversion is that memory is then not filled. In #21444, the justification is history.

A third possibility is that OverflowError is used instead of ValueError when an int fails a simple range check. See #15988: _testcapi.getargs_b requires an int in range(256). -1 and 256 raise OverflowErrors. #7267 is about the same issue. An int not being in range(256) has nothing to do with the merging of integer types in 3.x.

So I think that the docs need a new sentence. Both alternatives can be summarized by "OverflowError may also be raised for integers that are outside a required range." Knowing this might help people debugging such situations.
msg219615 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2014-06-02 18:45
"Integers are outside a required range" makes me wonder why it isn't a ValueError.  An OverflowError should be the result of a *computation*, IMO, not a bounds check.

So, maybe add your sentence with the additional phrase "for historical reasons"? :)
msg219727 - (view) Author: Josh Rosenberg (josh.r) * Date: 2014-06-03 22:22
It usually doesn't just mean "outside a required range", it means "outside the range of values representable due to implementation specific limitations (e.g. the function is converting to a C type)". You don't raise OverflowError because your function only allows values from 0-1000, you raise it because you accept "arbitrary" values that are in fact limited by the definition of int, long, Py_ssize_t, etc. It does get weird when you talk about unsigned values, where they're usually used because negative values aren't logically valid, not merely a side-effect of trying to use more efficient types. Case #3 mentioned in Terry's list is because it's stored as a C unsigned char, which simply doesn't support values outside the range [0,256).

I think of the distinction between ValueError and OverflowError as the difference between "The argument makes no logical sense in context" and "The argument can't be used due to interpreter limitations". I suppose it makes sense to be consistent; if your function only accepts values from 0-1000 on a logical basis, then any OverflowErrors should be converted to ValueErrors (since no change in implementation would alter the accepted logical range).

I'll grant it gets fuzzy when we talk about bytes (after all, the function could choose to use a larger storage type, and probably didn't because program logic dictates that [0,256) is the value range). Not sure how it's possible to handle that, or if it's even worth it when so much code, APIs, and third party modules are saying that implementation limits (OverflowError) trump logical limits (ValueError) when it comes to the exception type.
msg220702 - (view) Author: Roundup Robot (python-dev) Date: 2014-06-16 07:31
New changeset 9ba324a20bad by Terry Jan Reedy in branch '3.4':
Issue #21559: Add alternative (historical) reason for OverflowError.
http://hg.python.org/cpython/rev/9ba324a20bad
History
Date User Action Args
2014-06-16 07:33:06terry.reedysetstatus: open -> closed
2014-06-16 07:32:56terry.reedysetresolution: fixed
stage: resolved
2014-06-16 07:31:51python-devsetnosy: + python-dev
messages: + msg220702
2014-06-03 22:22:28josh.rsetnosy: + josh.r
messages: + msg219727
2014-06-02 18:45:05r.david.murraysetmessages: + msg219615
2014-06-02 18:02:12terry.reedysetmessages: + msg219611
2014-06-02 14:27:57r.david.murraysetnosy: + r.david.murray
messages: + msg219590
2014-05-25 02:41:35themesetmessages: + msg219069
2014-05-24 10:50:14skrahsetnosy: + skrah
messages: + msg219032
2014-05-24 04:44:25themesetmessages: + msg219024
2014-05-23 21:18:43terry.reedysetnosy: + terry.reedy
messages: + msg219004
2014-05-23 10:35:32themesetcomponents: + Library (Lib)
2014-05-23 10:34:39themecreate