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

This commit is contained in:
Nikita Sobolev 2024-06-03 19:03:56 +03:00 committed by GitHub
parent 153b118b78
commit 1d4c2e4a87
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 32 additions and 20 deletions

View File

@ -2950,7 +2950,7 @@ When run, this produces a file with exactly two lines:
.. code-block:: none .. code-block:: none
28/01/2015 07:21:23|INFO|Sample message| 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 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 information can be formatted to your liking. The :mod:`traceback` module may be

View File

@ -530,7 +530,7 @@ def int_divmod(a, b):
Its time complexity is O(n**1.58), where n = #bits(a) + #bits(b). Its time complexity is O(n**1.58), where n = #bits(a) + #bits(b).
""" """
if b == 0: if b == 0:
raise ZeroDivisionError raise ZeroDivisionError('division by zero')
elif b < 0: elif b < 0:
q, r = int_divmod(-a, -b) q, r = int_divmod(-a, -b)
return q, -r return q, -r

View File

@ -116,7 +116,7 @@ inf
>>> 0 ** -1 >>> 0 ** -1
Traceback (most recent call last): Traceback (most recent call last):
... ...
ZeroDivisionError: 0.0 cannot be raised to a negative power ZeroDivisionError: zero to a negative power
>>> pow(0, NAN) >>> pow(0, NAN)
nan nan

View File

@ -662,6 +662,16 @@ class BuiltinTest(unittest.TestCase):
self.assertAlmostEqual(result[1], exp_result[1]) self.assertAlmostEqual(result[1], exp_result[1])
self.assertRaises(TypeError, divmod) 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): def test_eval(self):
self.assertEqual(eval('1+1'), 2) self.assertEqual(eval('1+1'), 2)

View File

@ -1035,7 +1035,7 @@ replaced with any other string:
... >>> x = 12 ... >>> x = 12
... >>> print(x//0) ... >>> print(x//0)
... Traceback (most recent call last): ... Traceback (most recent call last):
... ZeroDivisionError: integer division or modulo by zero ... ZeroDivisionError: division by zero
... ''' ... '''
>>> test = doctest.DocTestFinder().find(f)[0] >>> test = doctest.DocTestFinder().find(f)[0]
>>> doctest.DocTestRunner(verbose=False).run(test) >>> doctest.DocTestRunner(verbose=False).run(test)
@ -1052,7 +1052,7 @@ unexpected exception:
... >>> print('pre-exception output', x//0) ... >>> print('pre-exception output', x//0)
... pre-exception output ... pre-exception output
... Traceback (most recent call last): ... Traceback (most recent call last):
... ZeroDivisionError: integer division or modulo by zero ... ZeroDivisionError: division by zero
... ''' ... '''
>>> test = doctest.DocTestFinder().find(f)[0] >>> test = doctest.DocTestFinder().find(f)[0]
>>> doctest.DocTestRunner(verbose=False).run(test) >>> doctest.DocTestRunner(verbose=False).run(test)
@ -1063,7 +1063,7 @@ unexpected exception:
print('pre-exception output', x//0) print('pre-exception output', x//0)
Exception raised: Exception raised:
... ...
ZeroDivisionError: integer division or modulo by zero ZeroDivisionError: division by zero
TestResults(failed=1, attempted=2) TestResults(failed=1, attempted=2)
Exception messages may contain newlines: Exception messages may contain newlines:
@ -1258,7 +1258,7 @@ unexpected exception:
Exception raised: Exception raised:
Traceback (most recent call last): Traceback (most recent call last):
... ...
ZeroDivisionError: integer division or modulo by zero ZeroDivisionError: division by zero
TestResults(failed=1, attempted=1) TestResults(failed=1, attempted=1)
>>> _colorize.COLORIZE = save_colorize >>> _colorize.COLORIZE = save_colorize

View File

@ -907,7 +907,7 @@ Specification: Generators and Exception Propagation
File "<stdin>", line 1, in ? File "<stdin>", line 1, in ?
File "<stdin>", line 2, in g File "<stdin>", line 2, in g
File "<stdin>", line 2, in f 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 >>> next(k) # and the generator cannot be resumed
Traceback (most recent call last): Traceback (most recent call last):
File "<stdin>", line 1, in ? File "<stdin>", line 1, in ?

View File

@ -223,7 +223,7 @@ Verify exception propagation
next(g) next(g)
File "<pyshell#35>", line 1, in <generator expression> File "<pyshell#35>", line 1, in <generator expression>
g = (10 // i for i in (5, 0, 2)) g = (10 // i for i in (5, 0, 2))
ZeroDivisionError: integer division or modulo by zero ZeroDivisionError: division by zero
>>> next(g) >>> next(g)
Traceback (most recent call last): Traceback (most recent call last):
File "<pyshell#38>", line 1, in -toplevel- File "<pyshell#38>", line 1, in -toplevel-

View File

@ -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".

View File

@ -523,7 +523,7 @@ complex_div(PyObject *v, PyObject *w)
errno = 0; errno = 0;
quot = _Py_c_quot(a, b); quot = _Py_c_quot(a, b);
if (errno == EDOM) { if (errno == EDOM) {
PyErr_SetString(PyExc_ZeroDivisionError, "complex division by zero"); PyErr_SetString(PyExc_ZeroDivisionError, "division by zero");
return NULL; return NULL;
} }
return PyComplex_FromCComplex(quot); return PyComplex_FromCComplex(quot);
@ -554,7 +554,7 @@ complex_pow(PyObject *v, PyObject *w, PyObject *z)
_Py_ADJUST_ERANGE2(p.real, p.imag); _Py_ADJUST_ERANGE2(p.real, p.imag);
if (errno == EDOM) { if (errno == EDOM) {
PyErr_SetString(PyExc_ZeroDivisionError, PyErr_SetString(PyExc_ZeroDivisionError,
"0.0 to a negative or complex power"); "zero to a negative or complex power");
return NULL; return NULL;
} }
else if (errno == ERANGE) { else if (errno == ERANGE) {

View File

@ -623,7 +623,7 @@ float_div(PyObject *v, PyObject *w)
CONVERT_TO_DOUBLE(w, b); CONVERT_TO_DOUBLE(w, b);
if (b == 0.0) { if (b == 0.0) {
PyErr_SetString(PyExc_ZeroDivisionError, PyErr_SetString(PyExc_ZeroDivisionError,
"float division by zero"); "division by zero");
return NULL; return NULL;
} }
a = a / b; a = a / b;
@ -639,7 +639,7 @@ float_rem(PyObject *v, PyObject *w)
CONVERT_TO_DOUBLE(w, wx); CONVERT_TO_DOUBLE(w, wx);
if (wx == 0.0) { if (wx == 0.0) {
PyErr_SetString(PyExc_ZeroDivisionError, PyErr_SetString(PyExc_ZeroDivisionError,
"float modulo by zero"); "division by zero");
return NULL; return NULL;
} }
mod = fmod(vx, wx); mod = fmod(vx, wx);
@ -704,7 +704,7 @@ float_divmod(PyObject *v, PyObject *w)
CONVERT_TO_DOUBLE(v, vx); CONVERT_TO_DOUBLE(v, vx);
CONVERT_TO_DOUBLE(w, wx); CONVERT_TO_DOUBLE(w, wx);
if (wx == 0.0) { if (wx == 0.0) {
PyErr_SetString(PyExc_ZeroDivisionError, "float divmod()"); PyErr_SetString(PyExc_ZeroDivisionError, "division by zero");
return NULL; return NULL;
} }
_float_div_mod(vx, wx, &floordiv, &mod); _float_div_mod(vx, wx, &floordiv, &mod);
@ -719,7 +719,7 @@ float_floor_div(PyObject *v, PyObject *w)
CONVERT_TO_DOUBLE(v, vx); CONVERT_TO_DOUBLE(v, vx);
CONVERT_TO_DOUBLE(w, wx); CONVERT_TO_DOUBLE(w, wx);
if (wx == 0.0) { if (wx == 0.0) {
PyErr_SetString(PyExc_ZeroDivisionError, "float floor division by zero"); PyErr_SetString(PyExc_ZeroDivisionError, "division by zero");
return NULL; return NULL;
} }
_float_div_mod(vx, wx, &floordiv, &mod); _float_div_mod(vx, wx, &floordiv, &mod);
@ -788,8 +788,7 @@ float_pow(PyObject *v, PyObject *w, PyObject *z)
int iw_is_odd = DOUBLE_IS_ODD_INTEGER(iw); int iw_is_odd = DOUBLE_IS_ODD_INTEGER(iw);
if (iw < 0.0) { if (iw < 0.0) {
PyErr_SetString(PyExc_ZeroDivisionError, PyErr_SetString(PyExc_ZeroDivisionError,
"0.0 cannot be raised to a " "zero to a negative power");
"negative power");
return NULL; return NULL;
} }
/* use correct sign if iw is odd */ /* use correct sign if iw is odd */

View File

@ -3121,8 +3121,7 @@ long_divrem(PyLongObject *a, PyLongObject *b,
PyLongObject *z; PyLongObject *z;
if (size_b == 0) { if (size_b == 0) {
PyErr_SetString(PyExc_ZeroDivisionError, PyErr_SetString(PyExc_ZeroDivisionError, "division by zero");
"integer division or modulo by zero");
return -1; return -1;
} }
if (size_a < size_b || if (size_a < size_b ||
@ -3185,7 +3184,7 @@ long_rem(PyLongObject *a, PyLongObject *b, PyLongObject **prem)
if (size_b == 0) { if (size_b == 0) {
PyErr_SetString(PyExc_ZeroDivisionError, PyErr_SetString(PyExc_ZeroDivisionError,
"integer modulo by zero"); "division by zero");
return -1; return -1;
} }
if (size_a < size_b || if (size_a < size_b ||