[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