8000 gh-89546: Clean up PyType_FromMetaclass by encukou · Pull Request #93686 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

gh-89546: Clean up PyType_FromMetaclass #93686

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 19 commits into from
Jun 14, 2022
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Prepare the type names early
  • Loading branch information
encukou committed Jun 10, 2022
commit 9fb6b1109e03444d494d643982a62c0dee4ea4d5
81 changes: 49 additions & 32 deletions Objects/typeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -3407,6 +3407,8 @@ PyType_FromMetaclass(PyTypeObject *metaclass, PyObject *module,
PyTypeObject *type;
PyObject *bases = NULL;
char *tp_doc = NULL;
PyObject *ht_name = NULL;
char *_ht_tpname = NULL;
int r;

const PyType_Slot *slot;
Expand Down Expand Up @@ -3478,12 +3480,43 @@ PyType_FromMetaclass(PyTypeObject *metaclass, PyObject *module,
}
}

/* Prepare the type name and qualname */

if (spec->name == NULL) {
PyErr_SetString(PyExc_SystemError,
"Type spec does not define the name field.");
goto finally;
}

const char *s = strrchr(spec->name, '.');
if (s == NULL) {
s = spec->name;
}
else {
s++;
}

ht_name = PyUnicode_FromString(s);
if (!ht_name) {
goto finally;
}

/* Copy spec->name to a buffer we own.
*
* Unfortunately, we can't use tp_name directly (with some
* flag saying that it should be deallocated with the type),
* because tp_name is public API and may be set independently
* of any such flag.
* So, we use a separate buffer, _ht_tpname, that's always
* deallocated with the type (if it's non-NULL).
*/
Py_ssize_t name_buf_len = strlen(spec->name) + 1;
_ht_tpname = PyMem_Malloc(name_buf_len);
if (_ht_tpname == NULL) {
goto finally;
}
memcpy(_ht_tpname, spec->name, name_buf_len);

/* Get a tuple of bases.
* bases is a strong reference (unlike bases_in).
*/
Expand Down Expand Up @@ -3534,58 +3567,40 @@ PyType_FromMetaclass(PyTypeObject *metaclass, PyObject *module,
/* The flags must be initialized early, before the GC traverses us */
type->tp_flags = spec->flags | Py_TPFLAGS_HEAPTYPE;

/* Set the type name and qualname */
const char *s = strrchr(spec->name, '.');
if (s == NULL) {
s = spec->name;
}
else {
s++;
}

res->ht_name = PyUnicode_FromString(s);
if (!res->ht_name) {
goto finally;
}
res->ht_qualname = Py_NewRef(res->ht_name);

/* Copy spec->name to a buffer we own.
*
* Unfortunately, we can't use tp_name directly (with some
* flag saying that it should be deallocated with the type),
* because tp_name is public API and may be set independently
* of any such flag.
* So, we use a separate buffer, _ht_tpname, that's always
* deallocated with the type (if it's non-NULL).
*/
Py_ssize_t name_buf_len = strlen(spec->name) + 1;
res->_ht_tpname = PyMem_Malloc(name_buf_len);
if (res->_ht_tpname == NULL) {
goto finally;
}
type->tp_name = memcpy(res->_ht_tpname, spec->name, name_buf_len);

res->ht_module = Py_XNewRef(module);

/* Initialize essential fields */

type->tp_as_async = &res->as_async;
type->tp_as_number = &res->as_number;
type->tp_as_sequence = &res->as_sequence;
type->tp_as_mapping = &res->as_mapping;
type->tp_as_buffer = &res->as_buffer;

/* Set tp_base and tp_bases */
/* Set slots we have prepared */

type->tp_base = (PyTypeObject *)Py_NewRef(base);
type->tp_bases = bases;
bases = NULL; // We give our reference to bases to the type

type->tp_doc = tp_doc;
tp_doc = NULL; // Give ownership of the allocated memory to the type

res->ht_qualname = Py_NewRef(ht_name);
res->ht_name = ht_name;
ht_name = NULL; // Give our reference to to the type

type->tp_name = _ht_tpname;
res->_ht_tpname = _ht_tpname;
_ht_tpname = NULL; // Give ownership to to the type

/* Copy the sizes */

type->tp_basicsize = spec->basicsize;
type->tp_itemsize = spec->itemsize;

/* Copy all the ordinary slots */

for (slot = spec->slots; slot->slot; slot++) {
switch (slot->slot) {
case Py_tp_base:
Expand Down Expand Up @@ -3692,6 +3707,8 @@ PyType_FromMetaclass(PyTypeObject *metaclass, PyObject *module,
Py_XDECREF(bases);
Py_XDECREF(modname);
PyObject_Free(tp_doc);
Py_XDECREF(ht_name);
PyMem_Free(_ht_tpname);
return (PyObject*)res;
}

Expand Down
0