Skip to content

Commit 0774e9b

Browse files
author
Stefan Krah
committed
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).
1 parent e7eee01 commit 0774e9b

3 files changed

Lines changed: 27 additions & 2 deletions

File tree

Lib/test/test_decimal.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4953,6 +4953,30 @@ def get_fmt(x, override=None, fmt='n'):
49534953
self.assertRaises(ValueError, get_fmt, 12345, invalid_dot, 'g')
49544954
self.assertRaises(ValueError, get_fmt, 12345, invalid_sep, 'g')
49554955

4956+
def test_exact_conversion(self):
4957+
Decimal = C.Decimal
4958+
localcontext = C.localcontext
4959+
InvalidOperation = C.InvalidOperation
4960+
4961+
with localcontext() as c:
4962+
4963+
c.traps[InvalidOperation] = True
4964+
4965+
# Clamped
4966+
x = "0e%d" % sys.maxsize
4967+
self.assertRaises(InvalidOperation, Decimal, x)
4968+
4969+
x = "0e%d" % (-sys.maxsize-1)
4970+
self.assertRaises(InvalidOperation, Decimal, x)
4971+
4972+
# Overflow
4973+
x = "1e%d" % sys.maxsize
4974+
self.assertRaises(InvalidOperation, Decimal, x)
4975+
4976+
# Underflow
4977+
x = "1e%d" % (-sys.maxsize-1)
4978+
self.assertRaises(InvalidOperation, Decimal, x)
4979+
49564980

49574981
all_tests = [
49584982
CExplicitConstructionTest, PyExplicitConstructionTest,

Modules/_decimal/_decimal.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1935,7 +1935,7 @@ PyDecType_FromCStringExact(PyTypeObject *type, const char *s,
19351935
mpd_maxcontext(&maxctx);
19361936

19371937
mpd_qset_string(MPD(dec), s, &maxctx, &status);
1938-
if (status & (MPD_Inexact|MPD_Rounded)) {
1938+
if (status & (MPD_Inexact|MPD_Rounded|MPD_Clamped)) {
19391939
/* we want exact results */
19401940
mpd_seterror(MPD(dec), MPD_Invalid_operation, &status);
19411941
}
@@ -2139,7 +2139,7 @@ PyDecType_FromLongExact(PyTypeObject *type, const PyObject *pylong,
21392139
return NULL;
21402140
}
21412141

2142-
if (status & (MPD_Inexact|MPD_Rounded)) {
2142+
if (status & (MPD_Inexact|MPD_Rounded|MPD_Clamped)) {
21432143
/* we want exact results */
21442144
mpd_seterror(MPD(dec), MPD_Invalid_operation, &status);
21452145
}

Modules/_decimal/tests/deccheck.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ def RestrictedDecimal(value):
302302
dec = maxcontext.create_decimal(value)
303303
if maxcontext.flags[P.Inexact] or \
304304
maxcontext.flags[P.Rounded] or \
305+
maxcontext.flags[P.Clamped] or \
305306
maxcontext.flags[P.InvalidOperation]:
306307
return context.p._raise_error(P.InvalidOperation)
307308
if maxcontext.flags[P.FloatOperation]:

0 commit comments

Comments
 (0)