@@ -3158,6 +3158,44 @@ PyType_GetModuleState(PyTypeObject *type)
31583158 return PyModule_GetState (m );
31593159}
31603160
3161+
3162+ /* Get the module of the first superclass where the module has the
3163+ * given PyModuleDef.
3164+ * Implemented by walking the MRO, is relatively slow.
3165+ *
3166+ * This is internal API for experimentation within stdlib. Discussion:
3167+ * https://mail.python.org/archives/list/capi-sig@python.org/thread/T3P2QNLNLBRFHWSKYSTPMVEIL2EEKFJU/
3168+ */
3169+ PyObject *
3170+ _PyType_GetModuleByDef (PyTypeObject * type , struct PyModuleDef * def )
3171+ {
3172+ assert (PyType_Check (type ));
3173+ assert (type -> tp_mro );
3174+ int i ;
3175+ for (i = 0 ; i < PyTuple_GET_SIZE (type -> tp_mro ); i ++ ) {
3176+ PyObject * super = PyTuple_GET_ITEM (type -> tp_mro , i );
3177+ if (!PyType_HasFeature ((PyTypeObject * )super , Py_TPFLAGS_HEAPTYPE )) {
3178+ /* Currently, there's no way for static types to inherit
3179+ * from heap types, but to allow that possibility,
3180+ * we `continue` rather than `break`.
3181+ * We'll just potentially loop a few more times before throwing
3182+ * the error.
3183+ */
3184+ continue ;
3185+ }
3186+ PyHeapTypeObject * ht = (PyHeapTypeObject * )super ;
3187+ if (ht -> ht_module && PyModule_GetDef (ht -> ht_module ) == def ) {
3188+ return ht -> ht_module ;
3189+ }
3190+ }
3191+ PyErr_Format (
3192+ PyExc_TypeError ,
3193+ "_PyType_GetModuleByDef: No superclass of '%s' has the given module" ,
3194+ type -> tp_name );
3195+ return NULL ;
3196+ }
3197+
3198+
31613199/* Internal API to look for a name through the MRO, bypassing the method cache.
31623200 This returns a borrowed reference, and might set an exception.
31633201 'error' is set to: -1: error with exception; 1: error without exception; 0: ok */
0 commit comments