diff --git a/Lib/decimal.py b/Lib/decimal.py --- a/Lib/decimal.py +++ b/Lib/decimal.py @@ -1613,7 +1613,7 @@ if self._isnan(): raise ValueError("Cannot convert NaN to integer") elif self._isinfinity(): - raise OverflowError("Cannot convert infinity to integer") + raise ValueError("Cannot convert infinity to integer") s = (-1)**self._sign if self._exp >= 0: return s*int(self._int)*10**self._exp @@ -1839,7 +1839,7 @@ >>> round(Decimal('Inf')) Traceback (most recent call last): ... - OverflowError: cannot round an infinity + ValueError: cannot round an infinity >>> round(Decimal('NaN')) Traceback (most recent call last): ... @@ -1876,7 +1876,8 @@ if self.is_nan(): raise ValueError("cannot round a NaN") else: - raise OverflowError("cannot round an infinity") + # bug 16469: error types should be consistent + raise ValueError("cannot round an infinity") return int(self._rescale(0, ROUND_HALF_EVEN)) def __floor__(self): @@ -1891,7 +1892,8 @@ if self.is_nan(): raise ValueError("cannot round a NaN") else: - raise OverflowError("cannot round an infinity") + # bug 16469: error types should be consistent + raise ValueError("cannot round an infinity") return int(self._rescale(0, ROUND_FLOOR)) def __ceil__(self): @@ -1906,7 +1908,8 @@ if self.is_nan(): raise ValueError("cannot round a NaN") else: - raise OverflowError("cannot round an infinity") + # bug 16469: error types should be consistent + raise ValueError("cannot round an infinity") return int(self._rescale(0, ROUND_CEILING)) def fma(self, other, third, context=None): diff --git a/Lib/fractions.py b/Lib/fractions.py --- a/Lib/fractions.py +++ b/Lib/fractions.py @@ -182,8 +182,11 @@ elif not isinstance(f, float): raise TypeError("%s.from_float() only takes floats, not %r (%s)" % (cls.__name__, f, type(f).__name__)) - if math.isnan(f) or math.isinf(f): - raise TypeError("Cannot convert %r to %s." % (f, cls.__name__)) + if math.isnan(f): + raise ValueError("Cannot convert %r to %s." % (f, cls.__name__)) + if math.isinf(f): + # bug 16469: error types should be consistent with float -> int + raise ValueError("Cannot convert %r to %s." % (f, cls.__name__)) return cls(*f.as_integer_ratio()) @classmethod @@ -196,9 +199,14 @@ raise TypeError( "%s.from_decimal() only takes Decimals, not %r (%s)" % (cls.__name__, dec, type(dec).__name__)) - if not dec.is_finite(): - # Catches infinities and nans. - raise TypeError("Cannot convert %s to %s." % (dec, cls.__name__)) + if dec.is_infinite(): + # Catches infinities + # bug 16469: error types should be consistent with decimal -> int + raise ValueError("Cannot convert %s to %s." % (dec, cls.__name__)) + if dec.is_nan(): + # Catches nans + # bug 16469: error types should be consistent with decimal -> int + raise ValueError("Cannot convert %s to %s." % (dec, cls.__name__)) sign, digits, exp = dec.as_tuple() digits = int(''.join(map(str, digits))) if sign: diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py --- a/Lib/test/test_decimal.py +++ b/Lib/test/test_decimal.py @@ -1882,8 +1882,8 @@ self.assertRaises(ValueError, math.floor, Decimal('-NaN')) self.assertRaises(ValueError, math.floor, Decimal('sNaN')) self.assertRaises(ValueError, math.floor, Decimal('NaN123')) - self.assertRaises(OverflowError, math.floor, Decimal('Inf')) - self.assertRaises(OverflowError, math.floor, Decimal('-Inf')) + self.assertRaises(ValueError, math.floor, Decimal('Inf')) + self.assertRaises(ValueError, math.floor, Decimal('-Inf')) #ceiling test_pairs = [ @@ -1902,8 +1902,8 @@ self.assertRaises(ValueError, math.ceil, Decimal('-NaN')) self.assertRaises(ValueError, math.ceil, Decimal('sNaN')) self.assertRaises(ValueError, math.ceil, Decimal('NaN123')) - self.assertRaises(OverflowError, math.ceil, Decimal('Inf')) - self.assertRaises(OverflowError, math.ceil, Decimal('-Inf')) + self.assertRaises(ValueError, math.ceil, Decimal('Inf')) + self.assertRaises(ValueError, math.ceil, Decimal('-Inf')) #round, single argument test_pairs = [ @@ -1929,8 +1929,8 @@ self.assertRaises(ValueError, round, Decimal('-NaN')) self.assertRaises(ValueError, round, Decimal('sNaN')) self.assertRaises(ValueError, round, Decimal('NaN123')) - self.assertRaises(OverflowError, round, Decimal('Inf')) - self.assertRaises(OverflowError, round, Decimal('-Inf')) + self.assertRaises(ValueError, round, Decimal('Inf')) + self.assertRaises(ValueError, round, Decimal('-Inf')) #round, two arguments; this is essentially equivalent #to quantize, which is already extensively tested @@ -2201,8 +2201,9 @@ self.assertRaises(ValueError, int, Decimal('-nan')) self.assertRaises(ValueError, int, Decimal('snan')) - self.assertRaises(OverflowError, int, Decimal('inf')) - self.assertRaises(OverflowError, int, Decimal('-inf')) + # bug 16469: converting to int nans and infinites should raise ValueError + self.assertRaises(ValueError, int, Decimal('inf')) + self.assertRaises(ValueError, int, Decimal('-inf')) def test_trunc(self): Decimal = self.decimal.Decimal diff --git a/Lib/test/test_float.py b/Lib/test/test_float.py --- a/Lib/test/test_float.py +++ b/Lib/test/test_float.py @@ -664,8 +664,9 @@ class RoundTestCase(unittest.TestCase): def test_inf_nan(self): - self.assertRaises(OverflowError, round, INF) - self.assertRaises(OverflowError, round, -INF) + # bug 16469 + self.assertRaises(ValueError, round, INF) + self.assertRaises(ValueError, round, -INF) self.assertRaises(ValueError, round, NAN) self.assertRaises(TypeError, round, INF, 0.0) self.assertRaises(TypeError, round, -INF, 1.0) diff --git a/Lib/test/test_fractions.py b/Lib/test/test_fractions.py --- a/Lib/test/test_fractions.py +++ b/Lib/test/test_fractions.py @@ -146,9 +146,10 @@ self.assertEqual((0, 1), _components(F(-0.0))) self.assertEqual((3602879701896397, 36028797018963968), _components(F(0.1))) - self.assertRaises(TypeError, F, float('nan')) - self.assertRaises(TypeError, F, float('inf')) - self.assertRaises(TypeError, F, float('-inf')) + # bug 16469: error types should be consistent with float -> int + self.assertRaises(ValueError, F, float('nan')) + self.assertRaises(ValueError, F, float('inf')) + self.assertRaises(ValueError, F, float('-inf')) def testInitFromDecimal(self): self.assertEqual((11, 10), @@ -157,10 +158,11 @@ _components(F(Decimal('3.5e-2')))) self.assertEqual((0, 1), _components(F(Decimal('.000e20')))) - self.assertRaises(TypeError, F, Decimal('nan')) - self.assertRaises(TypeError, F, Decimal('snan')) - self.assertRaises(TypeError, F, Decimal('inf')) - self.assertRaises(TypeError, F, Decimal('-inf')) + # bug 16469: error types should be consistent with decimal -> int + self.assertRaises(ValueError, F, Decimal('nan')) + self.assertRaises(ValueError, F, Decimal('snan')) + self.assertRaises(ValueError, F, Decimal('inf')) + self.assertRaises(ValueError, F, Decimal('-inf')) def testFromString(self): self.assertEqual((5, 1), _components(F("5"))) @@ -248,14 +250,15 @@ inf = 1e1000 nan = inf - inf + # bug 16469: error types should be consistent with float -> int self.assertRaisesMessage( - TypeError, "Cannot convert inf to Fraction.", + ValueError, "Cannot convert inf to Fraction.", F.from_float, inf) self.assertRaisesMessage( - TypeError, "Cannot convert -inf to Fraction.", + ValueError, "Cannot convert -inf to Fraction.", F.from_float, -inf) self.assertRaisesMessage( - TypeError, "Cannot convert nan to Fraction.", + ValueError, "Cannot convert nan to Fraction.", F.from_float, nan) def testFromDecimal(self): @@ -268,17 +271,18 @@ self.assertEqual(1 - F(1, 10**30), F.from_decimal(Decimal("0." + "9" * 30))) + # bug 16469: error types should be consistent with decimal -> int self.assertRaisesMessage( - TypeError, "Cannot convert Infinity to Fraction.", + ValueError, "Cannot convert Infinity to Fraction.", F.from_decimal, Decimal("inf")) self.assertRaisesMessage( - TypeError, "Cannot convert -Infinity to Fraction.", + ValueError, "Cannot convert -Infinity to Fraction.", F.from_decimal, Decimal("-inf")) self.assertRaisesMessage( - TypeError, "Cannot convert NaN to Fraction.", + ValueError, "Cannot convert NaN to Fraction.", F.from_decimal, Decimal("nan")) self.assertRaisesMessage( - TypeError, "Cannot convert sNaN to Fraction.", + ValueError, "Cannot convert sNaN to Fraction.", F.from_decimal, Decimal("snan")) def testLimitDenominator(self): diff --git a/Lib/test/test_int.py b/Lib/test/test_int.py --- a/Lib/test/test_int.py +++ b/Lib/test/test_int.py @@ -76,11 +76,18 @@ self.assertRaises(ValueError, int, '123\0') self.assertRaises(ValueError, int, '53', 40) + # SF bug 1545497: embedded NULs were not detected with # explicit base self.assertRaises(ValueError, int, '123\0', 10) self.assertRaises(ValueError, int, '123\x00 245', 20) + # bug 16469: converting to int nans and infinites should raise ValueError + self.assertRaises(ValueError, int, float("nan")) + self.assertRaises(ValueError, int, float("inf")) + self.assertRaises(ValueError, int, float("-inf")) + + x = int('1' * 600) self.assertIsInstance(x, int) diff --git a/Lib/test/test_long.py b/Lib/test/test_long.py --- a/Lib/test/test_long.py +++ b/Lib/test/test_long.py @@ -710,8 +710,9 @@ format(float(value), format_spec)) def test_nan_inf(self): - self.assertRaises(OverflowError, int, float('inf')) - self.assertRaises(OverflowError, int, float('-inf')) + # bug 16469: converting to int nans and infinites should raise ValueError + self.assertRaises(ValueError, int, float('inf')) + self.assertRaises(ValueError, int, float('-inf')) self.assertRaises(ValueError, int, float('nan')) def test_true_division(self): diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -3250,7 +3250,7 @@ "cannot convert NaN to integer"); } else { - PyErr_SetString(PyExc_OverflowError, + PyErr_SetString(PyExc_ValueError, "cannot convert Infinity to integer"); } return NULL; diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -890,7 +890,7 @@ _Py_IDENTIFIER(__ceil__); PyObject *method, *result; - method = _PyObject_LookupSpecial(number, &PyId___ceil__); + method = _PyObject_LookupSpecial(number, &PyId___floor__); if (method == NULL) { if (PyErr_Occurred()) return NULL; diff --git a/Objects/longobject.c b/Objects/longobject.c --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -276,7 +276,7 @@ int i, ndig, expo, neg; neg = 0; if (Py_IS_INFINITY(dval)) { - PyErr_SetString(PyExc_OverflowError, + PyErr_SetString(PyExc_ValueError, "cannot convert float infinity to integer"); return NULL; }