Skip to content

Commit 256e54a

Browse files
author
Erlend Egeberg Aasland
authored
bpo-41861: Convert _sqlite3 CursorType and ConnectionType to heap types (GH-22478)
1 parent 9031bd4 commit 256e54a

File tree

6 files changed

+74
-102
lines changed

6 files changed

+74
-102
lines changed

Modules/_sqlite/connection.c

+33-47
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,8 @@ void pysqlite_do_all_statements(pysqlite_Connection* self, int action, int reset
220220

221221
void pysqlite_connection_dealloc(pysqlite_Connection* self)
222222
{
223+
PyTypeObject *tp = Py_TYPE(self);
224+
223225
Py_XDECREF(self->statement_cache);
224226

225227
/* Clean up if user has not called .close() explicitly. */
@@ -236,7 +238,9 @@ void pysqlite_connection_dealloc(pysqlite_Connection* self)
236238
Py_XDECREF(self->collations);
237239
Py_XDECREF(self->statements);
238240
Py_XDECREF(self->cursors);
239-
Py_TYPE(self)->tp_free((PyObject*)self);
241+
242+
tp->tp_free(self);
243+
Py_DECREF(tp);
240244
}
241245

242246
/*
@@ -281,13 +285,13 @@ PyObject* pysqlite_connection_cursor(pysqlite_Connection* self, PyObject* args,
281285
}
282286

283287
if (factory == NULL) {
284-
factory = (PyObject*)&pysqlite_CursorType;
288+
factory = (PyObject*)pysqlite_CursorType;
285289
}
286290

287291
cursor = PyObject_CallOneArg(factory, (PyObject *)self);
288292
if (cursor == NULL)
289293
return NULL;
290-
if (!PyObject_TypeCheck(cursor, &pysqlite_CursorType)) {
294+
if (!PyObject_TypeCheck(cursor, pysqlite_CursorType)) {
291295
PyErr_Format(PyExc_TypeError,
292296
"factory must return a cursor, not %.100s",
293297
Py_TYPE(cursor)->tp_name);
@@ -1494,7 +1498,7 @@ pysqlite_connection_backup(pysqlite_Connection *self, PyObject *args, PyObject *
14941498
static char *keywords[] = {"target", "pages", "progress", "name", "sleep", NULL};
14951499

14961500
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|$iOsO:backup", keywords,
1497-
&pysqlite_ConnectionType, &target,
1501+
pysqlite_ConnectionType, &target,
14981502
&pages, &progress, &name, &sleep_obj)) {
14991503
return NULL;
15001504
}
@@ -1831,50 +1835,32 @@ static struct PyMemberDef connection_members[] =
18311835
{NULL}
18321836
};
18331837

1834-
PyTypeObject pysqlite_ConnectionType = {
1835-
PyVarObject_HEAD_INIT(NULL, 0)
1836-
MODULE_NAME ".Connection", /* tp_name */
1837-
sizeof(pysqlite_Connection), /* tp_basicsize */
1838-
0, /* tp_itemsize */
1839-
(destructor)pysqlite_connection_dealloc, /* tp_dealloc */
1840-
0, /* tp_vectorcall_offset */
1841-
0, /* tp_getattr */
1842-
0, /* tp_setattr */
1843-
0, /* tp_as_async */
1844-
0, /* tp_repr */
1845-
0, /* tp_as_number */
1846-
0, /* tp_as_sequence */
1847-
0, /* tp_as_mapping */
1848-
0, /* tp_hash */
1849-
(ternaryfunc)pysqlite_connection_call, /* tp_call */
1850-
0, /* tp_str */
1851-
0, /* tp_getattro */
1852-
0, /* tp_setattro */
1853-
0, /* tp_as_buffer */
1854-
Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */
1855-
connection_doc, /* tp_doc */
1856-
0, /* tp_traverse */
1857-
0, /* tp_clear */
1858-
0, /* tp_richcompare */
1859-
0, /* tp_weaklistoffset */
1860-
0, /* tp_iter */
1861-
0, /* tp_iternext */
1862-
connection_methods, /* tp_methods */
1863-
connection_members, /* tp_members */
1864-
connection_getset, /* tp_getset */
1865-
0, /* tp_base */
1866-
0, /* tp_dict */
1867-
0, /* tp_descr_get */
1868-
0, /* tp_descr_set */
1869-
0, /* tp_dictoffset */
1870-
(initproc)pysqlite_connection_init, /* tp_init */
1871-
0, /* tp_alloc */
1872-
0, /* tp_new */
1873-
0 /* tp_free */
1838+
static PyType_Slot connection_slots[] = {
1839+
{Py_tp_dealloc, pysqlite_connection_dealloc},
1840+
{Py_tp_doc, (void *)connection_doc},
1841+
{Py_tp_methods, connection_methods},
1842+
{Py_tp_members, connection_members},
1843+
{Py_tp_getset, connection_getset},
1844+
{Py_tp_new, PyType_GenericNew},
1845+
{Py_tp_init, pysqlite_connection_init},
1846+
{Py_tp_call, pysqlite_connection_call},
1847+
{0, NULL},
1848+
};
1849+
1850+
static PyType_Spec connection_spec = {
1851+
.name = MODULE_NAME ".Connection",
1852+
.basicsize = sizeof(pysqlite_Connection),
1853+
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
1854+
.slots = connection_slots,
18741855
};
18751856

1876-
extern int pysqlite_connection_setup_types(void)
1857+
PyTypeObject *pysqlite_ConnectionType = NULL;
1858+
1859+
extern int pysqlite_connection_setup_types(PyObject *module)
18771860
{
1878-
pysqlite_ConnectionType.tp_new = PyType_GenericNew;
1879-
return PyType_Ready(&pysqlite_ConnectionType);
1861+
pysqlite_ConnectionType = (PyTypeObject *)PyType_FromModuleAndSpec(module, &connection_spec, NULL);
1862+
if (pysqlite_ConnectionType == NULL) {
1863+
return -1;
1864+
}
1865+
return 0;
18801866
}

Modules/_sqlite/connection.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ typedef struct
106106
PyObject* NotSupportedError;
107107
} pysqlite_Connection;
108108

109-
extern PyTypeObject pysqlite_ConnectionType;
109+
extern PyTypeObject *pysqlite_ConnectionType;
110110

111111
PyObject* pysqlite_connection_alloc(PyTypeObject* type, int aware);
112112
void pysqlite_connection_dealloc(pysqlite_Connection* self);
@@ -122,6 +122,6 @@ int pysqlite_connection_register_cursor(pysqlite_Connection* connection, PyObjec
122122
int pysqlite_check_thread(pysqlite_Connection* self);
123123
int pysqlite_check_connection(pysqlite_Connection* con);
124124

125-
int pysqlite_connection_setup_types(void);
125+
int pysqlite_connection_setup_types(PyObject *module);
126126

127127
#endif

Modules/_sqlite/cursor.c

+31-45
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ static int pysqlite_cursor_init(pysqlite_Cursor* self, PyObject* args, PyObject*
3333
{
3434
pysqlite_Connection* connection;
3535

36-
if (!PyArg_ParseTuple(args, "O!", &pysqlite_ConnectionType, &connection))
36+
if (!PyArg_ParseTuple(args, "O!", pysqlite_ConnectionType, &connection))
3737
{
3838
return -1;
3939
}
@@ -74,6 +74,8 @@ static int pysqlite_cursor_init(pysqlite_Cursor* self, PyObject* args, PyObject*
7474

7575
static void pysqlite_cursor_dealloc(pysqlite_Cursor* self)
7676
{
77+
PyTypeObject *tp = Py_TYPE(self);
78+
7779
/* Reset the statement if the user has not closed the cursor */
7880
if (self->statement) {
7981
pysqlite_statement_reset(self->statement);
@@ -91,7 +93,8 @@ static void pysqlite_cursor_dealloc(pysqlite_Cursor* self)
9193
PyObject_ClearWeakRefs((PyObject*)self);
9294
}
9395

94-
Py_TYPE(self)->tp_free((PyObject*)self);
96+
tp->tp_free(self);
97+
Py_DECREF(tp);
9598
}
9699

97100
static PyObject *
@@ -898,56 +901,39 @@ static struct PyMemberDef cursor_members[] =
898901
{"lastrowid", T_OBJECT, offsetof(pysqlite_Cursor, lastrowid), READONLY},
899902
{"rowcount", T_LONG, offsetof(pysqlite_Cursor, rowcount), READONLY},
900903
{"row_factory", T_OBJECT, offsetof(pysqlite_Cursor, row_factory), 0},
904+
{"__weaklistoffset__", T_PYSSIZET, offsetof(pysqlite_Cursor, in_weakreflist), READONLY},
901905
{NULL}
902906
};
903907

904908
static const char cursor_doc[] =
905909
PyDoc_STR("SQLite database cursor class.");
906910

907-
PyTypeObject pysqlite_CursorType = {
908-
PyVarObject_HEAD_INIT(NULL, 0)
909-
MODULE_NAME ".Cursor", /* tp_name */
910-
sizeof(pysqlite_Cursor), /* tp_basicsize */
911-
0, /* tp_itemsize */
912-
(destructor)pysqlite_cursor_dealloc, /* tp_dealloc */
913-
0, /* tp_vectorcall_offset */
914-
0, /* tp_getattr */
915-
0, /* tp_setattr */
916-
0, /* tp_as_async */
917-
0, /* tp_repr */
918-
0, /* tp_as_number */
919-
0, /* tp_as_sequence */
920-
0, /* tp_as_mapping */
921-
0, /* tp_hash */
922-
0, /* tp_call */
923-
0, /* tp_str */
924-
0, /* tp_getattro */
925-
0, /* tp_setattro */
926-
0, /* tp_as_buffer */
927-
Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */
928-
cursor_doc, /* tp_doc */
929-
0, /* tp_traverse */
930-
0, /* tp_clear */
931-
0, /* tp_richcompare */
932-
offsetof(pysqlite_Cursor, in_weakreflist), /* tp_weaklistoffset */
933-
PyObject_SelfIter, /* tp_iter */
934-
(iternextfunc)pysqlite_cursor_iternext, /* tp_iternext */
935-
cursor_methods, /* tp_methods */
936-
cursor_members, /* tp_members */
937-
0, /* tp_getset */
938-
0, /* tp_base */
939-
0, /* tp_dict */
940-
0, /* tp_descr_get */
941-
0, /* tp_descr_set */
942-
0, /* tp_dictoffset */
943-
(initproc)pysqlite_cursor_init, /* tp_init */
944-
0, /* tp_alloc */
945-
0, /* tp_new */
946-
0 /* tp_free */
911+
static PyType_Slot cursor_slots[] = {
912+
{Py_tp_dealloc, pysqlite_cursor_dealloc},
913+
{Py_tp_doc, (void *)cursor_doc},
914+
{Py_tp_iter, PyObject_SelfIter},
915+
{Py_tp_iternext, pysqlite_cursor_iternext},
916+
{Py_tp_methods, cursor_methods},
917+
{Py_tp_members, cursor_members},
918+
{Py_tp_new, PyType_GenericNew},
919+
{Py_tp_init, pysqlite_cursor_init},
920+
{0, NULL},
921+
};
922+
923+
static PyType_Spec cursor_spec = {
924+
.name = MODULE_NAME ".Cursor",
925+
.basicsize = sizeof(pysqlite_Cursor),
926+
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
927+
.slots = cursor_slots,
947928
};
948929

949-
extern int pysqlite_cursor_setup_types(void)
930+
PyTypeObject *pysqlite_CursorType = NULL;
931+
932+
extern int pysqlite_cursor_setup_types(PyObject *module)
950933
{
951-
pysqlite_CursorType.tp_new = PyType_GenericNew;
952-
return PyType_Ready(&pysqlite_CursorType);
934+
pysqlite_CursorType = (PyTypeObject *)PyType_FromModuleAndSpec(module, &cursor_spec, NULL);
935+
if (pysqlite_CursorType == NULL) {
936+
return -1;
937+
}
938+
return 0;
953939
}

Modules/_sqlite/cursor.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ typedef struct
5252
PyObject* in_weakreflist; /* List of weak references */
5353
} pysqlite_Cursor;
5454

55-
extern PyTypeObject pysqlite_CursorType;
55+
extern PyTypeObject *pysqlite_CursorType;
5656

5757
PyObject* pysqlite_cursor_execute(pysqlite_Cursor* self, PyObject* args);
5858
PyObject* pysqlite_cursor_executemany(pysqlite_Cursor* self, PyObject* args);
@@ -64,7 +64,7 @@ PyObject* pysqlite_cursor_fetchall(pysqlite_Cursor* self, PyObject* args);
6464
PyObject* pysqlite_noop(pysqlite_Connection* self, PyObject* args);
6565
PyObject* pysqlite_cursor_close(pysqlite_Cursor* self, PyObject* args);
6666

67-
int pysqlite_cursor_setup_types(void);
67+
int pysqlite_cursor_setup_types(PyObject *module);
6868

6969
#define UNKNOWN (-1)
7070
#endif

Modules/_sqlite/module.c

+5-5
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ static PyObject* module_connect(PyObject* self, PyObject* args, PyObject*
8282
}
8383

8484
if (factory == NULL) {
85-
factory = (PyObject*)&pysqlite_ConnectionType;
85+
factory = (PyObject*)pysqlite_ConnectionType;
8686
}
8787

8888
if (PySys_Audit("sqlite3.connect", "O", database) < 0) {
@@ -353,8 +353,8 @@ PyMODINIT_FUNC PyInit__sqlite3(void)
353353

354354
if (!module ||
355355
(pysqlite_row_setup_types(module) < 0) ||
356-
(pysqlite_cursor_setup_types() < 0) ||
357-
(pysqlite_connection_setup_types() < 0) ||
356+
(pysqlite_cursor_setup_types(module) < 0) ||
357+
(pysqlite_connection_setup_types(module) < 0) ||
358358
(pysqlite_cache_setup_types(module) < 0) ||
359359
(pysqlite_statement_setup_types(module) < 0) ||
360360
(pysqlite_prepare_protocol_setup_types(module) < 0)
@@ -363,8 +363,8 @@ PyMODINIT_FUNC PyInit__sqlite3(void)
363363
return NULL;
364364
}
365365

366-
ADD_TYPE(module, pysqlite_ConnectionType);
367-
ADD_TYPE(module, pysqlite_CursorType);
366+
ADD_TYPE(module, *pysqlite_ConnectionType);
367+
ADD_TYPE(module, *pysqlite_CursorType);
368368
ADD_TYPE(module, *pysqlite_PrepareProtocolType);
369369
ADD_TYPE(module, *pysqlite_RowType);
370370

Modules/_sqlite/row.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ pysqlite_row_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
4949
if (!PyArg_ParseTuple(args, "OO", &cursor, &data))
5050
return NULL;
5151

52-
if (!PyObject_TypeCheck((PyObject*)cursor, &pysqlite_CursorType)) {
52+
if (!PyObject_TypeCheck((PyObject*)cursor, pysqlite_CursorType)) {
5353
PyErr_SetString(PyExc_TypeError, "instance of cursor required for first argument");
5454
return NULL;
5555
}

0 commit comments

Comments
 (0)