This commit is contained in:
Brett Cannon 2012-11-15 16:13:00 -05:00
commit 0676caf660
3 changed files with 31 additions and 19 deletions

View File

@ -182,8 +182,10 @@ class Fraction(numbers.Rational):
elif not isinstance(f, float): elif not isinstance(f, float):
raise TypeError("%s.from_float() only takes floats, not %r (%s)" % raise TypeError("%s.from_float() only takes floats, not %r (%s)" %
(cls.__name__, f, type(f).__name__)) (cls.__name__, f, type(f).__name__))
if math.isnan(f) or math.isinf(f): if math.isnan(f):
raise TypeError("Cannot convert %r to %s." % (f, cls.__name__)) 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()) return cls(*f.as_integer_ratio())
@classmethod @classmethod
@ -196,9 +198,11 @@ class Fraction(numbers.Rational):
raise TypeError( raise TypeError(
"%s.from_decimal() only takes Decimals, not %r (%s)" % "%s.from_decimal() only takes Decimals, not %r (%s)" %
(cls.__name__, dec, type(dec).__name__)) (cls.__name__, dec, type(dec).__name__))
if not dec.is_finite(): if dec.is_infinite():
# Catches infinities and nans. raise OverflowError(
raise TypeError("Cannot convert %s to %s." % (dec, cls.__name__)) "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() sign, digits, exp = dec.as_tuple()
digits = int(''.join(map(str, digits))) digits = int(''.join(map(str, digits)))
if sign: if sign:

View File

@ -146,9 +146,10 @@ class FractionTest(unittest.TestCase):
self.assertEqual((0, 1), _components(F(-0.0))) self.assertEqual((0, 1), _components(F(-0.0)))
self.assertEqual((3602879701896397, 36028797018963968), self.assertEqual((3602879701896397, 36028797018963968),
_components(F(0.1))) _components(F(0.1)))
self.assertRaises(TypeError, F, float('nan')) # bug 16469: error types should be consistent with float -> int
self.assertRaises(TypeError, F, float('inf')) self.assertRaises(ValueError, F, float('nan'))
self.assertRaises(TypeError, F, float('-inf')) self.assertRaises(OverflowError, F, float('inf'))
self.assertRaises(OverflowError, F, float('-inf'))
def testInitFromDecimal(self): def testInitFromDecimal(self):
self.assertEqual((11, 10), self.assertEqual((11, 10),
@ -157,10 +158,11 @@ class FractionTest(unittest.TestCase):
_components(F(Decimal('3.5e-2')))) _components(F(Decimal('3.5e-2'))))
self.assertEqual((0, 1), self.assertEqual((0, 1),
_components(F(Decimal('.000e20')))) _components(F(Decimal('.000e20'))))
self.assertRaises(TypeError, F, Decimal('nan')) # bug 16469: error types should be consistent with decimal -> int
self.assertRaises(TypeError, F, Decimal('snan')) self.assertRaises(ValueError, F, Decimal('nan'))
self.assertRaises(TypeError, F, Decimal('inf')) self.assertRaises(ValueError, F, Decimal('snan'))
self.assertRaises(TypeError, F, Decimal('-inf')) self.assertRaises(OverflowError, F, Decimal('inf'))
self.assertRaises(OverflowError, F, Decimal('-inf'))
def testFromString(self): def testFromString(self):
self.assertEqual((5, 1), _components(F("5"))) self.assertEqual((5, 1), _components(F("5")))
@ -248,14 +250,15 @@ class FractionTest(unittest.TestCase):
inf = 1e1000 inf = 1e1000
nan = inf - inf nan = inf - inf
# bug 16469: error types should be consistent with float -> int
self.assertRaisesMessage( self.assertRaisesMessage(
TypeError, "Cannot convert inf to Fraction.", OverflowError, "Cannot convert inf to Fraction.",
F.from_float, inf) F.from_float, inf)
self.assertRaisesMessage( self.assertRaisesMessage(
TypeError, "Cannot convert -inf to Fraction.", OverflowError, "Cannot convert -inf to Fraction.",
F.from_float, -inf) F.from_float, -inf)
self.assertRaisesMessage( self.assertRaisesMessage(
TypeError, "Cannot convert nan to Fraction.", ValueError, "Cannot convert nan to Fraction.",
F.from_float, nan) F.from_float, nan)
def testFromDecimal(self): def testFromDecimal(self):
@ -268,17 +271,18 @@ class FractionTest(unittest.TestCase):
self.assertEqual(1 - F(1, 10**30), self.assertEqual(1 - F(1, 10**30),
F.from_decimal(Decimal("0." + "9" * 30))) F.from_decimal(Decimal("0." + "9" * 30)))
# bug 16469: error types should be consistent with decimal -> int
self.assertRaisesMessage( self.assertRaisesMessage(
TypeError, "Cannot convert Infinity to Fraction.", OverflowError, "Cannot convert Infinity to Fraction.",
F.from_decimal, Decimal("inf")) F.from_decimal, Decimal("inf"))
self.assertRaisesMessage( self.assertRaisesMessage(
TypeError, "Cannot convert -Infinity to Fraction.", OverflowError, "Cannot convert -Infinity to Fraction.",
F.from_decimal, Decimal("-inf")) F.from_decimal, Decimal("-inf"))
self.assertRaisesMessage( self.assertRaisesMessage(
TypeError, "Cannot convert NaN to Fraction.", ValueError, "Cannot convert NaN to Fraction.",
F.from_decimal, Decimal("nan")) F.from_decimal, Decimal("nan"))
self.assertRaisesMessage( self.assertRaisesMessage(
TypeError, "Cannot convert sNaN to Fraction.", ValueError, "Cannot convert sNaN to Fraction.",
F.from_decimal, Decimal("snan")) F.from_decimal, Decimal("snan"))
def testLimitDenominator(self): def testLimitDenominator(self):

View File

@ -127,6 +127,10 @@ Core and Builtins
Library 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 #16481: multiprocessing no longer leaks process handles on Windows.
- Issue #12428: Add a pure Python implementation of functools.partial(). - Issue #12428: Add a pure Python implementation of functools.partial().