Merging upstream changes to allow compiling python3.13 wheels
This commit is contained in:
parent
70f0118baf
commit
8ea48ee2ad
19 changed files with 639 additions and 478 deletions
217
src/connection.c
217
src/connection.c
|
|
@ -56,6 +56,10 @@
|
|||
#define HAVE_ENCRYPTION
|
||||
#endif
|
||||
|
||||
#if PY_VERSION_HEX < 0x030D0000
|
||||
#define PyLong_AsInt _PyLong_AsInt
|
||||
#endif
|
||||
|
||||
_Py_IDENTIFIER(cursor);
|
||||
|
||||
static const char * const begin_statements[] = {
|
||||
|
|
@ -199,6 +203,7 @@ int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject
|
|||
self->function_pinboard_trace_callback = NULL;
|
||||
self->function_pinboard_progress_handler = NULL;
|
||||
self->function_pinboard_authorizer_cb = NULL;
|
||||
self->function_pinboard_busy_handler_cb = NULL;
|
||||
|
||||
Py_XSETREF(self->collations, PyDict_New());
|
||||
if (!self->collations) {
|
||||
|
|
@ -229,9 +234,7 @@ void pysqlite_do_all_statements(pysqlite_Connection* self, int action, int reset
|
|||
|
||||
for (i = 0; i < PyList_Size(self->statements); i++) {
|
||||
weakref = PyList_GetItem(self->statements, i);
|
||||
statement = PyWeakref_GetObject(weakref);
|
||||
if (statement != Py_None) {
|
||||
Py_INCREF(statement);
|
||||
if (PyWeakref_GetRef(weakref, &statement) == 1) {
|
||||
if (action == ACTION_RESET) {
|
||||
(void)pysqlite_statement_reset((pysqlite_Statement*)statement);
|
||||
} else {
|
||||
|
|
@ -244,9 +247,9 @@ void pysqlite_do_all_statements(pysqlite_Connection* self, int action, int reset
|
|||
if (reset_cursors) {
|
||||
for (i = 0; i < PyList_Size(self->cursors); i++) {
|
||||
weakref = PyList_GetItem(self->cursors, i);
|
||||
cursor = (pysqlite_Cursor*)PyWeakref_GetObject(weakref);
|
||||
if ((PyObject*)cursor != Py_None) {
|
||||
if (PyWeakref_GetRef(weakref, (PyObject**)&cursor) == 1) {
|
||||
cursor->reset = 1;
|
||||
Py_DECREF(cursor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -265,6 +268,7 @@ void pysqlite_connection_dealloc(pysqlite_Connection* self)
|
|||
Py_XDECREF(self->function_pinboard_trace_callback);
|
||||
Py_XDECREF(self->function_pinboard_progress_handler);
|
||||
Py_XDECREF(self->function_pinboard_authorizer_cb);
|
||||
Py_XDECREF(self->function_pinboard_busy_handler_cb);
|
||||
Py_XDECREF(self->row_factory);
|
||||
Py_XDECREF(self->text_factory);
|
||||
Py_XDECREF(self->collations);
|
||||
|
|
@ -412,9 +416,9 @@ static void pysqlite_close_all_blobs(pysqlite_Connection *self)
|
|||
|
||||
for (i = 0; i < PyList_GET_SIZE(self->blobs); i++) {
|
||||
weakref = PyList_GET_ITEM(self->blobs, i);
|
||||
blob = PyWeakref_GetObject(weakref);
|
||||
if (blob != Py_None) {
|
||||
if (PyWeakref_GetRef(weakref, &blob) == 1) {
|
||||
pysqlite_blob_close((pysqlite_Blob*)blob);
|
||||
Py_DECREF(blob);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -936,6 +940,7 @@ static void _pysqlite_drop_unused_statement_references(pysqlite_Connection* self
|
|||
{
|
||||
PyObject* new_list;
|
||||
PyObject* weakref;
|
||||
PyObject* ref;
|
||||
int i;
|
||||
|
||||
/* we only need to do this once in a while */
|
||||
|
|
@ -952,7 +957,8 @@ static void _pysqlite_drop_unused_statement_references(pysqlite_Connection* self
|
|||
|
||||
for (i = 0; i < PyList_Size(self->statements); i++) {
|
||||
weakref = PyList_GetItem(self->statements, i);
|
||||
if (PyWeakref_GetObject(weakref) != Py_None) {
|
||||
if (PyWeakref_GetRef(weakref, &ref) == 1) {
|
||||
Py_DECREF(ref);
|
||||
if (PyList_Append(new_list, weakref) != 0) {
|
||||
Py_DECREF(new_list);
|
||||
return;
|
||||
|
|
@ -967,6 +973,7 @@ static void _pysqlite_drop_unused_cursor_references(pysqlite_Connection* self)
|
|||
{
|
||||
PyObject* new_list;
|
||||
PyObject* weakref;
|
||||
PyObject* ref;
|
||||
int i;
|
||||
|
||||
/* we only need to do this once in a while */
|
||||
|
|
@ -983,7 +990,8 @@ static void _pysqlite_drop_unused_cursor_references(pysqlite_Connection* self)
|
|||
|
||||
for (i = 0; i < PyList_Size(self->cursors); i++) {
|
||||
weakref = PyList_GetItem(self->cursors, i);
|
||||
if (PyWeakref_GetObject(weakref) != Py_None) {
|
||||
if (PyWeakref_GetRef(weakref, &ref) == 1) {
|
||||
Py_DECREF(ref);
|
||||
if (PyList_Append(new_list, weakref) != 0) {
|
||||
Py_DECREF(new_list);
|
||||
return;
|
||||
|
|
@ -1154,7 +1162,7 @@ static int _authorizer_callback(void* user_arg, int action, const char* arg1, co
|
|||
}
|
||||
else {
|
||||
if (PyLong_Check(ret)) {
|
||||
rc = _PyLong_AsInt(ret);
|
||||
rc = PyLong_AsInt(ret);
|
||||
if (rc == -1 && PyErr_Occurred()) {
|
||||
if (_pysqlite_enable_callback_tracebacks)
|
||||
PyErr_Print();
|
||||
|
|
@ -1200,6 +1208,36 @@ static int _progress_handler(void* user_arg)
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int _busy_handler(void* user_arg, int n)
|
||||
{
|
||||
int rc;
|
||||
PyObject *ret;
|
||||
PyGILState_STATE gilstate;
|
||||
|
||||
gilstate = PyGILState_Ensure();
|
||||
ret = PyObject_CallFunction((PyObject*)user_arg, "i", n);
|
||||
|
||||
if (ret == NULL) {
|
||||
if (_pysqlite_enable_callback_tracebacks)
|
||||
PyErr_Print();
|
||||
else
|
||||
PyErr_Clear();
|
||||
|
||||
rc = 0;
|
||||
}
|
||||
else {
|
||||
if (PyLong_Check(ret))
|
||||
rc = PyLong_AsInt(ret);
|
||||
else
|
||||
rc = 0;
|
||||
|
||||
Py_DECREF(ret);
|
||||
}
|
||||
|
||||
PyGILState_Release(gilstate);
|
||||
return rc;
|
||||
}
|
||||
|
||||
#ifdef HAVE_TRACE_V2
|
||||
static int _trace_callback(unsigned int type, void *ctx, void *stmt, void *sql)
|
||||
{
|
||||
|
|
@ -1336,6 +1374,68 @@ static PyObject* pysqlite_connection_set_progress_handler(pysqlite_Connection* s
|
|||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject* pysqlite_connection_set_busy_handler(pysqlite_Connection* self, PyObject* args, PyObject* kwargs)
|
||||
{
|
||||
PyObject* busy_handler;
|
||||
|
||||
static char *kwlist[] = { "busy_handler", NULL };
|
||||
|
||||
if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:set_busy_handler",
|
||||
kwlist, &busy_handler)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int rc;
|
||||
if (busy_handler == Py_None) {
|
||||
rc = sqlite3_busy_handler(self->db, NULL, NULL);
|
||||
Py_XSETREF(self->function_pinboard_busy_handler_cb, NULL);
|
||||
}
|
||||
else {
|
||||
Py_INCREF(busy_handler);
|
||||
Py_XSETREF(self->function_pinboard_busy_handler_cb, busy_handler);
|
||||
rc = sqlite3_busy_handler(self->db, _busy_handler, (void*)busy_handler);
|
||||
}
|
||||
|
||||
if (rc != SQLITE_OK) {
|
||||
PyErr_SetString(pysqlite_OperationalError, "Error setting busy handler");
|
||||
Py_XSETREF(self->function_pinboard_busy_handler_cb, NULL);
|
||||
return NULL;
|
||||
}
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject* pysqlite_connection_set_busy_timeout(pysqlite_Connection* self, PyObject* args, PyObject* kwargs)
|
||||
{
|
||||
double busy_timeout;
|
||||
|
||||
static char *kwlist[] = { "timeout", NULL };
|
||||
|
||||
if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "d:set_busy_timeout",
|
||||
kwlist, &busy_timeout)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int rc;
|
||||
rc = sqlite3_busy_timeout(self->db, (int)busy_timeout * 1000);
|
||||
if (rc != SQLITE_OK) {
|
||||
PyErr_SetString(pysqlite_OperationalError, "Error setting busy timeout");
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
Py_XDECREF(self->function_pinboard_busy_handler_cb);
|
||||
}
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject* pysqlite_connection_set_trace_callback(pysqlite_Connection* self, PyObject* args, PyObject* kwargs)
|
||||
{
|
||||
PyObject* trace_callback;
|
||||
|
|
@ -1478,8 +1578,6 @@ pysqlite_connection_set_isolation_level(pysqlite_Connection* self, PyObject* iso
|
|||
self->begin_statement = NULL;
|
||||
} else {
|
||||
const char * const *candidate;
|
||||
PyObject *uppercase_level;
|
||||
_Py_IDENTIFIER(upper);
|
||||
|
||||
if (!PyUnicode_Check(isolation_level)) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
|
|
@ -1488,17 +1586,14 @@ pysqlite_connection_set_isolation_level(pysqlite_Connection* self, PyObject* iso
|
|||
return -1;
|
||||
}
|
||||
|
||||
uppercase_level = _PyObject_CallMethodIdObjArgs(
|
||||
(PyObject *)&PyUnicode_Type, &PyId_upper,
|
||||
isolation_level, NULL);
|
||||
if (!uppercase_level) {
|
||||
const char *level = PyUnicode_AsUTF8(isolation_level);
|
||||
if (level == NULL) {
|
||||
return -1;
|
||||
}
|
||||
for (candidate = begin_statements; *candidate; candidate++) {
|
||||
if (_PyUnicode_EqualToASCIIString(uppercase_level, *candidate + 6))
|
||||
if (sqlite3_stricmp(level, *candidate + 6) == 0)
|
||||
break;
|
||||
}
|
||||
Py_DECREF(uppercase_level);
|
||||
if (!*candidate) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"invalid value for isolation_level");
|
||||
|
|
@ -1523,9 +1618,6 @@ PyObject* pysqlite_connection_call(pysqlite_Connection* self, PyObject* args, Py
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (!_PyArg_NoKeywords(MODULE_NAME ".Connection", kwargs))
|
||||
return NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "U", &sql))
|
||||
return NULL;
|
||||
|
||||
|
|
@ -1742,35 +1834,18 @@ pysqlite_connection_backup(pysqlite_Connection *self, PyObject *args, PyObject *
|
|||
const char *name = "main";
|
||||
int rc;
|
||||
int callback_error = 0;
|
||||
PyObject *sleep_obj = NULL;
|
||||
int sleep_ms = 250;
|
||||
double sleep_s = 0.25;
|
||||
int sleep_ms = 0;
|
||||
sqlite3 *bck_conn;
|
||||
sqlite3_backup *bck_handle;
|
||||
static char *keywords[] = {"target", "pages", "progress", "name", "sleep", NULL};
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|$iOsO:backup", keywords,
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|$iOsd:backup", keywords,
|
||||
&pysqlite_ConnectionType, &target,
|
||||
&pages, &progress, &name, &sleep_obj)) {
|
||||
&pages, &progress, &name, &sleep_s)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// XXX: We use _PyTime_ROUND_CEILING to support 3.6.x, but it should
|
||||
// use _PyTime_ROUND_TIMEOUT instead.
|
||||
if (sleep_obj != NULL) {
|
||||
_PyTime_t sleep_secs;
|
||||
if (_PyTime_FromSecondsObject(&sleep_secs, sleep_obj,
|
||||
_PyTime_ROUND_CEILING)) {
|
||||
return NULL;
|
||||
}
|
||||
_PyTime_t ms = _PyTime_AsMilliseconds(sleep_secs,
|
||||
_PyTime_ROUND_CEILING);
|
||||
if (ms < INT_MIN || ms > INT_MAX) {
|
||||
PyErr_SetString(PyExc_OverflowError, "sleep is too large");
|
||||
return NULL;
|
||||
}
|
||||
sleep_ms = (int)ms;
|
||||
}
|
||||
|
||||
if (!pysqlite_check_connection((pysqlite_Connection *)target)) {
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -1779,6 +1854,11 @@ pysqlite_connection_backup(pysqlite_Connection *self, PyObject *args, PyObject *
|
|||
PyErr_SetString(PyExc_ValueError, "target cannot be the same connection instance");
|
||||
return NULL;
|
||||
}
|
||||
if (sleep_s < 0) {
|
||||
PyErr_SetString(PyExc_ValueError, "sleep must be greater-than or equal to zero");
|
||||
return NULL;
|
||||
}
|
||||
sleep_ms = (int)(sleep_s * 1000.0);
|
||||
|
||||
#if SQLITE_VERSION_NUMBER < 3008008
|
||||
/* Since 3.8.8 this is already done, per commit
|
||||
|
|
@ -1865,15 +1945,10 @@ static PyObject *
|
|||
pysqlite_connection_create_collation(pysqlite_Connection* self, PyObject* args)
|
||||
{
|
||||
PyObject* callable;
|
||||
PyObject* uppercase_name = 0;
|
||||
PyObject* name;
|
||||
PyObject* name = NULL;
|
||||
PyObject* retval;
|
||||
Py_ssize_t i, len;
|
||||
_Py_IDENTIFIER(upper);
|
||||
const char *uppercase_name_str;
|
||||
const char *name_str;
|
||||
int rc;
|
||||
unsigned int kind;
|
||||
const void *data;
|
||||
|
||||
if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) {
|
||||
goto finally;
|
||||
|
|
@ -1884,32 +1959,8 @@ pysqlite_connection_create_collation(pysqlite_Connection* self, PyObject* args)
|
|||
goto finally;
|
||||
}
|
||||
|
||||
uppercase_name = _PyObject_CallMethodIdObjArgs((PyObject *)&PyUnicode_Type,
|
||||
&PyId_upper, name, NULL);
|
||||
if (!uppercase_name) {
|
||||
goto finally;
|
||||
}
|
||||
|
||||
if (PyUnicode_READY(uppercase_name))
|
||||
goto finally;
|
||||
len = PyUnicode_GET_LENGTH(uppercase_name);
|
||||
kind = PyUnicode_KIND(uppercase_name);
|
||||
data = PyUnicode_DATA(uppercase_name);
|
||||
for (i=0; i<len; i++) {
|
||||
Py_UCS4 ch = PyUnicode_READ(kind, data, i);
|
||||
if ((ch >= '0' && ch <= '9')
|
||||
|| (ch >= 'A' && ch <= 'Z')
|
||||
|| (ch == '_'))
|
||||
{
|
||||
continue;
|
||||
} else {
|
||||
PyErr_SetString(pysqlite_ProgrammingError, "invalid character in collation name");
|
||||
goto finally;
|
||||
}
|
||||
}
|
||||
|
||||
uppercase_name_str = PyUnicode_AsUTF8(uppercase_name);
|
||||
if (!uppercase_name_str)
|
||||
name_str = PyUnicode_AsUTF8(name);
|
||||
if (!name_str)
|
||||
goto finally;
|
||||
|
||||
if (callable != Py_None && !PyCallable_Check(callable)) {
|
||||
|
|
@ -1918,27 +1969,25 @@ pysqlite_connection_create_collation(pysqlite_Connection* self, PyObject* args)
|
|||
}
|
||||
|
||||
if (callable != Py_None) {
|
||||
if (PyDict_SetItem(self->collations, uppercase_name, callable) == -1)
|
||||
if (PyDict_SetItem(self->collations, name, callable) == -1)
|
||||
goto finally;
|
||||
} else {
|
||||
if (PyDict_DelItem(self->collations, uppercase_name) == -1)
|
||||
if (PyDict_DelItem(self->collations, name) == -1)
|
||||
goto finally;
|
||||
}
|
||||
|
||||
rc = sqlite3_create_collation(self->db,
|
||||
uppercase_name_str,
|
||||
name_str,
|
||||
SQLITE_UTF8,
|
||||
(callable != Py_None) ? callable : NULL,
|
||||
(callable != Py_None) ? pysqlite_collation_callback : NULL);
|
||||
if (rc != SQLITE_OK) {
|
||||
PyDict_DelItem(self->collations, uppercase_name);
|
||||
PyDict_DelItem(self->collations, name);
|
||||
_pysqlite_seterror(self->db);
|
||||
goto finally;
|
||||
}
|
||||
|
||||
finally:
|
||||
Py_XDECREF(uppercase_name);
|
||||
|
||||
if (PyErr_Occurred()) {
|
||||
retval = NULL;
|
||||
} else {
|
||||
|
|
@ -2063,6 +2112,10 @@ static PyMethodDef connection_methods[] = {
|
|||
#endif
|
||||
{"set_authorizer", (PyCFunction)(void(*)(void))pysqlite_connection_set_authorizer, METH_VARARGS|METH_KEYWORDS,
|
||||
PyDoc_STR("Sets authorizer callback. Non-standard.")},
|
||||
{"set_busy_handler", (PyCFunction)(void(*)(void))pysqlite_connection_set_busy_handler, METH_VARARGS|METH_KEYWORDS,
|
||||
PyDoc_STR("Sets busy handler. Non-standard.")},
|
||||
{"set_busy_timeout", (PyCFunction)(void(*)(void))pysqlite_connection_set_busy_timeout, METH_VARARGS|METH_KEYWORDS,
|
||||
PyDoc_STR("Sets busy timeout. Non-standard.")},
|
||||
#ifdef HAVE_LOAD_EXTENSION
|
||||
{"enable_load_extension", (PyCFunction)pysqlite_enable_load_extension, METH_VARARGS,
|
||||
PyDoc_STR("Enable dynamic loading of SQLite extension modules. Non-standard.")},
|
||||
|
|
@ -2163,4 +2216,4 @@ extern int pysqlite_connection_setup_types(void)
|
|||
{
|
||||
pysqlite_ConnectionType.tp_new = PyType_GenericNew;
|
||||
return PyType_Ready(&pysqlite_ConnectionType);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue