gh-103968: Deprecate creating heap types whose metaclass has custom tp_new. (GH-103972)

(That's a mouthful of an edge case!)

Co-authored-by: Barney Gale <barney.gale@gmail.com>
This commit is contained in:
Petr Viktorin 2023-05-03 15:17:14 +02:00 • committed by GitHub
parent 423d7faeb3
commit 524a7f77fd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 106 additions and 12 deletions

View file

@ -3950,9 +3950,10 @@ check_basicsize_includes_size_and_offsets(PyTypeObject* type)
return 1;
}
PyObject *
PyType_FromMetaclass(PyTypeObject *metaclass, PyObject *module,
PyType_Spec *spec, PyObject *bases_in)
static PyObject *
_PyType_FromMetaclass_impl(
PyTypeObject *metaclass, PyObject *module,
PyType_Spec *spec, PyObject *bases_in, int _allow_tp_new)
{
/* Invariant: A non-NULL value in one of these means this function holds
* a strong reference or owns allocated memory.
@ -4127,9 +4128,21 @@ PyType_FromMetaclass(PyTypeObject *metaclass, PyObject *module,
goto finally;
}
if (metaclass->tp_new != PyType_Type.tp_new) {
PyErr_SetString(PyExc_TypeError,
"Metaclasses with custom tp_new are not supported.");
goto finally;
if (_allow_tp_new) {
if (PyErr_WarnFormat(
PyExc_DeprecationWarning, 1,
"Using PyType_Spec with metaclasses that have custom "
"tp_new is deprecated and will no longer be allowed in "
"Python 3.14.") < 0) {
goto finally;
}
}
else {
PyErr_SetString(
PyExc_TypeError,
"Metaclasses with custom tp_new are not supported.");
goto finally;
}
}
/* Calculate best base, and check that all bases are type objects */
@ -4316,22 +4329,29 @@ PyType_FromMetaclass(PyTypeObject *metaclass, PyObject *module,
return (PyObject*)res;
}
PyObject *
PyType_FromMetaclass(PyTypeObject *metaclass, PyObject *module,
PyType_Spec *spec, PyObject *bases_in)
{
return _PyType_FromMetaclass_impl(metaclass, module, spec, bases_in, 0);
}
PyObject *
PyType_FromModuleAndSpec(PyObject *module, PyType_Spec *spec, PyObject *bases)
{
return PyType_FromMetaclass(NULL, module, spec, bases);
return _PyType_FromMetaclass_impl(NULL, module, spec, bases, 1);
}
PyObject *
PyType_FromSpecWithBases(PyType_Spec *spec, PyObject *bases)
{
return PyType_FromMetaclass(NULL, NULL, spec, bases);
return _PyType_FromMetaclass_impl(NULL, NULL, spec, bases, 1);
}
PyObject *
PyType_FromSpec(PyType_Spec *spec)
{
return PyType_FromMetaclass(NULL, NULL, spec, NULL);
return _PyType_FromMetaclass_impl(NULL, NULL, spec, NULL, 1);
}
PyObject *