Issue #8294:  Allow float and Decimal arguments in Fraction constructor.
diff --git a/Lib/fractions.py b/Lib/fractions.py
index 7a3e555..a0d86a4 100644
--- a/Lib/fractions.py
+++ b/Lib/fractions.py
@@ -4,6 +4,7 @@
 """Rational, infinite-precision, real numbers."""
 
 from __future__ import division
+from decimal import Decimal
 import math
 import numbers
 import operator
@@ -43,13 +44,21 @@
 class Fraction(Rational):
     """This class implements rational numbers.
 
-    Fraction(8, 6) will produce a rational number equivalent to
-    4/3. Both arguments must be Integral. The numerator defaults to 0
-    and the denominator defaults to 1 so that Fraction(3) == 3 and
-    Fraction() == 0.
+    In the two-argument form of the constructor, Fraction(8, 6) will
+    produce a rational number equivalent to 4/3. Both arguments must
+    be Rational. The numerator defaults to 0 and the denominator
+    defaults to 1 so that Fraction(3) == 3 and Fraction() == 0.
 
-    Fractions can also be constructed from strings of the form
-    '[-+]?[0-9]+((/|.)[0-9]+)?', optionally surrounded by spaces.
+    Fractions can also be constructed from:
+
+      - numeric strings similar to those accepted by the
+        float constructor (for example, '-2.3' or '1e10')
+
+      - strings of the form '123/456'
+
+      - float and Decimal instances
+
+      - other Rational instances (including integers)
 
     """
 
@@ -59,8 +68,32 @@
     def __new__(cls, numerator=0, denominator=None):
         """Constructs a Fraction.
 
-        Takes a string like '3/2' or '1.5', another Fraction, or a
-        numerator/denominator pair.
+        Takes a string like '3/2' or '1.5', another Rational instance, a
+        numerator/denominator pair, or a float.
+
+        Examples
+        --------
+
+        >>> Fraction(10, -8)
+        Fraction(-5, 4)
+        >>> Fraction(Fraction(1, 7), 5)
+        Fraction(1, 35)
+        >>> Fraction(Fraction(1, 7), Fraction(2, 3))
+        Fraction(3, 14)
+        >>> Fraction('314')
+        Fraction(314, 1)
+        >>> Fraction('-35/4')
+        Fraction(-35, 4)
+        >>> Fraction('3.1415') # conversion from numeric string
+        Fraction(6283, 2000)
+        >>> Fraction('-47e-2') # string may include a decimal exponent
+        Fraction(-47, 100)
+        >>> Fraction(1.47)  # direct construction from float (exact conversion)
+        Fraction(6620291452234629, 4503599627370496)
+        >>> Fraction(2.25)
+        Fraction(9, 4)
+        >>> Fraction(Decimal('1.47'))
+        Fraction(147, 100)
 
         """
         self = super(Fraction, cls).__new__(cls)
@@ -71,6 +104,19 @@
                 self._denominator = numerator.denominator
                 return self
 
+            elif isinstance(numerator, float):
+                # Exact conversion from float
+                value = Fraction.from_float(numerator)
+                self._numerator = value._numerator
+                self._denominator = value._denominator
+                return self
+
+            elif isinstance(numerator, Decimal):
+                value = Fraction.from_decimal(numerator)
+                self._numerator = value._numerator
+                self._denominator = value._denominator
+                return self
+
             elif isinstance(numerator, basestring):
                 # Handle construction from strings.
                 m = _RATIONAL_FORMAT.match(numerator)
diff --git a/Lib/test/test_fractions.py b/Lib/test/test_fractions.py
index a24fcd3..7f0c428 100644
--- a/Lib/test/test_fractions.py
+++ b/Lib/test/test_fractions.py
@@ -12,6 +12,11 @@
 F = fractions.Fraction
 gcd = fractions.gcd
 
+# decorator for skipping tests on non-IEEE 754 platforms
+requires_IEEE_754 = unittest.skipUnless(
+    float.__getformat__("double").startswith("IEEE"),
+    "test requires IEEE 754 doubles")
+
 class DummyFloat(object):
     """Dummy float class for testing comparisons with Fractions"""
 
@@ -137,13 +142,33 @@
 
         self.assertRaisesMessage(ZeroDivisionError, "Fraction(12, 0)",
                                  F, 12, 0)
-        self.assertRaises(TypeError, F, 1.5)
         self.assertRaises(TypeError, F, 1.5 + 3j)
 
         self.assertRaises(TypeError, F, "3/2", 3)
         self.assertRaises(TypeError, F, 3, 0j)
         self.assertRaises(TypeError, F, 3, 1j)
 
+    @requires_IEEE_754
+    def testInitFromFloat(self):
+        self.assertEquals((5, 2), _components(F(2.5)))
+        self.assertEquals((0, 1), _components(F(-0.0)))
+        self.assertEquals((3602879701896397, 36028797018963968),
+                          _components(F(0.1)))
+        self.assertRaises(TypeError, F, float('nan'))
+        self.assertRaises(TypeError, F, float('inf'))
+        self.assertRaises(TypeError, F, float('-inf'))
+
+    def testInitFromDecimal(self):
+        self.assertEquals((11, 10),
+                          _components(F(Decimal('1.1'))))
+        self.assertEquals((7, 200),
+                          _components(F(Decimal('3.5e-2'))))
+        self.assertEquals((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'))
 
     def testFromString(self):
         self.assertEquals((5, 1), _components(F("5")))