bpo-40956: Convert _sqlite3.Connection to Argument Clinic, part 2 (GH-23838)

This commit is contained in:
Erlend Egeberg Aasland 2020-12-27 09:32:18 +01:00 committed by GitHub
parent b02ad2458b
commit 3ccef1ca47
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 297 additions and 77 deletions

View File

@ -57,6 +57,24 @@ pysqlite_connection_close(pysqlite_Connection *self, PyObject *Py_UNUSED(ignored
return pysqlite_connection_close_impl(self); return pysqlite_connection_close_impl(self);
} }
PyDoc_STRVAR(pysqlite_connection_commit__doc__,
"commit($self, /)\n"
"--\n"
"\n"
"Commit the current transaction.");
#define PYSQLITE_CONNECTION_COMMIT_METHODDEF \
{"commit", (PyCFunction)pysqlite_connection_commit, METH_NOARGS, pysqlite_connection_commit__doc__},
static PyObject *
pysqlite_connection_commit_impl(pysqlite_Connection *self);
static PyObject *
pysqlite_connection_commit(pysqlite_Connection *self, PyObject *Py_UNUSED(ignored))
{
return pysqlite_connection_commit_impl(self);
}
PyDoc_STRVAR(pysqlite_connection_rollback__doc__, PyDoc_STRVAR(pysqlite_connection_rollback__doc__,
"rollback($self, /)\n" "rollback($self, /)\n"
"--\n" "--\n"
@ -373,6 +391,95 @@ exit:
#endif /* !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #endif /* !defined(SQLITE_OMIT_LOAD_EXTENSION) */
PyDoc_STRVAR(pysqlite_connection_execute__doc__,
"execute($self, sql, parameters=<unrepresentable>, /)\n"
"--\n"
"\n"
"Executes a SQL statement. Non-standard.");
#define PYSQLITE_CONNECTION_EXECUTE_METHODDEF \
{"execute", (PyCFunction)(void(*)(void))pysqlite_connection_execute, METH_FASTCALL, pysqlite_connection_execute__doc__},
static PyObject *
pysqlite_connection_execute_impl(pysqlite_Connection *self, PyObject *sql,
PyObject *parameters);
static PyObject *
pysqlite_connection_execute(pysqlite_Connection *self, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
PyObject *sql;
PyObject *parameters = NULL;
if (!_PyArg_CheckPositional("execute", nargs, 1, 2)) {
goto exit;
}
if (!PyUnicode_Check(args[0])) {
_PyArg_BadArgument("execute", "argument 1", "str", args[0]);
goto exit;
}
if (PyUnicode_READY(args[0]) == -1) {
goto exit;
}
sql = args[0];
if (nargs < 2) {
goto skip_optional;
}
parameters = args[1];
skip_optional:
return_value = pysqlite_connection_execute_impl(self, sql, parameters);
exit:
return return_value;
}
PyDoc_STRVAR(pysqlite_connection_executemany__doc__,
"executemany($self, sql, parameters, /)\n"
"--\n"
"\n"
"Repeatedly executes a SQL statement. Non-standard.");
#define PYSQLITE_CONNECTION_EXECUTEMANY_METHODDEF \
{"executemany", (PyCFunction)(void(*)(void))pysqlite_connection_executemany, METH_FASTCALL, pysqlite_connection_executemany__doc__},
static PyObject *
pysqlite_connection_executemany_impl(pysqlite_Connection *self,
PyObject *sql, PyObject *parameters);
static PyObject *
pysqlite_connection_executemany(pysqlite_Connection *self, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
PyObject *sql;
PyObject *parameters;
if (!_PyArg_CheckPositional("executemany", nargs, 2, 2)) {
goto exit;
}
if (!PyUnicode_Check(args[0])) {
_PyArg_BadArgument("executemany", "argument 1", "str", args[0]);
goto exit;
}
if (PyUnicode_READY(args[0]) == -1) {
goto exit;
}
sql = args[0];
parameters = args[1];
return_value = pysqlite_connection_executemany_impl(self, sql, parameters);
exit:
return return_value;
}
PyDoc_STRVAR(pysqlite_connection_executescript__doc__,
"executescript($self, sql_script, /)\n"
"--\n"
"\n"
"Executes a multiple SQL statements at once. Non-standard.");
#define PYSQLITE_CONNECTION_EXECUTESCRIPT_METHODDEF \
{"executescript", (PyCFunction)pysqlite_connection_executescript, METH_O, pysqlite_connection_executescript__doc__},
PyDoc_STRVAR(pysqlite_connection_interrupt__doc__, PyDoc_STRVAR(pysqlite_connection_interrupt__doc__,
"interrupt($self, /)\n" "interrupt($self, /)\n"
"--\n" "--\n"
@ -411,6 +518,107 @@ pysqlite_connection_iterdump(pysqlite_Connection *self, PyObject *Py_UNUSED(igno
return pysqlite_connection_iterdump_impl(self); return pysqlite_connection_iterdump_impl(self);
} }
PyDoc_STRVAR(pysqlite_connection_backup__doc__,
"backup($self, /, target=<unrepresentable>, *, pages=-1, progress=None,\n"
" name=\'main\', sleep=0.25)\n"
"--\n"
"\n"
"Makes a backup of the database. Non-standard.");
#define PYSQLITE_CONNECTION_BACKUP_METHODDEF \
{"backup", (PyCFunction)(void(*)(void))pysqlite_connection_backup, METH_FASTCALL|METH_KEYWORDS, pysqlite_connection_backup__doc__},
static PyObject *
pysqlite_connection_backup_impl(pysqlite_Connection *self,
pysqlite_Connection *target, int pages,
PyObject *progress, const char *name,
double sleep);
static PyObject *
pysqlite_connection_backup(pysqlite_Connection *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"target", "pages", "progress", "name", "sleep", NULL};
static _PyArg_Parser _parser = {NULL, _keywords, "backup", 0};
PyObject *argsbuf[5];
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
pysqlite_Connection *target = NULL;
int pages = -1;
PyObject *progress = Py_None;
const char *name = "main";
double sleep = 0.25;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
if (!args) {
goto exit;
}
if (!noptargs) {
goto skip_optional_pos;
}
if (args[0]) {
if (!PyObject_TypeCheck(args[0], pysqlite_ConnectionType)) {
_PyArg_BadArgument("backup", "argument 'target'", (pysqlite_ConnectionType)->tp_name, args[0]);
goto exit;
}
target = (pysqlite_Connection *)args[0];
if (!--noptargs) {
goto skip_optional_pos;
}
}
skip_optional_pos:
if (!noptargs) {
goto skip_optional_kwonly;
}
if (args[1]) {
pages = _PyLong_AsInt(args[1]);
if (pages == -1 && PyErr_Occurred()) {
goto exit;
}
if (!--noptargs) {
goto skip_optional_kwonly;
}
}
if (args[2]) {
progress = args[2];
if (!--noptargs) {
goto skip_optional_kwonly;
}
}
if (args[3]) {
if (!PyUnicode_Check(args[3])) {
_PyArg_BadArgument("backup", "argument 'name'", "str", args[3]);
goto exit;
}
Py_ssize_t name_length;
name = PyUnicode_AsUTF8AndSize(args[3], &name_length);
if (name == NULL) {
goto exit;
}
if (strlen(name) != (size_t)name_length) {
PyErr_SetString(PyExc_ValueError, "embedded null character");
goto exit;
}
if (!--noptargs) {
goto skip_optional_kwonly;
}
}
if (PyFloat_CheckExact(args[4])) {
sleep = PyFloat_AS_DOUBLE(args[4]);
}
else
{
sleep = PyFloat_AsDouble(args[4]);
if (sleep == -1.0 && PyErr_Occurred()) {
goto exit;
}
}
skip_optional_kwonly:
return_value = pysqlite_connection_backup_impl(self, target, pages, progress, name, sleep);
exit:
return return_value;
}
PyDoc_STRVAR(pysqlite_connection_create_collation__doc__, PyDoc_STRVAR(pysqlite_connection_create_collation__doc__,
"create_collation($self, name, callback, /)\n" "create_collation($self, name, callback, /)\n"
"--\n" "--\n"
@ -511,4 +719,4 @@ exit:
#ifndef PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF #ifndef PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF
#define PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF #define PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF
#endif /* !defined(PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF) */ #endif /* !defined(PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF) */
/*[clinic end generated code: output=eb14a52e4c682f3b input=a9049054013a1b77]*/ /*[clinic end generated code: output=7cb13d491a5970aa input=a9049054013a1b77]*/

View File

@ -407,7 +407,15 @@ error:
} }
} }
PyObject* pysqlite_connection_commit(pysqlite_Connection* self, PyObject* args) /*[clinic input]
_sqlite3.Connection.commit as pysqlite_connection_commit
Commit the current transaction.
[clinic start generated code]*/
static PyObject *
pysqlite_connection_commit_impl(pysqlite_Connection *self)
/*[clinic end generated code: output=3da45579e89407f2 input=39c12c04dda276a8]*/
{ {
int rc; int rc;
const char* tail; const char* tail;
@ -1339,89 +1347,108 @@ error:
return NULL; return NULL;
} }
PyObject* pysqlite_connection_execute(pysqlite_Connection* self, PyObject* args) /*[clinic input]
_sqlite3.Connection.execute as pysqlite_connection_execute
sql: unicode
parameters: object = NULL
/
Executes a SQL statement. Non-standard.
[clinic start generated code]*/
static PyObject *
pysqlite_connection_execute_impl(pysqlite_Connection *self, PyObject *sql,
PyObject *parameters)
/*[clinic end generated code: output=5be05ae01ee17ee4 input=fbd17c75c7140271]*/
{ {
_Py_IDENTIFIER(execute);
PyObject* cursor = 0; PyObject* cursor = 0;
PyObject* result = 0; PyObject* result = 0;
PyObject* method = 0;
cursor = _PyObject_CallMethodIdNoArgs((PyObject*)self, &PyId_cursor); cursor = _PyObject_CallMethodIdNoArgs((PyObject*)self, &PyId_cursor);
if (!cursor) { if (!cursor) {
goto error; goto error;
} }
method = PyObject_GetAttrString(cursor, "execute"); result = _PyObject_CallMethodIdObjArgs(cursor, &PyId_execute, sql, parameters, NULL);
if (!method) {
Py_CLEAR(cursor);
goto error;
}
result = PyObject_CallObject(method, args);
if (!result) { if (!result) {
Py_CLEAR(cursor); Py_CLEAR(cursor);
} }
error: error:
Py_XDECREF(result); Py_XDECREF(result);
Py_XDECREF(method);
return cursor; return cursor;
} }
PyObject* pysqlite_connection_executemany(pysqlite_Connection* self, PyObject* args) /*[clinic input]
_sqlite3.Connection.executemany as pysqlite_connection_executemany
sql: unicode
parameters: object
/
Repeatedly executes a SQL statement. Non-standard.
[clinic start generated code]*/
static PyObject *
pysqlite_connection_executemany_impl(pysqlite_Connection *self,
PyObject *sql, PyObject *parameters)
/*[clinic end generated code: output=776cd2fd20bfe71f input=4feab80659ffc82b]*/
{ {
_Py_IDENTIFIER(executemany);
PyObject* cursor = 0; PyObject* cursor = 0;
PyObject* result = 0; PyObject* result = 0;
PyObject* method = 0;
cursor = _PyObject_CallMethodIdNoArgs((PyObject*)self, &PyId_cursor); cursor = _PyObject_CallMethodIdNoArgs((PyObject*)self, &PyId_cursor);
if (!cursor) { if (!cursor) {
goto error; goto error;
} }
method = PyObject_GetAttrString(cursor, "executemany"); result = _PyObject_CallMethodIdObjArgs(cursor, &PyId_executemany, sql,
if (!method) { parameters, NULL);
Py_CLEAR(cursor);
goto error;
}
result = PyObject_CallObject(method, args);
if (!result) { if (!result) {
Py_CLEAR(cursor); Py_CLEAR(cursor);
} }
error: error:
Py_XDECREF(result); Py_XDECREF(result);
Py_XDECREF(method);
return cursor; return cursor;
} }
PyObject* pysqlite_connection_executescript(pysqlite_Connection* self, PyObject* args) /*[clinic input]
_sqlite3.Connection.executescript as pysqlite_connection_executescript
sql_script as script_obj: object
/
Executes a multiple SQL statements at once. Non-standard.
[clinic start generated code]*/
static PyObject *
pysqlite_connection_executescript(pysqlite_Connection *self,
PyObject *script_obj)
/*[clinic end generated code: output=4c4f9d77aa0ae37d input=c0b14695aa6c81d9]*/
{ {
_Py_IDENTIFIER(executescript);
PyObject* cursor = 0; PyObject* cursor = 0;
PyObject* result = 0; PyObject* result = 0;
PyObject* method = 0;
cursor = _PyObject_CallMethodIdNoArgs((PyObject*)self, &PyId_cursor); cursor = _PyObject_CallMethodIdNoArgs((PyObject*)self, &PyId_cursor);
if (!cursor) { if (!cursor) {
goto error; goto error;
} }
method = PyObject_GetAttrString(cursor, "executescript"); result = _PyObject_CallMethodIdObjArgs(cursor, &PyId_executescript,
if (!method) { script_obj, NULL);
Py_CLEAR(cursor);
goto error;
}
result = PyObject_CallObject(method, args);
if (!result) { if (!result) {
Py_CLEAR(cursor); Py_CLEAR(cursor);
} }
error: error:
Py_XDECREF(result); Py_XDECREF(result);
Py_XDECREF(method);
return cursor; return cursor;
} }
@ -1558,51 +1585,41 @@ finally:
return retval; return retval;
} }
/*[clinic input]
_sqlite3.Connection.backup as pysqlite_connection_backup
target: object(type='pysqlite_Connection *', subclass_of='pysqlite_ConnectionType') = NULL
*
pages: int = -1
progress: object = None
name: str = "main"
sleep: double = 0.250
Makes a backup of the database. Non-standard.
[clinic start generated code]*/
static PyObject * static PyObject *
pysqlite_connection_backup(pysqlite_Connection *self, PyObject *args, PyObject *kwds) pysqlite_connection_backup_impl(pysqlite_Connection *self,
pysqlite_Connection *target, int pages,
PyObject *progress, const char *name,
double sleep)
/*[clinic end generated code: output=306a3e6a38c36334 input=2f3497ea530144b1]*/
{ {
PyObject *target = NULL;
int pages = -1;
PyObject *progress = Py_None;
const char *name = "main";
int rc; int rc;
int callback_error = 0; int callback_error = 0;
PyObject *sleep_obj = NULL; int sleep_ms = sleep * 1000.0;
int sleep_ms = 250;
sqlite3 *bck_conn; sqlite3 *bck_conn;
sqlite3_backup *bck_handle; sqlite3_backup *bck_handle;
static char *keywords[] = {"target", "pages", "progress", "name", "sleep", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|$iOsO:backup", keywords,
pysqlite_ConnectionType, &target,
&pages, &progress, &name, &sleep_obj)) {
return NULL;
}
if (sleep_obj != NULL) {
_PyTime_t sleep_secs;
if (_PyTime_FromSecondsObject(&sleep_secs, sleep_obj,
_PyTime_ROUND_TIMEOUT)) {
return NULL;
}
_PyTime_t ms = _PyTime_AsMilliseconds(sleep_secs,
_PyTime_ROUND_TIMEOUT);
if (ms < INT_MIN || ms > INT_MAX) {
PyErr_SetString(PyExc_OverflowError, "sleep is too large");
return NULL;
}
sleep_ms = (int)ms;
}
if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) {
return NULL; return NULL;
} }
if (!pysqlite_check_connection((pysqlite_Connection *)target)) { if (!pysqlite_check_connection(target)) {
return NULL; return NULL;
} }
if ((pysqlite_Connection *)target == self) { if (target == self) {
PyErr_SetString(PyExc_ValueError, "target cannot be the same connection instance"); PyErr_SetString(PyExc_ValueError, "target cannot be the same connection instance");
return NULL; return NULL;
} }
@ -1610,7 +1627,7 @@ pysqlite_connection_backup(pysqlite_Connection *self, PyObject *args, PyObject *
#if SQLITE_VERSION_NUMBER < 3008008 #if SQLITE_VERSION_NUMBER < 3008008
/* Since 3.8.8 this is already done, per commit /* Since 3.8.8 this is already done, per commit
https://www.sqlite.org/src/info/169b5505498c0a7e */ https://www.sqlite.org/src/info/169b5505498c0a7e */
if (!sqlite3_get_autocommit(((pysqlite_Connection *)target)->db)) { if (!sqlite3_get_autocommit(target->db)) {
PyErr_SetString(pysqlite_OperationalError, "target is in transaction"); PyErr_SetString(pysqlite_OperationalError, "target is in transaction");
return NULL; return NULL;
} }
@ -1625,7 +1642,7 @@ pysqlite_connection_backup(pysqlite_Connection *self, PyObject *args, PyObject *
pages = -1; pages = -1;
} }
bck_conn = ((pysqlite_Connection *)target)->db; bck_conn = target->db;
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
bck_handle = sqlite3_backup_init(bck_conn, "main", self->db, name); bck_handle = sqlite3_backup_init(bck_conn, "main", self->db, name);
@ -1869,13 +1886,18 @@ static PyGetSetDef connection_getset[] = {
}; };
static PyMethodDef connection_methods[] = { static PyMethodDef connection_methods[] = {
PYSQLITE_CONNECTION_BACKUP_METHODDEF
PYSQLITE_CONNECTION_CLOSE_METHODDEF PYSQLITE_CONNECTION_CLOSE_METHODDEF
PYSQLITE_CONNECTION_COMMIT_METHODDEF
PYSQLITE_CONNECTION_CREATE_AGGREGATE_METHODDEF PYSQLITE_CONNECTION_CREATE_AGGREGATE_METHODDEF
PYSQLITE_CONNECTION_CREATE_COLLATION_METHODDEF PYSQLITE_CONNECTION_CREATE_COLLATION_METHODDEF
PYSQLITE_CONNECTION_CREATE_FUNCTION_METHODDEF PYSQLITE_CONNECTION_CREATE_FUNCTION_METHODDEF
PYSQLITE_CONNECTION_CURSOR_METHODDEF PYSQLITE_CONNECTION_CURSOR_METHODDEF
PYSQLITE_CONNECTION_ENABLE_LOAD_EXTENSION_METHODDEF PYSQLITE_CONNECTION_ENABLE_LOAD_EXTENSION_METHODDEF
PYSQLITE_CONNECTION_ENTER_METHODDEF PYSQLITE_CONNECTION_ENTER_METHODDEF
PYSQLITE_CONNECTION_EXECUTEMANY_METHODDEF
PYSQLITE_CONNECTION_EXECUTESCRIPT_METHODDEF
PYSQLITE_CONNECTION_EXECUTE_METHODDEF
PYSQLITE_CONNECTION_EXIT_METHODDEF PYSQLITE_CONNECTION_EXIT_METHODDEF
PYSQLITE_CONNECTION_INTERRUPT_METHODDEF PYSQLITE_CONNECTION_INTERRUPT_METHODDEF
PYSQLITE_CONNECTION_ITERDUMP_METHODDEF PYSQLITE_CONNECTION_ITERDUMP_METHODDEF
@ -1884,16 +1906,6 @@ static PyMethodDef connection_methods[] = {
PYSQLITE_CONNECTION_SET_AUTHORIZER_METHODDEF PYSQLITE_CONNECTION_SET_AUTHORIZER_METHODDEF
PYSQLITE_CONNECTION_SET_PROGRESS_HANDLER_METHODDEF PYSQLITE_CONNECTION_SET_PROGRESS_HANDLER_METHODDEF
PYSQLITE_CONNECTION_SET_TRACE_CALLBACK_METHODDEF PYSQLITE_CONNECTION_SET_TRACE_CALLBACK_METHODDEF
{"commit", (PyCFunction)pysqlite_connection_commit, METH_NOARGS,
PyDoc_STR("Commit the current transaction.")},
{"execute", (PyCFunction)pysqlite_connection_execute, METH_VARARGS,
PyDoc_STR("Executes a SQL statement. Non-standard.")},
{"executemany", (PyCFunction)pysqlite_connection_executemany, METH_VARARGS,
PyDoc_STR("Repeatedly executes a SQL statement. Non-standard.")},
{"executescript", (PyCFunction)pysqlite_connection_executescript, METH_VARARGS,
PyDoc_STR("Executes a multiple SQL statements at once. Non-standard.")},
{"backup", (PyCFunction)(void(*)(void))pysqlite_connection_backup, METH_VARARGS | METH_KEYWORDS,
PyDoc_STR("Makes a backup of the database. Non-standard.")},
{NULL, NULL} {NULL, NULL}
}; };

View File

@ -111,7 +111,6 @@ extern PyTypeObject *pysqlite_ConnectionType;
PyObject* pysqlite_connection_alloc(PyTypeObject* type, int aware); PyObject* pysqlite_connection_alloc(PyTypeObject* type, int aware);
void pysqlite_connection_dealloc(pysqlite_Connection* self); void pysqlite_connection_dealloc(pysqlite_Connection* self);
PyObject* _pysqlite_connection_begin(pysqlite_Connection* self); PyObject* _pysqlite_connection_begin(pysqlite_Connection* self);
PyObject* pysqlite_connection_commit(pysqlite_Connection* self, PyObject* args);
PyObject* pysqlite_connection_new(PyTypeObject* type, PyObject* args, PyObject* kw); PyObject* pysqlite_connection_new(PyTypeObject* type, PyObject* args, PyObject* kw);
int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject* kwargs); int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject* kwargs);

View File

@ -628,6 +628,7 @@ PyObject* pysqlite_cursor_executemany(pysqlite_Cursor* self, PyObject* args)
static PyObject * static PyObject *
pysqlite_cursor_executescript(pysqlite_Cursor* self, PyObject* args) pysqlite_cursor_executescript(pysqlite_Cursor* self, PyObject* args)
{ {
_Py_IDENTIFIER(commit);
PyObject* script_obj; PyObject* script_obj;
const char* script_cstr; const char* script_cstr;
sqlite3_stmt* statement; sqlite3_stmt* statement;
@ -655,7 +656,7 @@ pysqlite_cursor_executescript(pysqlite_Cursor* self, PyObject* args)
} }
/* commit first */ /* commit first */
result = pysqlite_connection_commit(self->connection, NULL); result = _PyObject_CallMethodIdNoArgs((PyObject *)self->connection, &PyId_commit);
if (!result) { if (!result) {
goto error; goto error;
} }