Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 73726aa

Browse files
committed
Issue #16469: Fraction(float('nan')) and Fraction(float('inf')) now raise ValueError and OverflowError (resp.), not TypeError.
1 parent 8f7c4b8 commit 73726aa

3 files changed

Lines changed: 31 additions & 19 deletions

File tree

Lib/fractions.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,10 @@ def from_float(cls, f):
182182
elif not isinstance(f, float):
183183
raise TypeError("%s.from_float() only takes floats, not %r (%s)" %
184184
(cls.__name__, f, type(f).__name__))
185-
if math.isnan(f) or math.isinf(f):
186-
raise TypeError("Cannot convert %r to %s." % (f, cls.__name__))
185+
if math.isnan(f):
186+
raise ValueError("Cannot convert %r to %s." % (f, cls.__name__))
187+
if math.isinf(f):
188+
raise OverflowError("Cannot convert %r to %s." % (f, cls.__name__))
187189
return cls(*f.as_integer_ratio())
188190

189191
@classmethod
@@ -196,9 +198,11 @@ def from_decimal(cls, dec):
196198
raise TypeError(
197199
"%s.from_decimal() only takes Decimals, not %r (%s)" %
198200
(cls.__name__, dec, type(dec).__name__))
199-
if not dec.is_finite():
200-
# Catches infinities and nans.
201-
raise TypeError("Cannot convert %s to %s." % (dec, cls.__name__))
201+
if dec.is_infinite():
202+
raise OverflowError(
203+
"Cannot convert %s to %s." % (dec, cls.__name__))
204+
if dec.is_nan():
205+
raise ValueError("Cannot convert %s to %s." % (dec, cls.__name__))
202206
sign, digits, exp = dec.as_tuple()
203207
digits = int(''.join(map(str, digits)))
204208
if sign:

Lib/test/test_fractions.py

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -146,9 +146,10 @@ def testInitFromFloat(self):
146146
self.assertEqual((0, 1), _components(F(-0.0)))
147147
self.assertEqual((3602879701896397, 36028797018963968),
148148
_components(F(0.1)))
149-
self.assertRaises(TypeError, F, float('nan'))
150-
self.assertRaises(TypeError, F, float('inf'))
151-
self.assertRaises(TypeError, F, float('-inf'))
149+
# bug 16469: error types should be consistent with float -> int
150+
self.assertRaises(ValueError, F, float('nan'))
151+
self.assertRaises(OverflowError, F, float('inf'))
152+
self.assertRaises(OverflowError, F, float('-inf'))
152153

153154
def testInitFromDecimal(self):
154155
self.assertEqual((11, 10),
@@ -157,10 +158,11 @@ def testInitFromDecimal(self):
157158
_components(F(Decimal('3.5e-2'))))
158159
self.assertEqual((0, 1),
159160
_components(F(Decimal('.000e20'))))
160-
self.assertRaises(TypeError, F, Decimal('nan'))
161-
self.assertRaises(TypeError, F, Decimal('snan'))
162-
self.assertRaises(TypeError, F, Decimal('inf'))
163-
self.assertRaises(TypeError, F, Decimal('-inf'))
161+
# bug 16469: error types should be consistent with decimal -> int
162+
self.assertRaises(ValueError, F, Decimal('nan'))
163+
self.assertRaises(ValueError, F, Decimal('snan'))
164+
self.assertRaises(OverflowError, F, Decimal('inf'))
165+
self.assertRaises(OverflowError, F, Decimal('-inf'))
164166

165167
def testFromString(self):
166168
self.assertEqual((5, 1), _components(F("5")))
@@ -248,14 +250,15 @@ def testFromFloat(self):
248250

249251
inf = 1e1000
250252
nan = inf - inf
253+
# bug 16469: error types should be consistent with float -> int
251254
self.assertRaisesMessage(
252-
TypeError, "Cannot convert inf to Fraction.",
255+
OverflowError, "Cannot convert inf to Fraction.",
253256
F.from_float, inf)
254257
self.assertRaisesMessage(
255-
TypeError, "Cannot convert -inf to Fraction.",
258+
OverflowError, "Cannot convert -inf to Fraction.",
256259
F.from_float, -inf)
257260
self.assertRaisesMessage(
258-
TypeError, "Cannot convert nan to Fraction.",
261+
ValueError, "Cannot convert nan to Fraction.",
259262
F.from_float, nan)
260263

261264
def testFromDecimal(self):
@@ -268,17 +271,18 @@ def testFromDecimal(self):
268271
self.assertEqual(1 - F(1, 10**30),
269272
F.from_decimal(Decimal("0." + "9" * 30)))
270273

274+
# bug 16469: error types should be consistent with decimal -> int
271275
self.assertRaisesMessage(
272-
TypeError, "Cannot convert Infinity to Fraction.",
276+
OverflowError, "Cannot convert Infinity to Fraction.",
273277
F.from_decimal, Decimal("inf"))
274278
self.assertRaisesMessage(
275-
TypeError, "Cannot convert -Infinity to Fraction.",
279+
OverflowError, "Cannot convert -Infinity to Fraction.",
276280
F.from_decimal, Decimal("-inf"))
277281
self.assertRaisesMessage(
278-
TypeError, "Cannot convert NaN to Fraction.",
282+
ValueError, "Cannot convert NaN to Fraction.",
279283
F.from_decimal, Decimal("nan"))
280284
self.assertRaisesMessage(
281-
TypeError, "Cannot convert sNaN to Fraction.",
285+
ValueError, "Cannot convert sNaN to Fraction.",
282286
F.from_decimal, Decimal("snan"))
283287

284288
def testLimitDenominator(self):

Misc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,10 @@ Core and Builtins
127127
Library
128128
-------
129129

130+
- Issue #16469: Fix exceptions from float -> Fraction and Decimal -> Fraction
131+
conversions for special values to be consistent with those for float -> int
132+
and Decimal -> int. Patch by Alexey Kachayev.
133+
130134
- Issue #16481: multiprocessing no longer leaks process handles on Windows.
131135

132136
- Issue #12428: Add a pure Python implementation of functools.partial().

0 commit comments

Comments
 (0)