]> granicus.if.org Git - python/commitdiff
Raise InvalidOperation if exponents of zeros are clamped during exact
authorStefan Krah <skrah@bytereef.org>
Thu, 5 Apr 2012 13:21:58 +0000 (15:21 +0200)
committerStefan Krah <skrah@bytereef.org>
Thu, 5 Apr 2012 13:21:58 +0000 (15:21 +0200)
conversion in the Decimal constructor. Exact here refers to the
representation and not to the value (clamping does not change the value).

Lib/test/test_decimal.py
Modules/_decimal/_decimal.c
Modules/_decimal/tests/deccheck.py

index 694b959e21870bebe330bc6200d6e4c27c08a29d..90f40155498168b7d5e1ef45f3d499af6b11354a 100644 (file)
@@ -4953,6 +4953,30 @@ class CWhitebox(unittest.TestCase):
         self.assertRaises(ValueError, get_fmt, 12345, invalid_dot, 'g')
         self.assertRaises(ValueError, get_fmt, 12345, invalid_sep, 'g')
 
+    def test_exact_conversion(self):
+        Decimal = C.Decimal
+        localcontext = C.localcontext
+        InvalidOperation = C.InvalidOperation
+
+        with localcontext() as c:
+
+            c.traps[InvalidOperation] = True
+
+            # Clamped
+            x = "0e%d" % sys.maxsize
+            self.assertRaises(InvalidOperation, Decimal, x)
+
+            x = "0e%d" % (-sys.maxsize-1)
+            self.assertRaises(InvalidOperation, Decimal, x)
+
+            # Overflow
+            x = "1e%d" % sys.maxsize
+            self.assertRaises(InvalidOperation, Decimal, x)
+
+            # Underflow
+            x = "1e%d" % (-sys.maxsize-1)
+            self.assertRaises(InvalidOperation, Decimal, x)
+
 
 all_tests = [
   CExplicitConstructionTest, PyExplicitConstructionTest,
index 32e336b4fff36d75635a22b4221d2890ac5691d3..ad3c3df3184c15f55a464e368f304e5d74222c24 100644 (file)
@@ -1935,7 +1935,7 @@ PyDecType_FromCStringExact(PyTypeObject *type, const char *s,
     mpd_maxcontext(&maxctx);
 
     mpd_qset_string(MPD(dec), s, &maxctx, &status);
-    if (status & (MPD_Inexact|MPD_Rounded)) {
+    if (status & (MPD_Inexact|MPD_Rounded|MPD_Clamped)) {
         /* we want exact results */
         mpd_seterror(MPD(dec), MPD_Invalid_operation, &status);
     }
@@ -2139,7 +2139,7 @@ PyDecType_FromLongExact(PyTypeObject *type, const PyObject *pylong,
         return NULL;
     }
 
-    if (status & (MPD_Inexact|MPD_Rounded)) {
+    if (status & (MPD_Inexact|MPD_Rounded|MPD_Clamped)) {
         /* we want exact results */
         mpd_seterror(MPD(dec), MPD_Invalid_operation, &status);
     }
index aefbed67af4671c88aea5e2e5ed18c8e67b61365..c8da4d02b737c1eaf7f3f2285599c8a70d86389e 100644 (file)
@@ -302,6 +302,7 @@ def RestrictedDecimal(value):
     dec = maxcontext.create_decimal(value)
     if maxcontext.flags[P.Inexact] or \
        maxcontext.flags[P.Rounded] or \
+       maxcontext.flags[P.Clamped] or \
        maxcontext.flags[P.InvalidOperation]:
         return context.p._raise_error(P.InvalidOperation)
     if maxcontext.flags[P.FloatOperation]: