[Python-checkins] cpython (merge 3.5 -> default): Merge 3.5.

stefan.krah python-checkins at python.org
Sun Jul 17 08:14:05 EDT 2016


https://hg.python.org/cpython/rev/3763df0917a2
changeset:   102385:3763df0917a2
parent:      102383:5540234ca517
parent:      102384:f8cb955efd6a
user:        Stefan Krah <skrah at bytereef.org>
date:        Sun Jul 17 14:12:59 2016 +0200
summary:
  Merge 3.5.

files:
  Lib/test/test_decimal.py    |  28 +++++++++++
  Modules/_decimal/_decimal.c |  59 +++++++++++++++++++++---
  2 files changed, 79 insertions(+), 8 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
@@ -5431,6 +5431,34 @@
             y = Decimal(10**(9*25)).__sizeof__()
             self.assertEqual(y, x+4)
 
+    def test_internal_use_of_overridden_methods(self):
+        Decimal = C.Decimal
+
+        # Unsound subtyping
+        class X(float):
+            def as_integer_ratio(self):
+                return 1
+            def __abs__(self):
+                return self
+
+        class Y(float):
+            def __abs__(self):
+                return [1]*200
+
+        class I(int):
+            def bit_length(self):
+                return [1]*200
+
+        class Z(float):
+            def as_integer_ratio(self):
+                return (I(1), I(1))
+            def __abs__(self):
+                return self
+
+        for cls in X, Y, Z:
+            self.assertEqual(Decimal.from_float(cls(101.1)),
+                             Decimal.from_float(101.1))
+
 @requires_docstrings
 @unittest.skipUnless(C, "test requires C version")
 class SignatureTest(unittest.TestCase):
diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c
--- a/Modules/_decimal/_decimal.c
+++ b/Modules/_decimal/_decimal.c
@@ -2207,6 +2207,14 @@
     return dec;
 }
 
+/* External C-API functions */
+static binaryfunc _py_long_multiply;
+static binaryfunc _py_long_floor_divide;
+static ternaryfunc _py_long_power;
+static unaryfunc _py_float_abs;
+static PyCFunction _py_long_bit_length;
+static PyCFunction _py_float_as_integer_ratio;
+
 /* Return a PyDecObject or a subtype from a PyFloatObject.
    Conversion is exact. */
 static PyObject *
@@ -2257,13 +2265,13 @@
     }
 
     /* absolute value of the float */
-    tmp = PyObject_CallMethod(v, "__abs__", NULL);
+    tmp = _py_float_abs(v);
     if (tmp == NULL) {
         return NULL;
     }
 
     /* float as integer ratio: numerator/denominator */
-    n_d = PyObject_CallMethod(tmp, "as_integer_ratio", NULL);
+    n_d = _py_float_as_integer_ratio(tmp, NULL);
     Py_DECREF(tmp);
     if (n_d == NULL) {
         return NULL;
@@ -2271,7 +2279,7 @@
     n = PyTuple_GET_ITEM(n_d, 0);
     d = PyTuple_GET_ITEM(n_d, 1);
 
-    tmp = PyObject_CallMethod(d, "bit_length", NULL);
+    tmp = _py_long_bit_length(d, NULL);
     if (tmp == NULL) {
         Py_DECREF(n_d);
         return NULL;
@@ -3397,7 +3405,6 @@
     mpd_ssize_t exp;
     PyObject *context;
     uint32_t status = 0;
-    PyNumberMethods *long_methods = PyLong_Type.tp_as_number;
 
     if (mpd_isspecial(MPD(self))) {
         if (mpd_isnan(MPD(self))) {
@@ -3444,14 +3451,14 @@
         goto error;
     }
 
-    Py_SETREF(exponent, long_methods->nb_power(tmp, exponent, Py_None));
+    Py_SETREF(exponent, _py_long_power(tmp, exponent, Py_None));
     Py_DECREF(tmp);
     if (exponent == NULL) {
         goto error;
     }
 
     if (exp >= 0) {
-        Py_SETREF(numerator, long_methods->nb_multiply(numerator, exponent));
+        Py_SETREF(numerator, _py_long_multiply(numerator, exponent));
         if (numerator == NULL) {
             goto error;
         }
@@ -3467,8 +3474,8 @@
         if (tmp == NULL) {
             goto error;
         }
-        Py_SETREF(numerator, long_methods->nb_floor_divide(numerator, tmp));
-        Py_SETREF(denominator, long_methods->nb_floor_divide(denominator, tmp));
+        Py_SETREF(numerator, _py_long_floor_divide(numerator, tmp));
+        Py_SETREF(denominator, _py_long_floor_divide(denominator, tmp));
         Py_DECREF(tmp);
         if (numerator == NULL || denominator == NULL) {
             goto error;
@@ -5611,6 +5618,32 @@
 #define CHECK_PTR(expr) \
     do { if ((expr) == NULL) goto error; } while (0)
 
+
+static PyCFunction
+cfunc_noargs(PyTypeObject *t, const char *name)
+{
+    struct PyMethodDef *m;
+
+    if (t->tp_methods == NULL) {
+        goto error;
+    }
+
+    for (m = t->tp_methods; m->ml_name != NULL; m++) {
+        if (strcmp(name, m->ml_name) == 0) {
+            if (!(m->ml_flags & METH_NOARGS)) {
+                goto error;
+            }
+            return m->ml_meth;
+        }
+    }
+
+error:
+    PyErr_Format(PyExc_RuntimeError,
+        "internal error: could not find method %s", name);
+    return NULL;
+}
+
+
 PyMODINIT_FUNC
 PyInit__decimal(void)
 {
@@ -5635,6 +5668,16 @@
     mpd_setminalloc(_Py_DEC_MINALLOC);
 
 
+    /* Init external C-API functions */
+    _py_long_multiply = PyLong_Type.tp_as_number->nb_multiply;
+    _py_long_floor_divide = PyLong_Type.tp_as_number->nb_floor_divide;
+    _py_long_power = PyLong_Type.tp_as_number->nb_power;
+    _py_float_abs = PyFloat_Type.tp_as_number->nb_absolute;
+    ASSIGN_PTR(_py_float_as_integer_ratio, cfunc_noargs(&PyFloat_Type,
+                                                        "as_integer_ratio"));
+    ASSIGN_PTR(_py_long_bit_length, cfunc_noargs(&PyLong_Type, "bit_length"));
+
+
     /* Init types */
     PyDec_Type.tp_base = &PyBaseObject_Type;
     PyDecContext_Type.tp_base = &PyBaseObject_Type;

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


More information about the Python-checkins mailing list