From: Stefan Krah Date: Thu, 5 Apr 2012 13:21:58 +0000 (+0200) Subject: Raise InvalidOperation if exponents of zeros are clamped during exact X-Git-Tag: v3.3.0a3~305 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0774e9b9f57197380c796d36353344cb95ed07bf;p=python Raise InvalidOperation if exponents of zeros are clamped during exact conversion in the Decimal constructor. Exact here refers to the representation and not to the value (clamping does not change the value). --- diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py index 694b959e21..90f4015549 100644 --- a/Lib/test/test_decimal.py +++ b/Lib/test/test_decimal.py @@ -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, diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index 32e336b4ff..ad3c3df318 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -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); } diff --git a/Modules/_decimal/tests/deccheck.py b/Modules/_decimal/tests/deccheck.py index aefbed67af..c8da4d02b7 100644 --- a/Modules/_decimal/tests/deccheck.py +++ b/Modules/_decimal/tests/deccheck.py @@ -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]: