diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2016-10-08 09:26:25 (GMT) |
---|---|---|
committer | Serhiy Storchaka <storchaka@gmail.com> | 2016-10-08 09:26:25 (GMT) |
commit | 56588b7055a3c503bb7226a41d10be47f4bf2d58 (patch) | |
tree | e610121b12626a7860a0b95957a3fa596b352365 | |
parent | 2b801456fbfe5416d4cb8095e4e8af8ff588abe2 (diff) | |
parent | 8ef34600c7dfa2608fe1ad235cf5fc36392fe469 (diff) | |
download | cpython-56588b7055a3c503bb7226a41d10be47f4bf2d58.zip cpython-56588b7055a3c503bb7226a41d10be47f4bf2d58.tar.gz cpython-56588b7055a3c503bb7226a41d10be47f4bf2d58.tar.bz2 |
Issue #26906: Resolving special methods of uninitialized type now causes
implicit initialization of the type instead of a fail.
-rw-r--r-- | Misc/NEWS | 3 | ||||
-rw-r--r-- | Objects/typeobject.c | 24 |
2 files changed, 22 insertions, 5 deletions
@@ -10,6 +10,9 @@ What's New in Python 3.6.0 beta 2 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 --git a/Objects/typeobject.c b/Objects/typeobject.c index 52d5982..1960c1a 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -2914,11 +2914,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 |