Skip to content

Commit 57aaaa8

Browse files
authored
1 parent a603c3d commit 57aaaa8

File tree

4 files changed

+52
-3
lines changed

4 files changed

+52
-3
lines changed

Include/cpython/object.h

+2
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,8 @@ PyAPI_FUNC(PyObject *) _PyObject_LookupSpecial(PyObject *, _Py_Identifier *);
296296
PyAPI_FUNC(PyTypeObject *) _PyType_CalculateMetaclass(PyTypeObject *, PyObject *);
297297
PyAPI_FUNC(PyObject *) _PyType_GetDocFromInternalDoc(const char *, const char *);
298298
PyAPI_FUNC(PyObject *) _PyType_GetTextSignatureFromInternalDoc(const char *, const char *);
299+
struct PyModuleDef;
300+
PyAPI_FUNC(PyObject *) _PyType_GetModuleByDef(PyTypeObject *, struct PyModuleDef *);
299301

300302
struct _Py_Identifier;
301303
PyAPI_FUNC(int) PyObject_Print(PyObject *, FILE *, int);

Modules/_testmultiphase.c

+7-1
Original file line numberDiff line numberDiff line change
@@ -121,24 +121,30 @@ static PyType_Spec Example_Type_spec = {
121121
};
122122

123123

124+
static PyModuleDef def_meth_state_access;
125+
124126
/*[clinic input]
125127
_testmultiphase.StateAccessType.get_defining_module
126128
127129
cls: defining_class
128130
129131
Return the module of the defining class.
132+
133+
Also tests that result of _PyType_GetModuleByDef matches defining_class's
134+
module.
130135
[clinic start generated code]*/
131136

132137
static PyObject *
133138
_testmultiphase_StateAccessType_get_defining_module_impl(StateAccessTypeObject *self,
134139
PyTypeObject *cls)
135-
/*[clinic end generated code: output=ba2a14284a5d0921 input=946149f91cf72c0d]*/
140+
/*[clinic end generated code: output=ba2a14284a5d0921 input=356f999fc16e0933]*/
136141
{
137142
PyObject *retval;
138143
retval = PyType_GetModule(cls);
139144
if (retval == NULL) {
140145
return NULL;
141146
}
147+
assert(_PyType_GetModuleByDef(Py_TYPE(self), &def_meth_state_access) == retval);
142148
Py_INCREF(retval);
143149
return retval;
144150
}

Modules/clinic/_testmultiphase.c.h

+5-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Objects/typeobject.c

+38
Original file line numberDiff line numberDiff line change
@@ -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/[email protected]/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

Comments
 (0)