mirror of https://github.com/python/cpython
bpo-46433: _PyType_GetModuleByDef: handle static types in MRO (GH-30696)
Automerge-Triggered-By: GH:encukou
This commit is contained in:
parent
0d05da1fbf
commit
0ef0853012
|
@ -1068,6 +1068,22 @@ class Test_ModuleStateAccess(unittest.TestCase):
|
||||||
with self.assertRaises(TypeError):
|
with self.assertRaises(TypeError):
|
||||||
increment_count(1, 2, 3)
|
increment_count(1, 2, 3)
|
||||||
|
|
||||||
|
def test_get_module_bad_def(self):
|
||||||
|
# _PyType_GetModuleByDef fails gracefully if it doesn't
|
||||||
|
# find what it's looking for.
|
||||||
|
# see bpo-46433
|
||||||
|
instance = self.module.StateAccessType()
|
||||||
|
with self.assertRaises(TypeError):
|
||||||
|
instance.getmodulebydef_bad_def()
|
||||||
|
|
||||||
|
def test_get_module_static_in_mro(self):
|
||||||
|
# Here, the class _PyType_GetModuleByDef is looking for
|
||||||
|
# appears in the MRO after a static type (Exception).
|
||||||
|
# see bpo-46433
|
||||||
|
class Subclass(BaseException, self.module.StateAccessType):
|
||||||
|
pass
|
||||||
|
self.assertIs(Subclass().get_defining_module(), self.module)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
The internal function _PyType_GetModuleByDef now correctly handles
|
||||||
|
inheritance patterns involving static types.
|
|
@ -126,6 +126,8 @@ static PyType_Spec Example_Type_spec = {
|
||||||
|
|
||||||
|
|
||||||
static PyModuleDef def_meth_state_access;
|
static PyModuleDef def_meth_state_access;
|
||||||
|
static PyModuleDef def_nonmodule;
|
||||||
|
static PyModuleDef def_nonmodule_with_methods;
|
||||||
|
|
||||||
/*[clinic input]
|
/*[clinic input]
|
||||||
_testmultiphase.StateAccessType.get_defining_module
|
_testmultiphase.StateAccessType.get_defining_module
|
||||||
|
@ -153,6 +155,24 @@ _testmultiphase_StateAccessType_get_defining_module_impl(StateAccessTypeObject *
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*[clinic input]
|
||||||
|
_testmultiphase.StateAccessType.getmodulebydef_bad_def
|
||||||
|
|
||||||
|
cls: defining_class
|
||||||
|
|
||||||
|
Test that result of _PyType_GetModuleByDef with a bad def is NULL.
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
_testmultiphase_StateAccessType_getmodulebydef_bad_def_impl(StateAccessTypeObject *self,
|
||||||
|
PyTypeObject *cls)
|
||||||
|
/*[clinic end generated code: output=64509074dfcdbd31 input=906047715ee293cd]*/
|
||||||
|
{
|
||||||
|
_PyType_GetModuleByDef(Py_TYPE(self), &def_nonmodule); // should raise
|
||||||
|
assert(PyErr_Occurred());
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/*[clinic input]
|
/*[clinic input]
|
||||||
_testmultiphase.StateAccessType.increment_count_clinic
|
_testmultiphase.StateAccessType.increment_count_clinic
|
||||||
|
|
||||||
|
@ -249,6 +269,7 @@ _testmultiphase_StateAccessType_get_count_impl(StateAccessTypeObject *self,
|
||||||
|
|
||||||
static PyMethodDef StateAccessType_methods[] = {
|
static PyMethodDef StateAccessType_methods[] = {
|
||||||
_TESTMULTIPHASE_STATEACCESSTYPE_GET_DEFINING_MODULE_METHODDEF
|
_TESTMULTIPHASE_STATEACCESSTYPE_GET_DEFINING_MODULE_METHODDEF
|
||||||
|
_TESTMULTIPHASE_STATEACCESSTYPE_GETMODULEBYDEF_BAD_DEF_METHODDEF
|
||||||
_TESTMULTIPHASE_STATEACCESSTYPE_GET_COUNT_METHODDEF
|
_TESTMULTIPHASE_STATEACCESSTYPE_GET_COUNT_METHODDEF
|
||||||
_TESTMULTIPHASE_STATEACCESSTYPE_INCREMENT_COUNT_CLINIC_METHODDEF
|
_TESTMULTIPHASE_STATEACCESSTYPE_INCREMENT_COUNT_CLINIC_METHODDEF
|
||||||
{
|
{
|
||||||
|
@ -437,9 +458,6 @@ PyInit__testmultiphase(PyObject *spec)
|
||||||
|
|
||||||
/**** Importing a non-module object ****/
|
/**** Importing a non-module object ****/
|
||||||
|
|
||||||
static PyModuleDef def_nonmodule;
|
|
||||||
static PyModuleDef def_nonmodule_with_methods;
|
|
||||||
|
|
||||||
/* Create a SimpleNamespace(three=3) */
|
/* Create a SimpleNamespace(three=3) */
|
||||||
static PyObject*
|
static PyObject*
|
||||||
createfunc_nonmodule(PyObject *spec, PyModuleDef *def)
|
createfunc_nonmodule(PyObject *spec, PyModuleDef *def)
|
||||||
|
|
|
@ -35,6 +35,36 @@ exit:
|
||||||
return return_value;
|
return return_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(_testmultiphase_StateAccessType_getmodulebydef_bad_def__doc__,
|
||||||
|
"getmodulebydef_bad_def($self, /)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n"
|
||||||
|
"Test that result of _PyType_GetModuleByDef with a bad def is NULL.");
|
||||||
|
|
||||||
|
#define _TESTMULTIPHASE_STATEACCESSTYPE_GETMODULEBYDEF_BAD_DEF_METHODDEF \
|
||||||
|
{"getmodulebydef_bad_def", (PyCFunction)(void(*)(void))_testmultiphase_StateAccessType_getmodulebydef_bad_def, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _testmultiphase_StateAccessType_getmodulebydef_bad_def__doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
_testmultiphase_StateAccessType_getmodulebydef_bad_def_impl(StateAccessTypeObject *self,
|
||||||
|
PyTypeObject *cls);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
_testmultiphase_StateAccessType_getmodulebydef_bad_def(StateAccessTypeObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
|
||||||
|
{
|
||||||
|
PyObject *return_value = NULL;
|
||||||
|
static const char * const _keywords[] = { NULL};
|
||||||
|
static _PyArg_Parser _parser = {":getmodulebydef_bad_def", _keywords, 0};
|
||||||
|
|
||||||
|
if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser
|
||||||
|
)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
return_value = _testmultiphase_StateAccessType_getmodulebydef_bad_def_impl(self, cls);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(_testmultiphase_StateAccessType_increment_count_clinic__doc__,
|
PyDoc_STRVAR(_testmultiphase_StateAccessType_increment_count_clinic__doc__,
|
||||||
"increment_count_clinic($self, /, n=1, *, twice=False)\n"
|
"increment_count_clinic($self, /, n=1, *, twice=False)\n"
|
||||||
"--\n"
|
"--\n"
|
||||||
|
@ -101,4 +131,4 @@ _testmultiphase_StateAccessType_get_count(StateAccessTypeObject *self, PyTypeObj
|
||||||
exit:
|
exit:
|
||||||
return return_value;
|
return return_value;
|
||||||
}
|
}
|
||||||
/*[clinic end generated code: output=f01137bb3b373e14 input=a9049054013a1b77]*/
|
/*[clinic end generated code: output=eb1b8c2ee6290be3 input=a9049054013a1b77]*/
|
||||||
|
|
|
@ -3756,11 +3756,10 @@ _PyType_GetModuleByDef(PyTypeObject *type, struct PyModuleDef *def)
|
||||||
Py_ssize_t n = PyTuple_GET_SIZE(mro);
|
Py_ssize_t n = PyTuple_GET_SIZE(mro);
|
||||||
for (Py_ssize_t i = 0; i < n; i++) {
|
for (Py_ssize_t i = 0; i < n; i++) {
|
||||||
PyObject *super = PyTuple_GET_ITEM(mro, i);
|
PyObject *super = PyTuple_GET_ITEM(mro, i);
|
||||||
// _PyType_GetModuleByDef() must only be called on a heap type created
|
if(!_PyType_HasFeature((PyTypeObject *)super, Py_TPFLAGS_HEAPTYPE)) {
|
||||||
// by PyType_FromModuleAndSpec() or on its subclasses.
|
// Static types in the MRO need to be skipped
|
||||||
// type_ready_mro() ensures that a static type cannot inherit from a
|
continue;
|
||||||
// heap type.
|
}
|
||||||
assert(_PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE));
|
|
||||||
|
|
||||||
PyHeapTypeObject *ht = (PyHeapTypeObject*)super;
|
PyHeapTypeObject *ht = (PyHeapTypeObject*)super;
|
||||||
PyObject *module = ht->ht_module;
|
PyObject *module = ht->ht_module;
|
||||||
|
|
Loading…
Reference in New Issue