Skip to content

Commit

Permalink
Add _PyType_GetModuleByDef
Browse files Browse the repository at this point in the history
  • Loading branch information
encukou committed Oct 20, 2020
1 parent 1d34699 commit 0b0d93c
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 3 deletions.
2 changes: 2 additions & 0 deletions Include/cpython/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,8 @@ PyAPI_FUNC(PyObject *) _PyObject_LookupSpecial(PyObject *, _Py_Identifier *);
PyAPI_FUNC(PyTypeObject *) _PyType_CalculateMetaclass(PyTypeObject *, PyObject *);
PyAPI_FUNC(PyObject *) _PyType_GetDocFromInternalDoc(const char *, const char *);
PyAPI_FUNC(PyObject *) _PyType_GetTextSignatureFromInternalDoc(const char *, const char *);
struct PyModuleDef;
PyAPI_FUNC(PyObject *) _PyType_GetModuleByDef(PyTypeObject *, struct PyModuleDef *);

struct _Py_Identifier;
PyAPI_FUNC(int) PyObject_Print(PyObject *, FILE *, int);
Expand Down
8 changes: 7 additions & 1 deletion Modules/_testmultiphase.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,24 +121,30 @@ static PyType_Spec Example_Type_spec = {
};


static PyModuleDef def_meth_state_access;

/*[clinic input]
_testmultiphase.StateAccessType.get_defining_module
cls: defining_class
Return the module of the defining class.
Also tests that result of _PyType_GetModuleByDef matches defining_class's
module.
[clinic start generated code]*/

static PyObject *
_testmultiphase_StateAccessType_get_defining_module_impl(StateAccessTypeObject *self,
PyTypeObject *cls)
/*[clinic end generated code: output=ba2a14284a5d0921 input=946149f91cf72c0d]*/
/*[clinic end generated code: output=ba2a14284a5d0921 input=356f999fc16e0933]*/
{
PyObject *retval;
retval = PyType_GetModule(cls);
if (retval == NULL) {
return NULL;
}
assert(_PyType_GetModuleByDef(Py_TYPE(self), &def_meth_state_access) == retval);
Py_INCREF(retval);
return retval;
}
Expand Down
7 changes: 5 additions & 2 deletions Modules/clinic/_testmultiphase.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

38 changes: 38 additions & 0 deletions Objects/typeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -3155,6 +3155,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 */
Expand Down

0 comments on commit 0b0d93c

Please sign in to comment.