Merging upstream changes to allow compiling python3.13 wheels

This commit is contained in:
laggykiller 2025-02-09 22:52:57 +08:00
parent 70f0118baf
commit 8ea48ee2ad
No known key found for this signature in database
19 changed files with 639 additions and 478 deletions

View file

@ -24,13 +24,15 @@ int pysqlite_blob_init(pysqlite_Blob *self, pysqlite_Connection* connection,
static void remove_blob_from_connection_blob_list(pysqlite_Blob *self)
{
Py_ssize_t i;
PyObject *item;
PyObject *item, *ref;
for (i = 0; i < PyList_GET_SIZE(self->connection->blobs); i++) {
item = PyList_GET_ITEM(self->connection->blobs, i);
if (PyWeakref_GetObject(item) == (PyObject *)self) {
PyList_SetSlice(self->connection->blobs, i, i+1, NULL);
break;
if (PyWeakref_GetRef(item, &ref) == 1) {
if (ref == (PyObject *)self) {
PyList_SetSlice(self->connection->blobs, i, i+1, NULL);
break;
}
}
}
}
@ -649,4 +651,4 @@ extern int pysqlite_blob_setup_types(void)
{
pysqlite_BlobType.tp_new = PyType_GenericNew;
return PyType_Ready(&pysqlite_BlobType);
}
}

View file

@ -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);
}
}

View file

@ -90,6 +90,7 @@ typedef struct
PyObject* function_pinboard_trace_callback;
PyObject* function_pinboard_progress_handler;
PyObject* function_pinboard_authorizer_cb;
PyObject* function_pinboard_busy_handler_cb;
/* a dictionary of registered collation name => collation callable mappings */
PyObject* collations;

View file

@ -536,7 +536,7 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* args)
}
if (pysqlite_build_row_cast_map(self) != 0) {
_PyErr_FormatFromCause(pysqlite_OperationalError, "Error while building row_cast_map");
PyErr_Format(pysqlite_OperationalError, "Error while building row_cast_map");
goto error;
}

View file

@ -41,8 +41,6 @@ pysqlite_row_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
assert(type != NULL && type->tp_alloc != NULL);
if (!_PyArg_NoKeywords("Row", kwargs))
return NULL;
if (!PyArg_ParseTuple(args, "OO", &cursor, &data))
return NULL;

View file

@ -157,9 +157,15 @@ _pysqlite_long_as_int64(PyObject * py_val)
}
else if (sizeof(value) < sizeof(sqlite_int64)) {
sqlite_int64 int64val;
#if PY_VERSION_HEX < 0x030D0000
if (_PyLong_AsByteArray((PyLongObject *)py_val,
(unsigned char *)&int64val, sizeof(int64val),
IS_LITTLE_ENDIAN, 1 /* signed */) >= 0) {
#else
if (_PyLong_AsByteArray((PyLongObject *)py_val,
(unsigned char *)&int64val, sizeof(int64val),
IS_LITTLE_ENDIAN, 1 /* signed */, 1) >= 0) {
#endif
return int64val;
}
}

View file

@ -39,4 +39,46 @@ int _pysqlite_seterror(sqlite3* db);
sqlite_int64 _pysqlite_long_as_int64(PyObject * value);
#ifndef _Py_CAST
# define _Py_CAST(type, expr) ((type)(expr))
#endif
// Cast argument to PyObject* type.
#ifndef _PyObject_CAST
# define _PyObject_CAST(op) _Py_CAST(PyObject*, op)
#endif
#if PY_VERSION_HEX < 0x030A00A3 && !defined(Py_NewRef)
static inline PyObject* _Py_NewRef(PyObject *obj)
{
Py_INCREF(obj);
return obj;
}
#define Py_NewRef(obj) _Py_NewRef(_PyObject_CAST(obj))
#endif
#if PY_VERSION_HEX < 0x030D0000
static inline int PyWeakref_GetRef(PyObject *ref, PyObject **pobj)
{
PyObject *obj;
if (ref != NULL && !PyWeakref_Check(ref)) {
*pobj = NULL;
PyErr_SetString(PyExc_TypeError, "expected a weakref");
return -1;
}
obj = PyWeakref_GetObject(ref);
if (obj == NULL) {
// SystemError if ref is NULL
*pobj = NULL;
return -1;
}
if (obj == Py_None) {
*pobj = NULL;
return 0;
}
*pobj = Py_NewRef(obj);
return (*pobj != NULL);
}
#endif
#endif