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

corona10 webhook-mailer at python.org
Sun Dec 27 03:32:40 EST 2020


https://github.com/python/cpython/commit/3ccef1ca474592e191a00e131dfbaf777db271e9
commit: 3ccef1ca474592e191a00e131dfbaf777db271e9
branch: master
author: Erlend Egeberg Aasland <erlend.aasland at innova.no>
committer: corona10 <donghee.na92 at gmail.com>
date: 2020-12-27T17:32:18+09:00
summary:

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

files:
M Modules/_sqlite/clinic/connection.c.h
M Modules/_sqlite/connection.c
M Modules/_sqlite/connection.h
M Modules/_sqlite/cursor.c

diff --git a/Modules/_sqlite/clinic/connection.c.h b/Modules/_sqlite/clinic/connection.c.h
index 7e3c9a9e61b19..01b8e37a957fc 100644
--- a/Modules/_sqlite/clinic/connection.c.h
+++ b/Modules/_sqlite/clinic/connection.c.h
@@ -57,6 +57,24 @@ pysqlite_connection_close(pysqlite_Connection *self, PyObject *Py_UNUSED(ignored
     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__,
 "rollback($self, /)\n"
 "--\n"
@@ -373,6 +391,95 @@ pysqlite_connection_load_extension(pysqlite_Connection *self, PyObject *arg)
 
 #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__,
 "interrupt($self, /)\n"
 "--\n"
@@ -411,6 +518,107 @@ pysqlite_connection_iterdump(pysqlite_Connection *self, PyObject *Py_UNUSED(igno
     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__,
 "create_collation($self, name, callback, /)\n"
 "--\n"
@@ -511,4 +719,4 @@ pysqlite_connection_exit(pysqlite_Connection *self, PyObject *const *args, Py_ss
 #ifndef PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF
     #define 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]*/
diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c
index 75aec74e0aaa9..7f13f96cac4d0 100644
--- a/Modules/_sqlite/connection.c
+++ b/Modules/_sqlite/connection.c
@@ -407,7 +407,15 @@ PyObject* _pysqlite_connection_begin(pysqlite_Connection* self)
     }
 }
 
-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;
     const char* tail;
@@ -1339,89 +1347,108 @@ PyObject* pysqlite_connection_call(pysqlite_Connection* self, PyObject* args, Py
     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* result = 0;
-    PyObject* method = 0;
 
     cursor = _PyObject_CallMethodIdNoArgs((PyObject*)self, &PyId_cursor);
     if (!cursor) {
         goto error;
     }
 
-    method = PyObject_GetAttrString(cursor, "execute");
-    if (!method) {
-        Py_CLEAR(cursor);
-        goto error;
-    }
-
-    result = PyObject_CallObject(method, args);
+    result = _PyObject_CallMethodIdObjArgs(cursor, &PyId_execute, sql, parameters, NULL);
     if (!result) {
         Py_CLEAR(cursor);
     }
 
 error:
     Py_XDECREF(result);
-    Py_XDECREF(method);
 
     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* result = 0;
-    PyObject* method = 0;
 
     cursor = _PyObject_CallMethodIdNoArgs((PyObject*)self, &PyId_cursor);
     if (!cursor) {
         goto error;
     }
 
-    method = PyObject_GetAttrString(cursor, "executemany");
-    if (!method) {
-        Py_CLEAR(cursor);
-        goto error;
-    }
-
-    result = PyObject_CallObject(method, args);
+    result = _PyObject_CallMethodIdObjArgs(cursor, &PyId_executemany, sql,
+                                           parameters, NULL);
     if (!result) {
         Py_CLEAR(cursor);
     }
 
 error:
     Py_XDECREF(result);
-    Py_XDECREF(method);
 
     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* result = 0;
-    PyObject* method = 0;
 
     cursor = _PyObject_CallMethodIdNoArgs((PyObject*)self, &PyId_cursor);
     if (!cursor) {
         goto error;
     }
 
-    method = PyObject_GetAttrString(cursor, "executescript");
-    if (!method) {
-        Py_CLEAR(cursor);
-        goto error;
-    }
-
-    result = PyObject_CallObject(method, args);
+    result = _PyObject_CallMethodIdObjArgs(cursor, &PyId_executescript,
+                                           script_obj, NULL);
     if (!result) {
         Py_CLEAR(cursor);
     }
 
 error:
     Py_XDECREF(result);
-    Py_XDECREF(method);
 
     return cursor;
 }
@@ -1558,51 +1585,41 @@ pysqlite_connection_iterdump_impl(pysqlite_Connection *self)
     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 *
-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 callback_error = 0;
-    PyObject *sleep_obj = NULL;
-    int sleep_ms = 250;
+    int sleep_ms = sleep * 1000.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,
-                                     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)) {
         return NULL;
     }
 
-    if (!pysqlite_check_connection((pysqlite_Connection *)target)) {
+    if (!pysqlite_check_connection(target)) {
         return NULL;
     }
 
-    if ((pysqlite_Connection *)target == self) {
+    if (target == self) {
         PyErr_SetString(PyExc_ValueError, "target cannot be the same connection instance");
         return NULL;
     }
@@ -1610,7 +1627,7 @@ pysqlite_connection_backup(pysqlite_Connection *self, PyObject *args, PyObject *
 #if SQLITE_VERSION_NUMBER < 3008008
     /* Since 3.8.8 this is already done, per commit
        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");
         return NULL;
     }
@@ -1625,7 +1642,7 @@ pysqlite_connection_backup(pysqlite_Connection *self, PyObject *args, PyObject *
         pages = -1;
     }
 
-    bck_conn = ((pysqlite_Connection *)target)->db;
+    bck_conn = target->db;
 
     Py_BEGIN_ALLOW_THREADS
     bck_handle = sqlite3_backup_init(bck_conn, "main", self->db, name);
@@ -1869,13 +1886,18 @@ static PyGetSetDef connection_getset[] = {
 };
 
 static PyMethodDef connection_methods[] = {
+    PYSQLITE_CONNECTION_BACKUP_METHODDEF
     PYSQLITE_CONNECTION_CLOSE_METHODDEF
+    PYSQLITE_CONNECTION_COMMIT_METHODDEF
     PYSQLITE_CONNECTION_CREATE_AGGREGATE_METHODDEF
     PYSQLITE_CONNECTION_CREATE_COLLATION_METHODDEF
     PYSQLITE_CONNECTION_CREATE_FUNCTION_METHODDEF
     PYSQLITE_CONNECTION_CURSOR_METHODDEF
     PYSQLITE_CONNECTION_ENABLE_LOAD_EXTENSION_METHODDEF
     PYSQLITE_CONNECTION_ENTER_METHODDEF
+    PYSQLITE_CONNECTION_EXECUTEMANY_METHODDEF
+    PYSQLITE_CONNECTION_EXECUTESCRIPT_METHODDEF
+    PYSQLITE_CONNECTION_EXECUTE_METHODDEF
     PYSQLITE_CONNECTION_EXIT_METHODDEF
     PYSQLITE_CONNECTION_INTERRUPT_METHODDEF
     PYSQLITE_CONNECTION_ITERDUMP_METHODDEF
@@ -1884,16 +1906,6 @@ static PyMethodDef connection_methods[] = {
     PYSQLITE_CONNECTION_SET_AUTHORIZER_METHODDEF
     PYSQLITE_CONNECTION_SET_PROGRESS_HANDLER_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}
 };
 
diff --git a/Modules/_sqlite/connection.h b/Modules/_sqlite/connection.h
index 341ef01eda7fe..1d1a8ad5ae04d 100644
--- a/Modules/_sqlite/connection.h
+++ b/Modules/_sqlite/connection.h
@@ -111,7 +111,6 @@ extern PyTypeObject *pysqlite_ConnectionType;
 PyObject* pysqlite_connection_alloc(PyTypeObject* type, int aware);
 void pysqlite_connection_dealloc(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);
 int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject* kwargs);
 
diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c
index 3c09c1c6b7e50..2651e154df598 100644
--- a/Modules/_sqlite/cursor.c
+++ b/Modules/_sqlite/cursor.c
@@ -628,6 +628,7 @@ PyObject* pysqlite_cursor_executemany(pysqlite_Cursor* self, PyObject* args)
 static PyObject *
 pysqlite_cursor_executescript(pysqlite_Cursor* self, PyObject* args)
 {
+    _Py_IDENTIFIER(commit);
     PyObject* script_obj;
     const char* script_cstr;
     sqlite3_stmt* statement;
@@ -655,7 +656,7 @@ pysqlite_cursor_executescript(pysqlite_Cursor* self, PyObject* args)
     }
 
     /* commit first */
-    result = pysqlite_connection_commit(self->connection, NULL);
+    result = _PyObject_CallMethodIdNoArgs((PyObject *)self->connection, &PyId_commit);
     if (!result) {
         goto error;
     }



More information about the Python-checkins mailing list