[pypy-commit] pypy decimal-libmpdec: Add Decimal.from_float()

amauryfa noreply at buildbot.pypy.org
Sun Aug 24 22:27:25 CEST 2014


Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: decimal-libmpdec
Changeset: r73042:cf37d2846705
Date: 2014-05-25 21:50 +0200
http://bitbucket.org/pypy/pypy/changeset/cf37d2846705/

Log:	Add Decimal.from_float()

diff --git a/pypy/module/_decimal/interp_decimal.py b/pypy/module/_decimal/interp_decimal.py
--- a/pypy/module/_decimal/interp_decimal.py
+++ b/pypy/module/_decimal/interp_decimal.py
@@ -571,6 +571,10 @@
         return interp_context.getcontext(space)
     return space.interp_w(interp_context.W_Context, w_context)
 
+def decimal_from_float_w(space, w_cls, w_float):
+    context = interp_context.getcontext(space)
+    return decimal_from_float(space, w_cls, w_float, context, exact=True)
+
 # Constructors
 def decimal_from_ssize(space, w_subtype, value, context, exact=True):
     w_result = W_Decimal.allocate(space, w_subtype)
@@ -722,6 +726,10 @@
             return w_value.apply(space, context)
 
 def decimal_from_float(space, w_subtype, w_value, context, exact=True):
+    if space.isinstance_w(w_value, space.w_int):
+        value = space.bigint_w(w_value)
+        return decimal_from_bigint(space, w_subtype, value, context,
+                                   exact=exact)
     value = space.float_w(w_value)
     sign = 0 if rfloat.copysign(1.0, value) == 1.0 else 1
 
@@ -849,4 +857,5 @@
     is_infinite = interp2app(W_Decimal.is_infinite_w),
     #
     as_tuple = interp2app(W_Decimal.as_tuple_w),
+    from_float = interp2app(decimal_from_float_w, as_classmethod=True),
     )
diff --git a/pypy/module/_decimal/test/test_decimal.py b/pypy/module/_decimal/test/test_decimal.py
--- a/pypy/module/_decimal/test/test_decimal.py
+++ b/pypy/module/_decimal/test/test_decimal.py
@@ -14,6 +14,15 @@
             return space.wrap(f)
         cls.w_random_float = space.wrap(gateway.interp2app(random_float))
 
+        # a few functions from unittest library
+        cls.w_assertTrue = space.appexec([], """():
+            def assertTrue(x): assert x
+            return assertTrue""")
+        cls.w_assertEqual = space.appexec([], """():
+            def assertEqual(x, y): assert x == y
+            return assertEqual""")
+        cls.w_assertRaises = space.appexec([], """(): return raises""")
+
     def test_explicit_empty(self):
         Decimal = self.Decimal
         assert Decimal() == Decimal("0")
@@ -206,6 +215,34 @@
             x = self.random_float()
             assert x == float(Decimal(x)) # roundtrip
 
+    def test_from_float(self):
+        Decimal = self.decimal.Decimal
+
+        class MyDecimal(Decimal):
+            pass
+
+        self.assertTrue(issubclass(MyDecimal, Decimal))
+
+        r = MyDecimal.from_float(0.1)
+        self.assertEqual(type(r), MyDecimal)
+        self.assertEqual(str(r),
+                '0.1000000000000000055511151231257827021181583404541015625')
+        bigint = 12345678901234567890123456789
+        self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
+        self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
+        self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
+        self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
+        self.assertEqual(str(MyDecimal.from_float(float('nan'))),
+                         str(Decimal('NaN')))
+        self.assertEqual(str(MyDecimal.from_float(float('inf'))),
+                         str(Decimal('Infinity')))
+        self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
+                         str(Decimal('-Infinity')))
+        self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
+        for i in range(200):
+            x = self.random_float()
+            self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
+
     def test_explicit_context_create_decimal(self):
         Decimal = self.decimal.Decimal
         InvalidOperation = self.decimal.InvalidOperation


More information about the pypy-commit mailing list