summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/test/test_descr.py6
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2017-12-19-21-14-41.bpo-32379.B7mOmI.rst1
-rw-r--r--Objects/typeobject.c40
3 files changed, 43 insertions, 4 deletions
diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py
index ced25f3..d24d005 100644
--- a/Lib/test/test_descr.py
+++ b/Lib/test/test_descr.py
@@ -1783,6 +1783,12 @@ order (MRO) for bases """
def f(self): return "C"
class D(B, C):
pass
+ self.assertEqual(A.mro(), [A, object])
+ self.assertEqual(A.__mro__, (A, object))
+ self.assertEqual(B.mro(), [B, A, object])
+ self.assertEqual(B.__mro__, (B, A, object))
+ self.assertEqual(C.mro(), [C, A, object])
+ self.assertEqual(C.__mro__, (C, A, object))
self.assertEqual(D.mro(), [D, B, C, A, object])
self.assertEqual(D.__mro__, (D, B, C, A, object))
self.assertEqual(D().f(), "C")
diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-12-19-21-14-41.bpo-32379.B7mOmI.rst b/Misc/NEWS.d/next/Core and Builtins/2017-12-19-21-14-41.bpo-32379.B7mOmI.rst
new file mode 100644
index 0000000..1050c61
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2017-12-19-21-14-41.bpo-32379.B7mOmI.rst
@@ -0,0 +1 @@
+Make MRO computation faster when a class inherits from a single base.
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index aa90701..849c6dc 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -1761,6 +1761,36 @@ mro_implementation(PyTypeObject *type)
return NULL;
}
+ bases = type->tp_bases;
+ n = PyTuple_GET_SIZE(bases);
+ if (n == 1) {
+ /* Fast path: if there is a single base, constructing the MRO
+ * is trivial.
+ */
+ PyTypeObject *base = (PyTypeObject *)PyTuple_GET_ITEM(bases, 0);
+ Py_ssize_t k;
+
+ if (base->tp_mro == NULL) {
+ PyErr_Format(PyExc_TypeError,
+ "Cannot extend an incomplete type '%.100s'",
+ base->tp_name);
+ return NULL;
+ }
+ k = PyTuple_GET_SIZE(base->tp_mro);
+ result = PyTuple_New(k + 1);
+ if (result == NULL) {
+ return NULL;
+ }
+ Py_INCREF(type);
+ PyTuple_SET_ITEM(result, 0, (PyObject *) type);
+ for (i = 0; i < k; i++) {
+ PyObject *cls = PyTuple_GET_ITEM(base->tp_mro, i);
+ Py_INCREF(cls);
+ PyTuple_SET_ITEM(result, i + 1, cls);
+ }
+ return result;
+ }
+
/* Find a superclass linearization that honors the constraints
of the explicit lists of bases and the constraints implied by
each base class.
@@ -1770,9 +1800,6 @@ mro_implementation(PyTypeObject *type)
to_merge is the declared list of bases.
*/
- bases = type->tp_bases;
- n = PyTuple_GET_SIZE(bases);
-
to_merge = PyList_New(n+1);
if (to_merge == NULL)
return NULL;
@@ -1830,7 +1857,12 @@ static PyObject *
type_mro_impl(PyTypeObject *self)
/*[clinic end generated code: output=bffc4a39b5b57027 input=28414f4e156db28d]*/
{
- return mro_implementation(self);
+ PyObject *seq;
+ seq = mro_implementation(self);
+ if (seq != NULL && !PyList_Check(seq)) {
+ Py_SETREF(seq, PySequence_List(seq));
+ }
+ return seq;
}
static int