summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorPetr Viktorin <encukou@gmail.com>2020-11-03 21:27:12 (GMT)
committerGitHub <noreply@github.com>2020-11-03 21:27:12 (GMT)
commit57aaaa8d2a43bddffeca4ead5632ce6652945cc0 (patch)
tree30d87542dadc05d27d170ae279cb80c82855c9fc /Objects
parenta603c3d371cda76bae75836faf068e146eb6ab76 (diff)
downloadcpython-57aaaa8d2a43bddffeca4ead5632ce6652945cc0.zip
cpython-57aaaa8d2a43bddffeca4ead5632ce6652945cc0.tar.gz
cpython-57aaaa8d2a43bddffeca4ead5632ce6652945cc0.tar.bz2
Add _PyType_GetModuleByDef (GH-22835)
See https://mail.python.org/archives/list/capi-sig@python.org/thread/T3P2QNLNLBRFHWSKYSTPMVEIL2EEKFJU/ for discussion. https://bugs.python.org/issue42100
Diffstat (limited to 'Objects')
-rw-r--r--Objects/typeobject.c38
1 files changed, 38 insertions, 0 deletions
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index bd1587a..2daf374 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -3158,6 +3158,44 @@ PyType_GetModuleState(PyTypeObject *type)
return PyModule_GetState(m);
}
+
+/* Get the module of the first superclass where the module has the
+ * given PyModuleDef.
+ * Implemented by walking the MRO, is relatively slow.
+ *
+ * This is internal API for experimentation within stdlib. Discussion:
+ * https://mail.python.org/archives/list/capi-sig@python.org/thread/T3P2QNLNLBRFHWSKYSTPMVEIL2EEKFJU/
+ */
+PyObject *
+_PyType_GetModuleByDef(PyTypeObject *type, struct PyModuleDef *def)
+{
+ assert(PyType_Check(type));
+ assert(type->tp_mro);
+ int i;
+ for (i = 0; i < PyTuple_GET_SIZE(type->tp_mro); i++) {
+ PyObject *super = PyTuple_GET_ITEM(type->tp_mro, i);
+ if (!PyType_HasFeature((PyTypeObject *)super, Py_TPFLAGS_HEAPTYPE)) {
+ /* Currently, there's no way for static types to inherit
+ * from heap types, but to allow that possibility,
+ * we `continue` rather than `break`.
+ * We'll just potentially loop a few more times before throwing
+ * the error.
+ */
+ continue;
+ }
+ PyHeapTypeObject *ht = (PyHeapTypeObject*)super;
+ if (ht->ht_module && PyModule_GetDef(ht->ht_module) == def) {
+ return ht->ht_module;
+ }
+ }
+ PyErr_Format(
+ PyExc_TypeError,
+ "_PyType_GetModuleByDef: No superclass of '%s' has the given module",
+ type->tp_name);
+ return NULL;
+}
+
+
/* Internal API to look for a name through the MRO, bypassing the method cache.
This returns a borrowed reference, and might set an exception.
'error' is set to: -1: error with exception; 1: error without exception; 0: ok */