Skip to content

gh-119057: Use better error messages for zero division #119066

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jun 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Doc/howto/logging-cookbook.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2950,7 +2950,7 @@ When run, this produces a file with exactly two lines:
.. code-block:: none

28/01/2015 07:21:23|INFO|Sample message|
28/01/2015 07:21:23|ERROR|ZeroDivisionError: integer division or modulo by zero|'Traceback (most recent call last):\n File "logtest7.py", line 30, in main\n x = 1 / 0\nZeroDivisionError: integer division or modulo by zero'|
28/01/2015 07:21:23|ERROR|ZeroDivisionError: division by zero|'Traceback (most recent call last):\n File "logtest7.py", line 30, in main\n x = 1 / 0\nZeroDivisionError: division by zero'|

While the above treatment is simplistic, it points the way to how exception
information can be formatted to your liking. The :mod:`traceback` module may be
Expand Down
2 changes: 1 addition & 1 deletion Lib/_pylong.py
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ def int_divmod(a, b):
Its time complexity is O(n**1.58), where n = #bits(a) + #bits(b).
"""
if b == 0:
raise ZeroDivisionError
raise ZeroDivisionError('division by zero')
elif b < 0:
q, r = int_divmod(-a, -b)
return q, -r
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/mathdata/ieee754.txt
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ inf
>>> 0 ** -1
Traceback (most recent call last):
...
ZeroDivisionError: 0.0 cannot be raised to a negative power
ZeroDivisionError: zero to a negative power
>>> pow(0, NAN)
nan

Expand Down
10 changes: 10 additions & 0 deletions Lib/test/test_builtin.py
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,16 @@ def test_divmod(self):
self.assertAlmostEqual(result[1], exp_result[1])

self.assertRaises(TypeError, divmod)
self.assertRaisesRegex(
ZeroDivisionError,
"division by zero",
divmod, 1, 0,
)
self.assertRaisesRegex(
ZeroDivisionError,
"division by zero",
divmod, 0.0, 0,
)

def test_eval(self):
self.assertEqual(eval('1+1'), 2)
Expand Down
8 changes: 4 additions & 4 deletions Lib/test/test_doctest/test_doctest.py
Original file line number Diff line number Diff line change
Expand Up @@ -1035,7 +1035,7 @@ def exceptions(): r"""
... >>> x = 12
... >>> print(x//0)
... Traceback (most recent call last):
... ZeroDivisionError: integer division or modulo by zero
... ZeroDivisionError: division by zero
... '''
>>> test = doctest.DocTestFinder().find(f)[0]
>>> doctest.DocTestRunner(verbose=False).run(test)
Expand All @@ -1052,7 +1052,7 @@ def exceptions(): r"""
... >>> print('pre-exception output', x//0)
... pre-exception output
... Traceback (most recent call last):
... ZeroDivisionError: integer division or modulo by zero
... ZeroDivisionError: division by zero
... '''
>>> test = doctest.DocTestFinder().find(f)[0]
>>> doctest.DocTestRunner(verbose=False).run(test)
Expand All @@ -1063,7 +1063,7 @@ def exceptions(): r"""
print('pre-exception output', x//0)
Exception raised:
...
ZeroDivisionError: integer division or modulo by zero
ZeroDivisionError: division by zero
TestResults(failed=1, attempted=2)

Exception messages may contain newlines:
Expand Down Expand Up @@ -1258,7 +1258,7 @@ def exceptions(): r"""
Exception raised:
Traceback (most recent call last):
...
ZeroDivisionError: integer division or modulo by zero
ZeroDivisionError: division by zero
TestResults(failed=1, attempted=1)

>>> _colorize.COLORIZE = save_colorize
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_generators.py
Original file line number Diff line number Diff line change
Expand Up @@ -907,7 +907,7 @@ def b():
File "<stdin>", line 1, in ?
File "<stdin>", line 2, in g
File "<stdin>", line 2, in f
ZeroDivisionError: integer division or modulo by zero
ZeroDivisionError: division by zero
>>> next(k) # and the generator cannot be resumed
Traceback (most recent call last):
File "<stdin>", line 1, in ?
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_genexps.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@
next(g)
File "<pyshell#35>", line 1, in <generator expression>
g = (10 // i for i in (5, 0, 2))
ZeroDivisionError: integer division or modulo by zero
ZeroDivisionError: division by zero
>>> next(g)
Traceback (most recent call last):
File "<pyshell#38>", line 1, in -toplevel-
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Improve :exc:`ZeroDivisionError` error message.
Now, all error messages are harmonized: all ``/``, ``//``, and ``%``
operations just use "division by zero" message.
And ``0 ** -1`` operation uses "zero to a negative power".
4 changes: 2 additions & 2 deletions Objects/complexobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -523,7 +523,7 @@ complex_div(PyObject *v, PyObject *w)
errno = 0;
quot = _Py_c_quot(a, b);
if (errno == EDOM) {
PyErr_SetString(PyExc_ZeroDivisionError, "complex division by zero");
PyErr_SetString(PyExc_ZeroDivisionError, "division by zero");
return NULL;
}
return PyComplex_FromCComplex(quot);
Expand Down Expand Up @@ -554,7 +554,7 @@ complex_pow(PyObject *v, PyObject *w, PyObject *z)
_Py_ADJUST_ERANGE2(p.real, p.imag);
if (errno == EDOM) {
PyErr_SetString(PyExc_ZeroDivisionError,
"0.0 to a negative or complex power");
"zero to a negative or complex power");
return NULL;
}
else if (errno == ERANGE) {
Expand Down
11 changes: 5 additions & 6 deletions Objects/floatobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -623,7 +623,7 @@ float_div(PyObject *v, PyObject *w)
CONVERT_TO_DOUBLE(w, b);
if (b == 0.0) {
PyErr_SetString(PyExc_ZeroDivisionError,
"float division by zero");
"division by zero");
return NULL;
}
a = a / b;
Expand All @@ -639,7 +639,7 @@ float_rem(PyObject *v, PyObject *w)
CONVERT_TO_DOUBLE(w, wx);
if (wx == 0.0) {
PyErr_SetString(PyExc_ZeroDivisionError,
"float modulo by zero");
"division by zero");
return NULL;
}
mod = fmod(vx, wx);
Expand Down Expand Up @@ -704,7 +704,7 @@ float_divmod(PyObject *v, PyObject *w)
CONVERT_TO_DOUBLE(v, vx);
CONVERT_TO_DOUBLE(w, wx);
if (wx == 0.0) {
PyErr_SetString(PyExc_ZeroDivisionError, "float divmod()");
PyErr_SetString(PyExc_ZeroDivisionError, "division by zero");
return NULL;
}
_float_div_mod(vx, wx, &floordiv, &mod);
Expand All @@ -719,7 +719,7 @@ float_floor_div(PyObject *v, PyObject *w)
CONVERT_TO_DOUBLE(v, vx);
CONVERT_TO_DOUBLE(w, wx);
if (wx == 0.0) {
PyErr_SetString(PyExc_ZeroDivisionError, "float floor division by zero");
PyErr_SetString(PyExc_ZeroDivisionError, "division by zero");
return NULL;
}
_float_div_mod(vx, wx, &floordiv, &mod);
Expand Down Expand Up @@ -788,8 +788,7 @@ float_pow(PyObject *v, PyObject *w, PyObject *z)
int iw_is_odd = DOUBLE_IS_ODD_INTEGER(iw);
if (iw < 0.0) {
PyErr_SetString(PyExc_ZeroDivisionError,
"0.0 cannot be raised to a "
"negative power");
"zero to a negative power");
return NULL;
}
/* use correct sign if iw is odd */
Expand Down
5 changes: 2 additions & 3 deletions Objects/longobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -3109,8 +3109,7 @@ long_divrem(PyLongObject *a, PyLongObject *b,
PyLongObject *z;

if (size_b == 0) {
PyErr_SetString(PyExc_ZeroDivisionError,
"integer division or modulo by zero");
PyErr_SetString(PyExc_ZeroDivisionError, "division by zero");
return -1;
}
if (size_a < size_b ||
Expand Down Expand Up @@ -3173,7 +3172,7 @@ long_rem(PyLongObject *a, PyLongObject *b, PyLongObject **prem)

if (size_b == 0) {
PyErr_SetString(PyExc_ZeroDivisionError,
"integer modulo by zero");
"division by zero");
return -1;
}
if (size_a < size_b ||
Expand Down
Loading