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
This commit is contained in:
parent
a603c3d371
commit
57aaaa8d2a
|
@ -296,6 +296,8 @@ PyAPI_FUNC(PyObject *) _PyObject_LookupSpecial(PyObject *, _Py_Identifier *);
|
||||||
PyAPI_FUNC(PyTypeObject *) _PyType_CalculateMetaclass(PyTypeObject *, PyObject *);
|
PyAPI_FUNC(PyTypeObject *) _PyType_CalculateMetaclass(PyTypeObject *, PyObject *);
|
||||||
PyAPI_FUNC(PyObject *) _PyType_GetDocFromInternalDoc(const char *, const char *);
|
PyAPI_FUNC(PyObject *) _PyType_GetDocFromInternalDoc(const char *, const char *);
|
||||||
PyAPI_FUNC(PyObject *) _PyType_GetTextSignatureFromInternalDoc(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;
|
struct _Py_Identifier;
|
||||||
PyAPI_FUNC(int) PyObject_Print(PyObject *, FILE *, int);
|
PyAPI_FUNC(int) PyObject_Print(PyObject *, FILE *, int);
|
||||||
|
|
|
@ -121,24 +121,30 @@ static PyType_Spec Example_Type_spec = {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static PyModuleDef def_meth_state_access;
|
||||||
|
|
||||||
/*[clinic input]
|
/*[clinic input]
|
||||||
_testmultiphase.StateAccessType.get_defining_module
|
_testmultiphase.StateAccessType.get_defining_module
|
||||||
|
|
||||||
cls: defining_class
|
cls: defining_class
|
||||||
|
|
||||||
Return the module of the 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]*/
|
[clinic start generated code]*/
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_testmultiphase_StateAccessType_get_defining_module_impl(StateAccessTypeObject *self,
|
_testmultiphase_StateAccessType_get_defining_module_impl(StateAccessTypeObject *self,
|
||||||
PyTypeObject *cls)
|
PyTypeObject *cls)
|
||||||
/*[clinic end generated code: output=ba2a14284a5d0921 input=946149f91cf72c0d]*/
|
/*[clinic end generated code: output=ba2a14284a5d0921 input=356f999fc16e0933]*/
|
||||||
{
|
{
|
||||||
PyObject *retval;
|
PyObject *retval;
|
||||||
retval = PyType_GetModule(cls);
|
retval = PyType_GetModule(cls);
|
||||||
if (retval == NULL) {
|
if (retval == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
assert(_PyType_GetModuleByDef(Py_TYPE(self), &def_meth_state_access) == retval);
|
||||||
Py_INCREF(retval);
|
Py_INCREF(retval);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,10 @@ PyDoc_STRVAR(_testmultiphase_StateAccessType_get_defining_module__doc__,
|
||||||
"get_defining_module($self, /)\n"
|
"get_defining_module($self, /)\n"
|
||||||
"--\n"
|
"--\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Return the module of the defining class.");
|
"Return the module of the defining class.\n"
|
||||||
|
"\n"
|
||||||
|
"Also tests that result of _PyType_GetModuleByDef matches defining_class\'s\n"
|
||||||
|
"module.");
|
||||||
|
|
||||||
#define _TESTMULTIPHASE_STATEACCESSTYPE_GET_DEFINING_MODULE_METHODDEF \
|
#define _TESTMULTIPHASE_STATEACCESSTYPE_GET_DEFINING_MODULE_METHODDEF \
|
||||||
{"get_defining_module", (PyCFunction)(void(*)(void))_testmultiphase_StateAccessType_get_defining_module, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _testmultiphase_StateAccessType_get_defining_module__doc__},
|
{"get_defining_module", (PyCFunction)(void(*)(void))_testmultiphase_StateAccessType_get_defining_module, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _testmultiphase_StateAccessType_get_defining_module__doc__},
|
||||||
|
@ -98,4 +101,4 @@ _testmultiphase_StateAccessType_get_count(StateAccessTypeObject *self, PyTypeObj
|
||||||
exit:
|
exit:
|
||||||
return return_value;
|
return return_value;
|
||||||
}
|
}
|
||||||
/*[clinic end generated code: output=39eea487e94e7f5d input=a9049054013a1b77]*/
|
/*[clinic end generated code: output=f01137bb3b373e14 input=a9049054013a1b77]*/
|
||||||
|
|
|
@ -3158,6 +3158,44 @@ PyType_GetModuleState(PyTypeObject *type)
|
||||||
return PyModule_GetState(m);
|
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.
|
/* Internal API to look for a name through the MRO, bypassing the method cache.
|
||||||
This returns a borrowed reference, and might set an exception.
|
This returns a borrowed reference, and might set an exception.
|
||||||
'error' is set to: -1: error with exception; 1: error without exception; 0: ok */
|
'error' is set to: -1: error with exception; 1: error without exception; 0: ok */
|
||||||
|
|
Loading…
Reference in New Issue