]> granicus.if.org Git - python/commitdiff
Issue #26906: Resolving special methods of uninitialized type now causes
authorSerhiy Storchaka <storchaka@gmail.com>
Sat, 8 Oct 2016 09:24:09 +0000 (12:24 +0300)
committerSerhiy Storchaka <storchaka@gmail.com>
Sat, 8 Oct 2016 09:24:09 +0000 (12:24 +0300)
implicit initialization of the type instead of a fail.

Misc/NEWS
Objects/typeobject.c

index 1b1c9d63dc245dbd5cd8c8e5ca14874d035e7dfd..91681976c84879969f16cddd1c4541e576b056f5 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@ Release date: TBA
 Core and Builtins
 -----------------
 
+- Issue #26906: Resolving special methods of uninitialized type now causes
+  implicit initialization of the type instead of a fail.
+
 - Issue #18287: PyType_Ready() now checks that tp_name is not NULL.
   Original patch by Niklas Koep.
 
index cbffecd5db3d8d7d024f93982774bbc24e0e7c2a..e9384ab72530846be9cea7c5116937cd96e5fd44 100644 (file)
@@ -2869,11 +2869,25 @@ _PyType_Lookup(PyTypeObject *type, PyObject *name)
     /* Look in tp_dict of types in MRO */
     mro = type->tp_mro;
 
-    /* If mro is NULL, the type is either not yet initialized
-       by PyType_Ready(), or already cleared by type_clear().
-       Either way the safest thing to do is to return NULL. */
-    if (mro == NULL)
-        return NULL;
+    if (mro == NULL) {
+        if ((type->tp_flags & Py_TPFLAGS_READYING) == 0 &&
+            PyType_Ready(type) < 0) {
+            /* It's not ideal to clear the error condition,
+               but this function is documented as not setting
+               an exception, and I don't want to change that.
+               When PyType_Ready() can't proceed, it won't
+               set the "ready" flag, so future attempts to ready
+               the same type will call it again -- hopefully
+               in a context that propagates the exception out.
+            */
+            PyErr_Clear();
+            return NULL;
+        }
+        mro = type->tp_mro;
+        if (mro == NULL) {
+            return NULL;
+        }
+    }
 
     res = NULL;
     /* keep a strong reference to mro because type->tp_mro can be replaced