[Python-checkins] cpython (3.3): Issue #16422: Use strings for rounding mode constants for better readability

stefan.krah python-checkins at python.org
Wed Jan 16 13:02:11 CET 2013


http://hg.python.org/cpython/rev/733bb4fd9888
changeset:   81538:733bb4fd9888
branch:      3.3
parent:      81536:3fa3e7975724
user:        Stefan Krah <skrah at bytereef.org>
date:        Wed Jan 16 12:58:59 2013 +0100
summary:
  Issue #16422: Use strings for rounding mode constants for better readability
and pickling compatibility.

files:
  Lib/test/test_decimal.py           |  119 +++++++---------
  Misc/NEWS                          |    3 +
  Modules/_decimal/_decimal.c        |  122 +++++++---------
  Modules/_decimal/tests/deccheck.py |   36 +---
  4 files changed, 127 insertions(+), 153 deletions(-)


diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py
--- a/Lib/test/test_decimal.py
+++ b/Lib/test/test_decimal.py
@@ -78,14 +78,20 @@
     d = getattr(context, attr)
     cls.assertTrue(all(d[s] if s in expected else not d[s] for s in d))
 
-RoundingModes = {
-  C: (C.ROUND_UP, C.ROUND_DOWN, C.ROUND_CEILING, C.ROUND_FLOOR,
-      C.ROUND_HALF_UP, C.ROUND_HALF_DOWN, C.ROUND_HALF_EVEN,
-      C.ROUND_05UP) if C else None,
-  P: (P.ROUND_UP, P.ROUND_DOWN, P.ROUND_CEILING, P.ROUND_FLOOR,
-      P.ROUND_HALF_UP, P.ROUND_HALF_DOWN, P.ROUND_HALF_EVEN,
-      P.ROUND_05UP)
-}
+ROUND_UP = P.ROUND_UP
+ROUND_DOWN = P.ROUND_DOWN
+ROUND_CEILING = P.ROUND_CEILING
+ROUND_FLOOR = P.ROUND_FLOOR
+ROUND_HALF_UP = P.ROUND_HALF_UP
+ROUND_HALF_DOWN = P.ROUND_HALF_DOWN
+ROUND_HALF_EVEN = P.ROUND_HALF_EVEN
+ROUND_05UP = P.ROUND_05UP
+
+RoundingModes = [
+  ROUND_UP, ROUND_DOWN, ROUND_CEILING, ROUND_FLOOR,
+  ROUND_HALF_UP, ROUND_HALF_DOWN, ROUND_HALF_EVEN,
+  ROUND_05UP
+]
 
 # Tests are built around these assumed context defaults.
 # test_main() restores the original context.
@@ -96,7 +102,7 @@
 def init(m):
     if not m: return
     DefaultTestContext = m.Context(
-       prec=9, rounding=m.ROUND_HALF_EVEN, traps=dict.fromkeys(Signals[m], 0)
+       prec=9, rounding=ROUND_HALF_EVEN, traps=dict.fromkeys(Signals[m], 0)
     )
     m.setcontext(DefaultTestContext)
 
@@ -229,14 +235,14 @@
                             'xor':'logical_xor'}
 
         # Map test-case names to roundings.
-        self.RoundingDict = {'ceiling' : self.decimal.ROUND_CEILING,
-                             'down' : self.decimal.ROUND_DOWN,
-                             'floor' : self.decimal.ROUND_FLOOR,
-                             'half_down' : self.decimal.ROUND_HALF_DOWN,
-                             'half_even' : self.decimal.ROUND_HALF_EVEN,
-                             'half_up' : self.decimal.ROUND_HALF_UP,
-                             'up' : self.decimal.ROUND_UP,
-                             '05up' : self.decimal.ROUND_05UP}
+        self.RoundingDict = {'ceiling' : ROUND_CEILING,
+                             'down' : ROUND_DOWN,
+                             'floor' : ROUND_FLOOR,
+                             'half_down' : ROUND_HALF_DOWN,
+                             'half_even' : ROUND_HALF_EVEN,
+                             'half_up' : ROUND_HALF_UP,
+                             'up' : ROUND_UP,
+                             '05up' : ROUND_05UP}
 
         # Map the test cases' error names to the actual errors.
         self.ErrorNames = {'clamped' : self.decimal.Clamped,
@@ -2101,9 +2107,6 @@
         Inexact = self.decimal.Inexact
         Rounded = self.decimal.Rounded
         Clamped = self.decimal.Clamped
-        ROUND_HALF_EVEN = self.decimal.ROUND_HALF_EVEN
-        ROUND_DOWN = self.decimal.ROUND_DOWN
-        ROUND_UP = self.decimal.ROUND_UP
 
         with localcontext(Context()) as c:
             c.prec = 7
@@ -2430,7 +2433,6 @@
 
     def test_int(self):
         Decimal = self.decimal.Decimal
-        ROUND_DOWN = self.decimal.ROUND_DOWN
 
         for x in range(-250, 250):
             s = '%0.2f' % (x / 100.0)
@@ -2448,7 +2450,6 @@
 
     def test_trunc(self):
         Decimal = self.decimal.Decimal
-        ROUND_DOWN = self.decimal.ROUND_DOWN
 
         for x in range(-250, 250):
             s = '%0.2f' % (x / 100.0)
@@ -2491,8 +2492,6 @@
     def test_create_decimal_from_float(self):
         Decimal = self.decimal.Decimal
         Context = self.decimal.Context
-        ROUND_DOWN = self.decimal.ROUND_DOWN
-        ROUND_UP = self.decimal.ROUND_UP
         Inexact = self.decimal.Inexact
 
         context = Context(prec=5, rounding=ROUND_DOWN)
@@ -2522,7 +2521,6 @@
         Decimal = self.decimal.Decimal
         Context = self.decimal.Context
         InvalidOperation = self.decimal.InvalidOperation
-        ROUND_DOWN = self.decimal.ROUND_DOWN
 
         c = Context(Emax=99999, Emin=-99999)
         self.assertEqual(
@@ -2723,7 +2721,6 @@
         InvalidOperation = self.decimal.InvalidOperation
         DivisionByZero = self.decimal.DivisionByZero
         Overflow = self.decimal.Overflow
-        ROUND_HALF_EVEN = self.decimal.ROUND_HALF_EVEN
 
         c1 = Context()
         c2 = Context(prec=None, rounding=None, Emax=None, Emin=None,
@@ -2739,6 +2736,21 @@
             assert_signals(self, c, 'traps', [InvalidOperation, DivisionByZero,
                                               Overflow])
 
+    @cpython_only
+    def test_from_legacy_strings(self):
+        import _testcapi
+        c = self.decimal.Context()
+
+        for rnd in RoundingModes:
+            c.rounding = _testcapi.unicode_legacy_string(rnd)
+            self.assertEqual(c.rounding, rnd)
+
+        s = _testcapi.unicode_legacy_string('')
+        self.assertRaises(TypeError, setattr, c, 'rounding', s)
+
+        s = _testcapi.unicode_legacy_string('ROUND_\x00UP')
+        self.assertRaises(TypeError, setattr, c, 'rounding', s)
+
     def test_pickle(self):
 
         Context = self.decimal.Context
@@ -2762,7 +2774,7 @@
         # Test interchangeability
         combinations = [(C, P), (P, C)] if C else [(P, P)]
         for dumper, loader in combinations:
-            for ri, _ in enumerate(RoundingModes[dumper]):
+            for ri, _ in enumerate(RoundingModes):
                 for fi, _ in enumerate(OrderedSignals[dumper]):
                     for ti, _ in enumerate(OrderedSignals[dumper]):
 
@@ -2776,7 +2788,7 @@
                         sys.modules['decimal'] = dumper
                         c = dumper.Context(
                               prec=prec, Emin=emin, Emax=emax,
-                              rounding=RoundingModes[dumper][ri],
+                              rounding=RoundingModes[ri],
                               capitals=caps, clamp=clamp,
                               flags=OrderedSignals[dumper][:fi],
                               traps=OrderedSignals[dumper][:ti]
@@ -2791,7 +2803,7 @@
                         self.assertEqual(d.prec, prec)
                         self.assertEqual(d.Emin, emin)
                         self.assertEqual(d.Emax, emax)
-                        self.assertEqual(d.rounding, RoundingModes[loader][ri])
+                        self.assertEqual(d.rounding, RoundingModes[ri])
                         self.assertEqual(d.capitals, caps)
                         self.assertEqual(d.clamp, clamp)
                         assert_signals(self, d, 'flags', OrderedSignals[loader][:fi])
@@ -3593,7 +3605,6 @@
         Underflow = self.decimal.Underflow
         Clamped = self.decimal.Clamped
         Subnormal = self.decimal.Subnormal
-        ROUND_HALF_EVEN = self.decimal.ROUND_HALF_EVEN
 
         def raise_error(context, flag):
             if self.decimal == C:
@@ -3960,17 +3971,6 @@
         self.assertRaises(ValueError, setattr, c, 'Emin', 1)
         self.assertRaises(TypeError, setattr, c, 'Emin', (1,2,3))
 
-        # rounding: always raise TypeError in order to get consistent
-        # exceptions across implementations. In decimal, rounding
-        # modes are strings, in _decimal they are integers. The idea
-        # is to view rounding as an abstract type and not mind the
-        # implementation details.
-        # Hence, a user should view the rounding modes as if they
-        # had been defined in a language that supports abstract
-        # data types, e.g. ocaml:
-        #
-        #   type rounding = ROUND_DOWN | ROUND_HALF_UP | ... ;;
-        #
         self.assertRaises(TypeError, setattr, c, 'rounding', -1)
         self.assertRaises(TypeError, setattr, c, 'rounding', 9)
         self.assertRaises(TypeError, setattr, c, 'rounding', 1.0)
@@ -4023,8 +4023,6 @@
         decimal = self.decimal
         Decimal = decimal.Decimal
         Context = decimal.Context
-        ROUND_HALF_EVEN = decimal.ROUND_HALF_EVEN
-        ROUND_DOWN = decimal.ROUND_DOWN
         Clamped = decimal.Clamped
         DivisionByZero = decimal.DivisionByZero
         Inexact = decimal.Inexact
@@ -4192,7 +4190,7 @@
         c.prec = 425000000
         c.Emax = 425000000
         c.Emin = -425000000
-        c.rounding = self.decimal.ROUND_HALF_DOWN
+        c.rounding = ROUND_HALF_DOWN
         c.capitals = 0
         c.clamp = 1
         for sig in OrderedSignals[self.decimal]:
@@ -4584,7 +4582,6 @@
     def test_py_rescale(self):
         # Coverage
         Decimal = P.Decimal
-        ROUND_UP = P.ROUND_UP
         localcontext = P.localcontext
 
         with localcontext() as c:
@@ -4594,7 +4591,6 @@
     def test_py__round(self):
         # Coverage
         Decimal = P.Decimal
-        ROUND_UP = P.ROUND_UP
 
         self.assertRaises(ValueError, Decimal("3.1234")._round, 0, ROUND_UP)
 
@@ -4663,11 +4659,6 @@
         self.assertEqual(C.DECIMAL128, 128)
         self.assertEqual(C.IEEE_CONTEXT_MAX_BITS, 512)
 
-        # Rounding modes
-        for i, v in enumerate(RoundingModes[C]):
-            self.assertEqual(v, i)
-        self.assertEqual(C.ROUND_TRUNC, 8)
-
         # Conditions
         for i, v in enumerate(cond):
             self.assertEqual(v, 1<<i)
@@ -4727,7 +4718,6 @@
         # in the same order.
         DefaultContext = C.DefaultContext
         FloatOperation = C.FloatOperation
-        ROUND_HALF_DOWN = C.ROUND_HALF_DOWN
 
         c = DefaultContext.copy()
 
@@ -4800,7 +4790,6 @@
         self.assertRaises(OverflowError, Context, prec=int_max+1)
         self.assertRaises(OverflowError, Context, Emax=int_max+1)
         self.assertRaises(OverflowError, Context, Emin=-int_max-2)
-        self.assertRaises(OverflowError, Context, rounding=int_max+1)
         self.assertRaises(OverflowError, Context, clamp=int_max+1)
         self.assertRaises(OverflowError, Context, capitals=int_max+1)
 
@@ -4812,14 +4801,6 @@
                 self.assertRaises(ValueError, setattr, c, attr, int_max)
                 self.assertRaises(ValueError, setattr, c, attr, -int_max-1)
 
-        # OverflowError, general TypeError
-        for attr in ('rounding',):
-            self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
-            self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
-            if sys.platform != 'win32':
-                self.assertRaises(TypeError, setattr, c, attr, int_max)
-                self.assertRaises(TypeError, setattr, c, attr, -int_max-1)
-
         # OverflowError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
         if C.MAX_PREC == 425000000:
             self.assertRaises(OverflowError, getattr(c, '_unsafe_setprec'),
@@ -4862,6 +4843,17 @@
         self.assertRaises(TypeError, setcontext, "xyz")
         setcontext(saved_context)
 
+    def test_rounding_strings_interned(self):
+
+        self.assertIs(C.ROUND_UP, P.ROUND_UP)
+        self.assertIs(C.ROUND_DOWN, P.ROUND_DOWN)
+        self.assertIs(C.ROUND_CEILING, P.ROUND_CEILING)
+        self.assertIs(C.ROUND_FLOOR, P.ROUND_FLOOR)
+        self.assertIs(C.ROUND_HALF_UP, P.ROUND_HALF_UP)
+        self.assertIs(C.ROUND_HALF_DOWN, P.ROUND_HALF_DOWN)
+        self.assertIs(C.ROUND_HALF_EVEN, P.ROUND_HALF_EVEN)
+        self.assertIs(C.ROUND_05UP, P.ROUND_05UP)
+
     @requires_extra_functionality
     def test_c_context_errors_extra(self):
         Context = C.Context
@@ -4908,7 +4900,6 @@
     def test_c_valid_context(self):
         # These tests are for code coverage in _decimal.
         DefaultContext = C.DefaultContext
-        ROUND_HALF_UP = C.ROUND_HALF_UP
         Clamped = C.Clamped
         Underflow = C.Underflow
         Inexact = C.Inexact
@@ -5000,7 +4991,6 @@
     def test_c_integral(self):
         Decimal = C.Decimal
         Inexact = C.Inexact
-        ROUND_UP = C.ROUND_UP
         localcontext = C.localcontext
 
         x = Decimal(10)
@@ -5034,7 +5024,6 @@
         Decimal = C.Decimal
         InvalidOperation = C.InvalidOperation
         DivisionByZero = C.DivisionByZero
-        ROUND_UP = C.ROUND_UP
         getcontext = C.getcontext
         localcontext = C.localcontext
 
@@ -5237,7 +5226,7 @@
         lim = len(OrderedSignals[C])
         for r in range(lim):
             for t in range(lim):
-                for round in RoundingModes[C]:
+                for round in RoundingModes:
                     flags = random.sample(OrderedSignals[C], r)
                     traps = random.sample(OrderedSignals[C], t)
                     prec = random.randrange(1, 10000)
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -150,6 +150,9 @@
 Library
 -------
 
+- Issue #16422: Use strings for rounding mode constants for better readability
+  and pickling compatibility.
+
 - Issue #15861: tkinter now correctly works with lists and tuples containing
   strings with whitespaces, backslashes or unbalanced braces.
 
diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c
--- a/Modules/_decimal/_decimal.c
+++ b/Modules/_decimal/_decimal.c
@@ -202,6 +202,13 @@
     "Underflow",
 };
 
+#ifdef EXTRA_FUNCTIONALITY
+  #define _PY_DEC_ROUND_GUARD MPD_ROUND_GUARD
+#else
+  #define _PY_DEC_ROUND_GUARD (MPD_ROUND_GUARD-1)
+#endif
+static PyObject *round_map[_PY_DEC_ROUND_GUARD];
+
 static const char *invalid_rounding_err =
 "valid values for rounding are:\n\
   [ROUND_CEILING, ROUND_FLOOR, ROUND_UP, ROUND_DOWN,\n\
@@ -249,13 +256,6 @@
     return -1;
 }
 
-static PyObject *
-type_error_ptr(const char *mesg)
-{
-    PyErr_SetString(PyExc_TypeError, mesg);
-    return NULL;
-}
-
 static int
 runtime_error_int(const char *mesg)
 {
@@ -502,6 +502,27 @@
     return 0;
 }
 
+static int
+getround(PyObject *v)
+{
+    int i;
+
+    if (PyUnicode_Check(v)) {
+        for (i = 0; i < _PY_DEC_ROUND_GUARD; i++) {
+            if (v == round_map[i]) {
+                return i;
+            }
+        }
+        for (i = 0; i < _PY_DEC_ROUND_GUARD; i++) {
+            if (PyUnicode_Compare(v, round_map[i]) == 0) {
+                return i;
+            }
+        }
+    }
+
+    return type_error_int(invalid_rounding_err);
+}
+
 
 /******************************************************************************/
 /*                            SignalDict Object                               */
@@ -715,7 +736,6 @@
 Dec_CONTEXT_GET_SSIZE(prec)
 Dec_CONTEXT_GET_SSIZE(emax)
 Dec_CONTEXT_GET_SSIZE(emin)
-Dec_CONTEXT_GET_SSIZE(round)
 Dec_CONTEXT_GET_SSIZE(clamp)
 
 #ifdef EXTRA_FUNCTIONALITY
@@ -724,6 +744,15 @@
 #endif
 
 static PyObject *
+context_getround(PyObject *self, void *closure UNUSED)
+{
+    int i = mpd_getround(CTX(self));
+
+    Py_INCREF(round_map[i]);
+    return round_map[i];
+}
+
+static PyObject *
 context_getcapitals(PyObject *self, void *closure UNUSED)
 {
     return PyLong_FromLong(CtxCaps(self));
@@ -875,17 +904,16 @@
 context_setround(PyObject *self, PyObject *value, void *closure UNUSED)
 {
     mpd_context_t *ctx;
-    mpd_ssize_t x;
-
-    x = PyLong_AsSsize_t(value);
-    if (x == -1 && PyErr_Occurred()) {
+    int x;
+
+    x = getround(value);
+    if (x == -1) {
         return -1;
     }
-    BOUNDS_CHECK(x, INT_MIN, INT_MAX);
 
     ctx = CTX(self);
-    if (!mpd_qsetround(ctx, (int)x)) {
-        return type_error_int(invalid_rounding_err);
+    if (!mpd_qsetround(ctx, x)) {
+        INTERNAL_ERROR_INT("context_setround"); /* GCOV_NOT_REACHED */
     }
 
     return 0;
@@ -1208,33 +1236,6 @@
 }
 
 static int
-getround(PyObject *v)
-{
-    const char *s;
-    long x;
-    int i;
-
-    if (PyLong_Check(v)) {
-        x = PyLong_AsLong(v);
-        if (x == -1 && PyErr_Occurred()) {
-            return -1;
-        }
-        BOUNDS_CHECK(x, 0, INT_MAX);
-        return (int)x;
-    }
-    else if (PyUnicode_Check(v)) {
-        for (i = 0; i < MPD_ROUND_GUARD; i++) {
-            s = mpd_round_string[i];
-            if (PyUnicode_CompareWithASCIIString(v, s) == 0) {
-                return i;
-            }
-        }
-    }
-
-    return type_error_int("invalid rounding mode");
-}
-
-static int
 context_init(PyObject *self, PyObject *args, PyObject *kwds)
 {
     static char *kwlist[] = {
@@ -1264,6 +1265,9 @@
     if (prec != Py_None && context_setprec(self, prec, NULL) < 0) {
         return -1;
     }
+    if (rounding != Py_None && context_setround(self, rounding, NULL) < 0) {
+        return -1;
+    }
     if (emin != Py_None && context_setemin(self, emin, NULL) < 0) {
         return -1;
     }
@@ -1277,16 +1281,6 @@
        return -1;
     }
 
-    if (rounding != Py_None) {
-        int x = getround(rounding);
-        if (x < 0) {
-            return -1;
-        }
-        if (!mpd_qsetround(CTX(self), x)) {
-            return type_error_int(invalid_rounding_err);
-        }
-    }
-
     if (traps != Py_None) {
         if (PyList_Check(traps)) {
             ret = context_settraps_list(self, traps);
@@ -3345,7 +3339,7 @@
             return NULL;
         }
         if (!mpd_qsetround(&workctx, round)) {
-            return type_error_ptr(invalid_rounding_err);
+            INTERNAL_ERROR_PTR("PyDec_ToIntegralValue"); /* GCOV_NOT_REACHED */
         }
     }
 
@@ -3386,7 +3380,7 @@
             return NULL;
         }
         if (!mpd_qsetround(&workctx, round)) {
-            return type_error_ptr(invalid_rounding_err);
+            INTERNAL_ERROR_PTR("PyDec_ToIntegralExact"); /* GCOV_NOT_REACHED */
         }
     }
 
@@ -4187,7 +4181,7 @@
             return NULL;
         }
         if (!mpd_qsetround(&workctx, round)) {
-            return type_error_ptr(invalid_rounding_err);
+            INTERNAL_ERROR_PTR("dec_mpd_qquantize"); /* GCOV_NOT_REACHED */
         }
     }
 
@@ -5419,17 +5413,6 @@
     {"DECIMAL64", MPD_DECIMAL64},
     {"DECIMAL128", MPD_DECIMAL128},
     {"IEEE_CONTEXT_MAX_BITS", MPD_IEEE_CONTEXT_MAX_BITS},
-#endif
-    {"ROUND_CEILING", MPD_ROUND_CEILING},
-    {"ROUND_FLOOR", MPD_ROUND_FLOOR},
-    {"ROUND_UP", MPD_ROUND_UP},
-    {"ROUND_DOWN", MPD_ROUND_DOWN},
-    {"ROUND_HALF_UP", MPD_ROUND_HALF_UP},
-    {"ROUND_HALF_DOWN", MPD_ROUND_HALF_DOWN},
-    {"ROUND_HALF_EVEN", MPD_ROUND_HALF_EVEN},
-    {"ROUND_05UP", MPD_ROUND_05UP},
-#ifdef EXTRA_FUNCTIONALITY
-    {"ROUND_TRUNC", MPD_ROUND_TRUNC},
     /* int condition flags */
     {"DecClamped", MPD_Clamped},
     {"DecConversionSyntax", MPD_Conversion_syntax},
@@ -5680,6 +5663,13 @@
                                           int_cm->val));
     }
 
+    /* Init string constants */
+    for (i = 0; i < _PY_DEC_ROUND_GUARD; i++) {
+        ASSIGN_PTR(round_map[i], PyUnicode_InternFromString(mpd_round_string[i]));
+        Py_INCREF(round_map[i]);
+        CHECK_INT(PyModule_AddObject(m, mpd_round_string[i], round_map[i]));
+    }
+
     /* Add specification version number */
     CHECK_INT(PyModule_AddStringConstant(m, "__version__", " 1.70"));
 
diff --git a/Modules/_decimal/tests/deccheck.py b/Modules/_decimal/tests/deccheck.py
--- a/Modules/_decimal/tests/deccheck.py
+++ b/Modules/_decimal/tests/deccheck.py
@@ -158,17 +158,9 @@
         C.FloatOperation:      P.FloatOperation,
 }
 
-RoundMap = {
-        C.ROUND_UP:           P.ROUND_UP,
-        C.ROUND_DOWN:         P.ROUND_DOWN,
-        C.ROUND_CEILING:      P.ROUND_CEILING,
-        C.ROUND_FLOOR:        P.ROUND_FLOOR,
-        C.ROUND_HALF_UP:      P.ROUND_HALF_UP,
-        C.ROUND_HALF_DOWN:    P.ROUND_HALF_DOWN,
-        C.ROUND_HALF_EVEN:    P.ROUND_HALF_EVEN,
-        C.ROUND_05UP:         P.ROUND_05UP
-}
-RoundModes = RoundMap.items()
+RoundModes = [C.ROUND_UP, C.ROUND_DOWN, C.ROUND_CEILING, C.ROUND_FLOOR,
+              C.ROUND_HALF_UP, C.ROUND_HALF_DOWN, C.ROUND_HALF_EVEN,
+              C.ROUND_05UP]
 
 
 class Context(object):
@@ -183,7 +175,7 @@
         self.p.prec = self.c.prec
         self.p.Emin = self.c.Emin
         self.p.Emax = self.c.Emax
-        self.p.rounding = RoundMap[self.c.rounding]
+        self.p.rounding = self.c.rounding
         self.p.capitals = self.c.capitals
         self.settraps([sig for sig in self.c.traps if self.c.traps[sig]])
         self.setstatus([sig for sig in self.c.flags if self.c.flags[sig]])
@@ -217,12 +209,12 @@
         self.p.Emax = val
 
     def getround(self):
-        assert(self.c.rounding == RoundMap[self.p.rounding])
+        assert(self.c.rounding == self.p.rounding)
         return self.c.rounding
 
     def setround(self, val):
         self.c.rounding = val
-        self.p.rounding = RoundMap[val]
+        self.p.rounding = val
 
     def getcapitals(self):
         assert(self.c.capitals == self.p.capitals)
@@ -627,8 +619,12 @@
 
         context.clear_status()
 
-        if not t.contextfunc and i == 0 or \
-           convstr and isinstance(op, str):
+        if op in RoundModes:
+            t.cop.append(op)
+            t.pop.append(op)
+
+        elif not t.contextfunc and i == 0 or \
+             convstr and isinstance(op, str):
             try:
                 c = C.Decimal(op)
                 cex = None
@@ -662,10 +658,6 @@
             t.cop.append(op.c)
             t.pop.append(op.p)
 
-        elif op in RoundModes:
-            t.cop.append(op[0])
-            t.pop.append(op[1])
-
         else:
             t.cop.append(op)
             t.pop.append(op)
@@ -809,7 +801,7 @@
                 log("    prec: %d  emin: %d  emax: %d",
                     (context.prec, context.Emin, context.Emax))
                 restr_range = 9999 if context.Emax > 9999 else context.Emax+99
-                for rounding in sorted(RoundMap):
+                for rounding in RoundModes:
                     context.rounding = rounding
                     context.capitals = random.randrange(2)
                     if spec['clamp'] == 'rand':
@@ -941,7 +933,7 @@
 
 def test_from_float(method, prec, exprange, restricted_range, itr, stat):
     """Iterate the __float__ method through many test cases."""
-    for rounding in sorted(RoundMap):
+    for rounding in RoundModes:
         context.rounding = rounding
         for i in range(1000):
             f = randfloat()

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list