]> granicus.if.org Git - python/commitdiff
Issue #16469: Fraction(float('nan')) and Fraction(float('inf')) now raise ValueError...
authorMark Dickinson <mdickinson@enthought.com>
Thu, 15 Nov 2012 20:58:40 +0000 (20:58 +0000)
committerMark Dickinson <mdickinson@enthought.com>
Thu, 15 Nov 2012 20:58:40 +0000 (20:58 +0000)
Lib/fractions.py
Lib/test/test_fractions.py
Misc/NEWS

index 8be52d2db88ca6afda2f18786e6a41b5de62f279..79e83ff2c00d3bc9148673fc9ed5b73be6c2a1b4 100644 (file)
@@ -182,8 +182,10 @@ class Fraction(numbers.Rational):
         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):
+            raise OverflowError("Cannot convert %r to %s." % (f, cls.__name__))
         return cls(*f.as_integer_ratio())
 
     @classmethod
@@ -196,9 +198,11 @@ class Fraction(numbers.Rational):
             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():
+            raise OverflowError(
+                "Cannot convert %s to %s." % (dec, cls.__name__))
+        if dec.is_nan():
+            raise ValueError("Cannot convert %s to %s." % (dec, cls.__name__))
         sign, digits, exp = dec.as_tuple()
         digits = int(''.join(map(str, digits)))
         if sign:
index 1fad9215c0db2ca1f0a2fc812bf0d73c6412c4c9..33365322b9484dc567575f5868f06c4df5276d02 100644 (file)
@@ -146,9 +146,10 @@ class FractionTest(unittest.TestCase):
         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(OverflowError, F, float('inf'))
+        self.assertRaises(OverflowError, F, float('-inf'))
 
     def testInitFromDecimal(self):
         self.assertEqual((11, 10),
@@ -157,10 +158,11 @@ class FractionTest(unittest.TestCase):
                          _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(OverflowError, F, Decimal('inf'))
+        self.assertRaises(OverflowError, F, Decimal('-inf'))
 
     def testFromString(self):
         self.assertEqual((5, 1), _components(F("5")))
@@ -248,14 +250,15 @@ class FractionTest(unittest.TestCase):
 
         inf = 1e1000
         nan = inf - inf
+        # bug 16469: error types should be consistent with float -> int
         self.assertRaisesMessage(
-            TypeError, "Cannot convert inf to Fraction.",
+            OverflowError, "Cannot convert inf to Fraction.",
             F.from_float, inf)
         self.assertRaisesMessage(
-            TypeError, "Cannot convert -inf to Fraction.",
+            OverflowError, "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 @@ class FractionTest(unittest.TestCase):
         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.",
+            OverflowError, "Cannot convert Infinity to Fraction.",
             F.from_decimal, Decimal("inf"))
         self.assertRaisesMessage(
-            TypeError, "Cannot convert -Infinity to Fraction.",
+            OverflowError, "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):
index 7ffbd7b1351fcb38baa0f62a13f0bdd8c4665581..10e2d6310cfa0b3ef857ceecd4d76421ac69d24e 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -127,6 +127,10 @@ Core and Builtins
 Library
 -------
 
+- Issue #16469: Fix exceptions from float -> Fraction and Decimal -> Fraction
+  conversions for special values to be consistent with those for float -> int
+  and Decimal -> int.  Patch by Alexey Kachayev.
+
 - Issue #16481: multiprocessing no longer leaks process handles on Windows.
 
 - Issue #12428: Add a pure Python implementation of functools.partial().