summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Krah <skrah@bytereef.org>2012-04-05 13:21:58 (GMT)
committerStefan Krah <skrah@bytereef.org>2012-04-05 13:21:58 (GMT)
commit0774e9b9f57197380c796d36353344cb95ed07bf (patch)
tree89d37955fb4526cf0f2a561b369788971746e93f
parente7eee01f3697835d168f82357a6a97d7ca40d99a (diff)
downloadcpython-0774e9b9f57197380c796d36353344cb95ed07bf.zip
cpython-0774e9b9f57197380c796d36353344cb95ed07bf.tar.gz
cpython-0774e9b9f57197380c796d36353344cb95ed07bf.tar.bz2
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).
-rw-r--r--Lib/test/test_decimal.py24
-rw-r--r--Modules/_decimal/_decimal.c4
-rw-r--r--Modules/_decimal/tests/deccheck.py1
3 files changed, 27 insertions, 2 deletions
diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py
index 694b959..90f4015 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 32e336b..ad3c3df 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 aefbed6..c8da4d0 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]: