summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2016-10-08 09:26:25 (GMT)
committerSerhiy Storchaka <storchaka@gmail.com>2016-10-08 09:26:25 (GMT)
commit56588b7055a3c503bb7226a41d10be47f4bf2d58 (patch)
treee610121b12626a7860a0b95957a3fa596b352365
parent2b801456fbfe5416d4cb8095e4e8af8ff588abe2 (diff)
parent8ef34600c7dfa2608fe1ad235cf5fc36392fe469 (diff)
downloadcpython-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/NEWS3
-rw-r--r--Objects/typeobject.c24
2 files changed, 22 insertions, 5 deletions
diff --git a/Misc/NEWS b/Misc/NEWS
index c258a67..237bf6f 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -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