From 9031bd4fa42dbb0f25aee9286154ad4bf60df3f8 Mon Sep 17 00:00:00 2001 From: Erlend Egeberg Aasland Date: Thu, 1 Oct 2020 15:24:31 +0200 Subject: [PATCH] bpo-41861: Convert _sqlite3 RowType and StatementType to heap types (GH-22444) --- Modules/_sqlite/cache.c | 4 +- Modules/_sqlite/connection.c | 2 +- Modules/_sqlite/cursor.c | 2 +- Modules/_sqlite/module.c | 6 +- Modules/_sqlite/prepare_protocol.c | 2 +- Modules/_sqlite/row.c | 96 ++++++++++-------------------- Modules/_sqlite/row.h | 4 +- Modules/_sqlite/statement.c | 71 +++++++++------------- Modules/_sqlite/statement.h | 4 +- 9 files changed, 72 insertions(+), 119 deletions(-) diff --git a/Modules/_sqlite/cache.c b/Modules/_sqlite/cache.c index c417ce872d3..0b02be4f0be 100644 --- a/Modules/_sqlite/cache.c +++ b/Modules/_sqlite/cache.c @@ -267,7 +267,7 @@ static PyType_Slot pysqlite_NodeType_slots[] = { static PyType_Spec pysqlite_NodeType_spec = { .name = MODULE_NAME ".Node", .basicsize = sizeof(pysqlite_Node), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HEAPTYPE, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, .slots = pysqlite_NodeType_slots, }; PyTypeObject *pysqlite_NodeType = NULL; @@ -291,7 +291,7 @@ static PyType_Slot pysqlite_CacheType_slots[] = { static PyType_Spec pysqlite_CacheType_spec = { .name = MODULE_NAME ".Cache", .basicsize = sizeof(pysqlite_Cache), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HEAPTYPE, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, .slots = pysqlite_CacheType_slots, }; PyTypeObject *pysqlite_CacheType = NULL; diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index 121850ae7e1..91e9046f50c 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -1234,7 +1234,7 @@ PyObject* pysqlite_connection_call(pysqlite_Connection* self, PyObject* args, Py _pysqlite_drop_unused_statement_references(self); - statement = PyObject_New(pysqlite_Statement, &pysqlite_StatementType); + statement = PyObject_New(pysqlite_Statement, pysqlite_StatementType); if (!statement) { return NULL; } diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c index 5cfb4b97d61..dbbdb12cadd 100644 --- a/Modules/_sqlite/cursor.c +++ b/Modules/_sqlite/cursor.c @@ -472,7 +472,7 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* args) if (self->statement->in_use) { Py_SETREF(self->statement, - PyObject_New(pysqlite_Statement, &pysqlite_StatementType)); + PyObject_New(pysqlite_Statement, pysqlite_StatementType)); if (!self->statement) { goto error; } diff --git a/Modules/_sqlite/module.c b/Modules/_sqlite/module.c index d0a546c008d..8ac9ea84773 100644 --- a/Modules/_sqlite/module.c +++ b/Modules/_sqlite/module.c @@ -352,11 +352,11 @@ PyMODINIT_FUNC PyInit__sqlite3(void) module = PyModule_Create(&_sqlite3module); if (!module || - (pysqlite_row_setup_types() < 0) || + (pysqlite_row_setup_types(module) < 0) || (pysqlite_cursor_setup_types() < 0) || (pysqlite_connection_setup_types() < 0) || (pysqlite_cache_setup_types(module) < 0) || - (pysqlite_statement_setup_types() < 0) || + (pysqlite_statement_setup_types(module) < 0) || (pysqlite_prepare_protocol_setup_types(module) < 0) ) { Py_XDECREF(module); @@ -366,7 +366,7 @@ PyMODINIT_FUNC PyInit__sqlite3(void) ADD_TYPE(module, pysqlite_ConnectionType); ADD_TYPE(module, pysqlite_CursorType); ADD_TYPE(module, *pysqlite_PrepareProtocolType); - ADD_TYPE(module, pysqlite_RowType); + ADD_TYPE(module, *pysqlite_RowType); if (!(dict = PyModule_GetDict(module))) { goto error; diff --git a/Modules/_sqlite/prepare_protocol.c b/Modules/_sqlite/prepare_protocol.c index 7daf8a62009..089d66b9810 100644 --- a/Modules/_sqlite/prepare_protocol.c +++ b/Modules/_sqlite/prepare_protocol.c @@ -46,7 +46,7 @@ static PyType_Slot type_slots[] = { static PyType_Spec type_spec = { .name = MODULE_NAME ".PrepareProtocol", .basicsize = sizeof(pysqlite_PrepareProtocol), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE, + .flags = Py_TPFLAGS_DEFAULT, .slots = type_slots, }; diff --git a/Modules/_sqlite/row.c b/Modules/_sqlite/row.c index 4b47108278a..85179e7f4df 100644 --- a/Modules/_sqlite/row.c +++ b/Modules/_sqlite/row.c @@ -26,10 +26,13 @@ void pysqlite_row_dealloc(pysqlite_Row* self) { + PyTypeObject *tp = Py_TYPE(self); + Py_XDECREF(self->data); Py_XDECREF(self->description); - Py_TYPE(self)->tp_free((PyObject*)self); + tp->tp_free(self); + Py_DECREF(tp); } static PyObject * @@ -192,7 +195,7 @@ static PyObject* pysqlite_row_richcompare(pysqlite_Row *self, PyObject *_other, if (opid != Py_EQ && opid != Py_NE) Py_RETURN_NOTIMPLEMENTED; - if (PyObject_TypeCheck(_other, &pysqlite_RowType)) { + if (PyObject_TypeCheck(_other, pysqlite_RowType)) { pysqlite_Row *other = (pysqlite_Row *)_other; int eq = PyObject_RichCompareBool(self->description, other->description, Py_EQ); if (eq < 0) { @@ -206,73 +209,40 @@ static PyObject* pysqlite_row_richcompare(pysqlite_Row *self, PyObject *_other, Py_RETURN_NOTIMPLEMENTED; } -PyMappingMethods pysqlite_row_as_mapping = { - /* mp_length */ (lenfunc)pysqlite_row_length, - /* mp_subscript */ (binaryfunc)pysqlite_row_subscript, - /* mp_ass_subscript */ (objobjargproc)0, -}; - -static PySequenceMethods pysqlite_row_as_sequence = { - /* sq_length */ (lenfunc)pysqlite_row_length, - /* sq_concat */ 0, - /* sq_repeat */ 0, - /* sq_item */ (ssizeargfunc)pysqlite_row_item, -}; - - -static PyMethodDef pysqlite_row_methods[] = { +static PyMethodDef row_methods[] = { {"keys", (PyCFunction)pysqlite_row_keys, METH_NOARGS, PyDoc_STR("Returns the keys of the row.")}, {NULL, NULL} }; - -PyTypeObject pysqlite_RowType = { - PyVarObject_HEAD_INIT(NULL, 0) - MODULE_NAME ".Row", /* tp_name */ - sizeof(pysqlite_Row), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)pysqlite_row_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - (hashfunc)pysqlite_row_hash, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */ - 0, /* tp_doc */ - (traverseproc)0, /* tp_traverse */ - 0, /* tp_clear */ - (richcmpfunc)pysqlite_row_richcompare, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - (getiterfunc)pysqlite_iter, /* tp_iter */ - 0, /* tp_iternext */ - pysqlite_row_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ - 0 /* tp_free */ +static PyType_Slot row_slots[] = { + {Py_tp_dealloc, pysqlite_row_dealloc}, + {Py_tp_hash, pysqlite_row_hash}, + {Py_tp_methods, row_methods}, + {Py_tp_richcompare, pysqlite_row_richcompare}, + {Py_tp_iter, pysqlite_iter}, + {Py_mp_length, pysqlite_row_length}, + {Py_mp_subscript, pysqlite_row_subscript}, + {Py_sq_length, pysqlite_row_length}, + {Py_sq_item, pysqlite_row_item}, + {Py_tp_new, pysqlite_row_new}, + {0, NULL}, }; -extern int pysqlite_row_setup_types(void) +static PyType_Spec row_spec = { + .name = MODULE_NAME ".Row", + .basicsize = sizeof(pysqlite_Row), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .slots = row_slots, +}; + +PyTypeObject *pysqlite_RowType = NULL; + +extern int pysqlite_row_setup_types(PyObject *module) { - pysqlite_RowType.tp_new = pysqlite_row_new; - pysqlite_RowType.tp_as_mapping = &pysqlite_row_as_mapping; - pysqlite_RowType.tp_as_sequence = &pysqlite_row_as_sequence; - return PyType_Ready(&pysqlite_RowType); + pysqlite_RowType = (PyTypeObject *)PyType_FromModuleAndSpec(module, &row_spec, NULL); + if (pysqlite_RowType == NULL) { + return -1; + } + return 0; } diff --git a/Modules/_sqlite/row.h b/Modules/_sqlite/row.h index 4ad506f8dd9..2dac41e89e1 100644 --- a/Modules/_sqlite/row.h +++ b/Modules/_sqlite/row.h @@ -33,8 +33,8 @@ typedef struct _Row PyObject* description; } pysqlite_Row; -extern PyTypeObject pysqlite_RowType; +extern PyTypeObject *pysqlite_RowType; -int pysqlite_row_setup_types(void); +int pysqlite_row_setup_types(PyObject *module); #endif diff --git a/Modules/_sqlite/statement.c b/Modules/_sqlite/statement.c index 0458e1171eb..4682d286c58 100644 --- a/Modules/_sqlite/statement.c +++ b/Modules/_sqlite/statement.c @@ -371,6 +371,8 @@ void pysqlite_statement_mark_dirty(pysqlite_Statement* self) void pysqlite_statement_dealloc(pysqlite_Statement* self) { + PyTypeObject *tp = Py_TYPE(self); + if (self->st) { Py_BEGIN_ALLOW_THREADS sqlite3_finalize(self->st); @@ -385,7 +387,8 @@ void pysqlite_statement_dealloc(pysqlite_Statement* self) PyObject_ClearWeakRefs((PyObject*)self); } - Py_TYPE(self)->tp_free((PyObject*)self); + tp->tp_free(self); + Py_DECREF(tp); } /* @@ -458,50 +461,30 @@ static int pysqlite_check_remaining_sql(const char* tail) return 0; } -PyTypeObject pysqlite_StatementType = { - PyVarObject_HEAD_INIT(NULL, 0) - MODULE_NAME ".Statement", /* tp_name */ - sizeof(pysqlite_Statement), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)pysqlite_statement_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - 0, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - offsetof(pysqlite_Statement, in_weakreflist), /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ - 0 /* tp_free */ +static PyMemberDef stmt_members[] = { + {"__weaklistoffset__", T_PYSSIZET, offsetof(pysqlite_Statement, in_weakreflist), READONLY}, + {NULL}, +}; +static PyType_Slot stmt_slots[] = { + {Py_tp_members, stmt_members}, + {Py_tp_dealloc, pysqlite_statement_dealloc}, + {Py_tp_new, PyType_GenericNew}, + {0, NULL}, }; -extern int pysqlite_statement_setup_types(void) +static PyType_Spec stmt_spec = { + .name = MODULE_NAME ".Statement", + .basicsize = sizeof(pysqlite_Statement), + .flags = Py_TPFLAGS_DEFAULT, + .slots = stmt_slots, +}; +PyTypeObject *pysqlite_StatementType = NULL; + +extern int pysqlite_statement_setup_types(PyObject *module) { - pysqlite_StatementType.tp_new = PyType_GenericNew; - return PyType_Ready(&pysqlite_StatementType); + pysqlite_StatementType = (PyTypeObject *)PyType_FromModuleAndSpec(module, &stmt_spec, NULL); + if (pysqlite_StatementType == NULL) { + return -1; + } + return 0; } diff --git a/Modules/_sqlite/statement.h b/Modules/_sqlite/statement.h index 5002f02dc5b..b4260360028 100644 --- a/Modules/_sqlite/statement.h +++ b/Modules/_sqlite/statement.h @@ -43,7 +43,7 @@ typedef struct PyObject* in_weakreflist; /* List of weak references */ } pysqlite_Statement; -extern PyTypeObject pysqlite_StatementType; +extern PyTypeObject *pysqlite_StatementType; int pysqlite_statement_create(pysqlite_Statement* self, pysqlite_Connection* connection, PyObject* sql); void pysqlite_statement_dealloc(pysqlite_Statement* self); @@ -55,6 +55,6 @@ int pysqlite_statement_finalize(pysqlite_Statement* self); int pysqlite_statement_reset(pysqlite_Statement* self); void pysqlite_statement_mark_dirty(pysqlite_Statement* self); -int pysqlite_statement_setup_types(void); +int pysqlite_statement_setup_types(PyObject *module); #endif