Skip to content

Commit 401272e

Browse files
author
Erlend Egeberg Aasland
authored
bpo-42064: Adapt sqlite3 to multi-phase init (PEP 489) (GH-29234)
1 parent 454cdb9 commit 401272e

File tree

2 files changed

+101
-20
lines changed

2 files changed

+101
-20
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Convert :mod:`sqlite3` to multi-phase initialisation (PEP 489). Patches by
2+
Erlend E. Aasland.

Modules/_sqlite/module.c

Lines changed: 99 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -415,12 +415,75 @@ add_integer_constants(PyObject *module) {
415415
return 0;
416416
}
417417

418-
struct PyModuleDef _sqlite3module = {
419-
.m_base = PyModuleDef_HEAD_INIT,
420-
.m_name = "_sqlite3",
421-
.m_size = sizeof(pysqlite_state),
422-
.m_methods = module_methods,
423-
};
418+
static int
419+
module_traverse(PyObject *module, visitproc visit, void *arg)
420+
{
421+
pysqlite_state *state = pysqlite_get_state(module);
422+
423+
// Exceptions
424+
Py_VISIT(state->DataError);
425+
Py_VISIT(state->DatabaseError);
426+
Py_VISIT(state->Error);
427+
Py_VISIT(state->IntegrityError);
428+
Py_VISIT(state->InterfaceError);
429+
Py_VISIT(state->InternalError);
430+
Py_VISIT(state->NotSupportedError);
431+
Py_VISIT(state->OperationalError);
432+
Py_VISIT(state->ProgrammingError);
433+
Py_VISIT(state->Warning);
434+
435+
// Types
436+
Py_VISIT(state->ConnectionType);
437+
Py_VISIT(state->CursorType);
438+
Py_VISIT(state->PrepareProtocolType);
439+
Py_VISIT(state->RowType);
440+
Py_VISIT(state->StatementType);
441+
442+
// Misc
443+
Py_VISIT(state->converters);
444+
Py_VISIT(state->lru_cache);
445+
Py_VISIT(state->psyco_adapters);
446+
447+
return 0;
448+
}
449+
450+
static int
451+
module_clear(PyObject *module)
452+
{
453+
pysqlite_state *state = pysqlite_get_state(module);
454+
455+
// Exceptions
456+
Py_CLEAR(state->DataError);
457+
Py_CLEAR(state->DatabaseError);
458+
Py_CLEAR(state->Error);
459+
Py_CLEAR(state->IntegrityError);
460+
Py_CLEAR(state->InterfaceError);
461+
Py_CLEAR(state->InternalError);
462+
Py_CLEAR(state->NotSupportedError);
463+
Py_CLEAR(state->OperationalError);
464+
Py_CLEAR(state->ProgrammingError);
465+
Py_CLEAR(state->Warning);
466+
467+
// Types
468+
Py_CLEAR(state->ConnectionType);
469+
Py_CLEAR(state->CursorType);
470+
Py_CLEAR(state->PrepareProtocolType);
471+
Py_CLEAR(state->RowType);
472+
Py_CLEAR(state->StatementType);
473+
474+
// Misc
475+
Py_CLEAR(state->converters);
476+
Py_CLEAR(state->lru_cache);
477+
Py_CLEAR(state->psyco_adapters);
478+
479+
return 0;
480+
}
481+
482+
static void
483+
module_free(void *module)
484+
{
485+
module_clear((PyObject *)module);
486+
}
424487

425488
#define ADD_TYPE(module, type) \
426489
do { \
@@ -438,26 +501,21 @@ do { \
438501
ADD_TYPE(module, (PyTypeObject *)state->exc); \
439502
} while (0)
440503

441-
PyMODINIT_FUNC PyInit__sqlite3(void)
504+
static int
505+
module_exec(PyObject *module)
442506
{
443-
PyObject *module;
444-
445507
if (sqlite3_libversion_number() < 3007015) {
446508
PyErr_SetString(PyExc_ImportError, MODULE_NAME ": SQLite 3.7.15 or higher required");
447-
return NULL;
509+
return -1;
448510
}
449511

450512
int rc = sqlite3_initialize();
451513
if (rc != SQLITE_OK) {
452514
PyErr_SetString(PyExc_ImportError, sqlite3_errstr(rc));
453-
return NULL;
515+
return -1;
454516
}
455517

456-
module = PyModule_Create(&_sqlite3module);
457-
pysqlite_state *state = pysqlite_get_state(module);
458-
459-
if (!module ||
460-
(pysqlite_row_setup_types(module) < 0) ||
518+
if ((pysqlite_row_setup_types(module) < 0) ||
461519
(pysqlite_cursor_setup_types(module) < 0) ||
462520
(pysqlite_connection_setup_types(module) < 0) ||
463521
(pysqlite_statement_setup_types(module) < 0) ||
@@ -466,6 +524,7 @@ PyMODINIT_FUNC PyInit__sqlite3(void)
466524
goto error;
467525
}
468526

527+
pysqlite_state *state = pysqlite_get_state(module);
469528
ADD_TYPE(module, state->ConnectionType);
470529
ADD_TYPE(module, state->CursorType);
471530
ADD_TYPE(module, state->PrepareProtocolType);
@@ -519,11 +578,31 @@ PyMODINIT_FUNC PyInit__sqlite3(void)
519578
goto error;
520579
}
521580

522-
return module;
581+
return 0;
523582

524583
error:
525584
sqlite3_shutdown();
526-
PyErr_SetString(PyExc_ImportError, MODULE_NAME ": init failed");
527-
Py_XDECREF(module);
528-
return NULL;
585+
return -1;
586+
}
587+
588+
static struct PyModuleDef_Slot module_slots[] = {
589+
{Py_mod_exec, module_exec},
590+
{0, NULL},
591+
};
592+
593+
struct PyModuleDef _sqlite3module = {
594+
.m_base = PyModuleDef_HEAD_INIT,
595+
.m_name = "_sqlite3",
596+
.m_size = sizeof(pysqlite_state),
597+
.m_methods = module_methods,
598+
.m_slots = module_slots,
599+
.m_traverse = module_traverse,
600+
.m_clear = module_clear,
601+
.m_free = module_free,
602+
};
603+
604+
PyMODINIT_FUNC
605+
PyInit__sqlite3(void)
606+
{
607+
return PyModuleDef_Init(&_sqlite3module);
529608
}

0 commit comments

Comments
 (0)