(original) (raw)
changeset: 104368:d24f1467a297 parent: 104363:696851f38c93 parent: 104367:888a26fac9d2 user: Serhiy Storchaka storchaka@gmail.com date: Sat Oct 08 12:28:25 2016 +0300 files: Misc/NEWS description: Issue #26906: Resolving special methods of uninitialized type now causes implicit initialization of the type instead of a fail. diff -r 696851f38c93 -r d24f1467a297 Misc/NEWS --- a/Misc/NEWS Fri Oct 07 23:47:17 2016 +0300 +++ b/Misc/NEWS Sat Oct 08 12:28:25 2016 +0300 @@ -10,6 +10,9 @@ 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. diff -r 696851f38c93 -r d24f1467a297 Objects/typeobject.c --- a/Objects/typeobject.c Fri Oct 07 23:47:17 2016 +0300 +++ b/Objects/typeobject.c Sat Oct 08 12:28:25 2016 +0300 @@ -2914,11 +2914,25 @@ /* 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 /storchaka@gmail.com