From 7d210271579ae31f43b32f73c2aff5bc4fe0d27f Mon Sep 17 00:00:00 2001 From: Erlend Egeberg Aasland Date: Sat, 31 Oct 2020 07:07:44 +0100 Subject: [PATCH] bpo-40956: Convert _sqlite3 module level functions to Argument Clinic (GH-22484) --- Modules/_sqlite/clinic/module.c.h | 222 ++++++++++++++++++++++++++++++ Modules/_sqlite/microprotocols.c | 13 -- Modules/_sqlite/microprotocols.h | 5 - Modules/_sqlite/module.c | 161 ++++++++++++---------- 4 files changed, 313 insertions(+), 88 deletions(-) create mode 100644 Modules/_sqlite/clinic/module.c.h diff --git a/Modules/_sqlite/clinic/module.c.h b/Modules/_sqlite/clinic/module.c.h new file mode 100644 index 00000000000..fb1e1187b20 --- /dev/null +++ b/Modules/_sqlite/clinic/module.c.h @@ -0,0 +1,222 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +PyDoc_STRVAR(pysqlite_complete_statement__doc__, +"complete_statement($module, /, statement)\n" +"--\n" +"\n" +"Checks if a string contains a complete SQL statement. Non-standard."); + +#define PYSQLITE_COMPLETE_STATEMENT_METHODDEF \ + {"complete_statement", (PyCFunction)(void(*)(void))pysqlite_complete_statement, METH_FASTCALL|METH_KEYWORDS, pysqlite_complete_statement__doc__}, + +static PyObject * +pysqlite_complete_statement_impl(PyObject *module, const char *statement); + +static PyObject * +pysqlite_complete_statement(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"statement", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "complete_statement", 0}; + PyObject *argsbuf[1]; + const char *statement; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!PyUnicode_Check(args[0])) { + _PyArg_BadArgument("complete_statement", "argument 'statement'", "str", args[0]); + goto exit; + } + Py_ssize_t statement_length; + statement = PyUnicode_AsUTF8AndSize(args[0], &statement_length); + if (statement == NULL) { + goto exit; + } + if (strlen(statement) != (size_t)statement_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } + return_value = pysqlite_complete_statement_impl(module, statement); + +exit: + return return_value; +} + +PyDoc_STRVAR(pysqlite_enable_shared_cache__doc__, +"enable_shared_cache($module, /, do_enable)\n" +"--\n" +"\n" +"Enable or disable shared cache mode for the calling thread.\n" +"\n" +"Experimental/Non-standard."); + +#define PYSQLITE_ENABLE_SHARED_CACHE_METHODDEF \ + {"enable_shared_cache", (PyCFunction)(void(*)(void))pysqlite_enable_shared_cache, METH_FASTCALL|METH_KEYWORDS, pysqlite_enable_shared_cache__doc__}, + +static PyObject * +pysqlite_enable_shared_cache_impl(PyObject *module, int do_enable); + +static PyObject * +pysqlite_enable_shared_cache(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"do_enable", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "enable_shared_cache", 0}; + PyObject *argsbuf[1]; + int do_enable; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + do_enable = _PyLong_AsInt(args[0]); + if (do_enable == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = pysqlite_enable_shared_cache_impl(module, do_enable); + +exit: + return return_value; +} + +PyDoc_STRVAR(pysqlite_register_adapter__doc__, +"register_adapter($module, type, caster, /)\n" +"--\n" +"\n" +"Registers an adapter with pysqlite\'s adapter registry. Non-standard."); + +#define PYSQLITE_REGISTER_ADAPTER_METHODDEF \ + {"register_adapter", (PyCFunction)(void(*)(void))pysqlite_register_adapter, METH_FASTCALL, pysqlite_register_adapter__doc__}, + +static PyObject * +pysqlite_register_adapter_impl(PyObject *module, PyTypeObject *type, + PyObject *caster); + +static PyObject * +pysqlite_register_adapter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyTypeObject *type; + PyObject *caster; + + if (!_PyArg_CheckPositional("register_adapter", nargs, 2, 2)) { + goto exit; + } + type = (PyTypeObject *)args[0]; + caster = args[1]; + return_value = pysqlite_register_adapter_impl(module, type, caster); + +exit: + return return_value; +} + +PyDoc_STRVAR(pysqlite_register_converter__doc__, +"register_converter($module, name, converter, /)\n" +"--\n" +"\n" +"Registers a converter with pysqlite. Non-standard."); + +#define PYSQLITE_REGISTER_CONVERTER_METHODDEF \ + {"register_converter", (PyCFunction)(void(*)(void))pysqlite_register_converter, METH_FASTCALL, pysqlite_register_converter__doc__}, + +static PyObject * +pysqlite_register_converter_impl(PyObject *module, PyObject *orig_name, + PyObject *callable); + +static PyObject * +pysqlite_register_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *orig_name; + PyObject *callable; + + if (!_PyArg_CheckPositional("register_converter", nargs, 2, 2)) { + goto exit; + } + if (!PyUnicode_Check(args[0])) { + _PyArg_BadArgument("register_converter", "argument 1", "str", args[0]); + goto exit; + } + if (PyUnicode_READY(args[0]) == -1) { + goto exit; + } + orig_name = args[0]; + callable = args[1]; + return_value = pysqlite_register_converter_impl(module, orig_name, callable); + +exit: + return return_value; +} + +PyDoc_STRVAR(pysqlite_enable_callback_trace__doc__, +"enable_callback_tracebacks($module, enable, /)\n" +"--\n" +"\n" +"Enable or disable callback functions throwing errors to stderr."); + +#define PYSQLITE_ENABLE_CALLBACK_TRACE_METHODDEF \ + {"enable_callback_tracebacks", (PyCFunction)pysqlite_enable_callback_trace, METH_O, pysqlite_enable_callback_trace__doc__}, + +static PyObject * +pysqlite_enable_callback_trace_impl(PyObject *module, int enable); + +static PyObject * +pysqlite_enable_callback_trace(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int enable; + + enable = _PyLong_AsInt(arg); + if (enable == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = pysqlite_enable_callback_trace_impl(module, enable); + +exit: + return return_value; +} + +PyDoc_STRVAR(pysqlite_adapt__doc__, +"adapt($module, obj, proto=PrepareProtocolType, alt=, /)\n" +"--\n" +"\n" +"Adapt given object to given protocol. Non-standard."); + +#define PYSQLITE_ADAPT_METHODDEF \ + {"adapt", (PyCFunction)(void(*)(void))pysqlite_adapt, METH_FASTCALL, pysqlite_adapt__doc__}, + +static PyObject * +pysqlite_adapt_impl(PyObject *module, PyObject *obj, PyObject *proto, + PyObject *alt); + +static PyObject * +pysqlite_adapt(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *obj; + PyObject *proto = (PyObject*)pysqlite_PrepareProtocolType; + PyObject *alt = NULL; + + if (!_PyArg_CheckPositional("adapt", nargs, 1, 3)) { + goto exit; + } + obj = args[0]; + if (nargs < 2) { + goto skip_optional; + } + proto = args[1]; + if (nargs < 3) { + goto skip_optional; + } + alt = args[2]; +skip_optional: + return_value = pysqlite_adapt_impl(module, obj, proto, alt); + +exit: + return return_value; +} +/*[clinic end generated code: output=d87990f941c209fa input=a9049054013a1b77]*/ diff --git a/Modules/_sqlite/microprotocols.c b/Modules/_sqlite/microprotocols.c index ddc30e8a89b..cf1fefd6718 100644 --- a/Modules/_sqlite/microprotocols.c +++ b/Modules/_sqlite/microprotocols.c @@ -29,7 +29,6 @@ #include "microprotocols.h" #include "prepare_protocol.h" - /** the adapters registry **/ static PyObject *psyco_adapters = NULL; @@ -150,15 +149,3 @@ pysqlite_microprotocols_adapt(PyObject *obj, PyObject *proto, PyObject *alt) PyErr_SetString(pysqlite_ProgrammingError, "can't adapt"); return NULL; } - -/** module-level functions **/ - -PyObject * -pysqlite_adapt(pysqlite_Cursor *self, PyObject *args) -{ - PyObject *obj, *alt = NULL; - PyObject *proto = (PyObject*)pysqlite_PrepareProtocolType; - - if (!PyArg_ParseTuple(args, "O|OO", &obj, &proto, &alt)) return NULL; - return pysqlite_microprotocols_adapt(obj, proto, alt); -} diff --git a/Modules/_sqlite/microprotocols.h b/Modules/_sqlite/microprotocols.h index 87df6bac557..e9adef916e7 100644 --- a/Modules/_sqlite/microprotocols.h +++ b/Modules/_sqlite/microprotocols.h @@ -44,9 +44,4 @@ extern int pysqlite_microprotocols_add( extern PyObject *pysqlite_microprotocols_adapt( PyObject *obj, PyObject *proto, PyObject *alt); -extern PyObject * - pysqlite_adapt(pysqlite_Cursor* self, PyObject *args); -#define pysqlite_adapt_doc \ - "adapt(obj, protocol, alternate) -> adapt obj to given protocol. Non-standard." - #endif /* !defined(PSYCOPG_MICROPROTOCOLS_H) */ diff --git a/Modules/_sqlite/module.c b/Modules/_sqlite/module.c index 0297e2fab29..33324402385 100644 --- a/Modules/_sqlite/module.c +++ b/Modules/_sqlite/module.c @@ -33,6 +33,12 @@ #error "SQLite 3.7.3 or higher required" #endif +#include "clinic/module.c.h" +/*[clinic input] +module _sqlite3 +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=81e330492d57488e]*/ + /* static objects at module-level */ PyObject *pysqlite_Error = NULL; @@ -102,19 +108,20 @@ Opens a connection to the SQLite database file *database*. You can use\n\ \":memory:\" to open a database connection to a database that resides in\n\ RAM instead of on disk."); -static PyObject* module_complete(PyObject* self, PyObject* args, PyObject* - kwargs) +/*[clinic input] +_sqlite3.complete_statement as pysqlite_complete_statement + + statement: str + +Checks if a string contains a complete SQL statement. Non-standard. +[clinic start generated code]*/ + +static PyObject * +pysqlite_complete_statement_impl(PyObject *module, const char *statement) +/*[clinic end generated code: output=e55f1ff1952df558 input=f6b24996b31c5c33]*/ { - static char *kwlist[] = {"statement", NULL}; - char* statement; - PyObject* result; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &statement)) - { - return NULL; - } - if (sqlite3_complete(statement)) { result = Py_True; } else { @@ -126,23 +133,22 @@ static PyObject* module_complete(PyObject* self, PyObject* args, PyObject* return result; } -PyDoc_STRVAR(module_complete_doc, -"complete_statement(sql)\n\ -\n\ -Checks if a string contains a complete SQL statement. Non-standard."); +/*[clinic input] +_sqlite3.enable_shared_cache as pysqlite_enable_shared_cache -static PyObject* module_enable_shared_cache(PyObject* self, PyObject* args, PyObject* - kwargs) + do_enable: int + +Enable or disable shared cache mode for the calling thread. + +Experimental/Non-standard. +[clinic start generated code]*/ + +static PyObject * +pysqlite_enable_shared_cache_impl(PyObject *module, int do_enable) +/*[clinic end generated code: output=259c74eedee1516b input=8400e41bc58b6b24]*/ { - static char *kwlist[] = {"do_enable", NULL}; - int do_enable; int rc; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i", kwlist, &do_enable)) - { - return NULL; - } - rc = sqlite3_enable_shared_cache(do_enable); if (rc != SQLITE_OK) { @@ -153,22 +159,23 @@ static PyObject* module_enable_shared_cache(PyObject* self, PyObject* args, PyOb } } -PyDoc_STRVAR(module_enable_shared_cache_doc, -"enable_shared_cache(do_enable)\n\ -\n\ -Enable or disable shared cache mode for the calling thread.\n\ -Experimental/Non-standard."); +/*[clinic input] +_sqlite3.register_adapter as pysqlite_register_adapter -static PyObject* module_register_adapter(PyObject* self, PyObject* args) + type: object(type='PyTypeObject *') + caster: object + / + +Registers an adapter with pysqlite's adapter registry. Non-standard. +[clinic start generated code]*/ + +static PyObject * +pysqlite_register_adapter_impl(PyObject *module, PyTypeObject *type, + PyObject *caster) +/*[clinic end generated code: output=a287e8db18e8af23 input=839dad90e2492725]*/ { - PyTypeObject* type; - PyObject* caster; int rc; - if (!PyArg_ParseTuple(args, "OO", &type, &caster)) { - return NULL; - } - /* a basic type is adapted; there's a performance optimization if that's not the case * (99 % of all usages) */ if (type == &PyLong_Type || type == &PyFloat_Type @@ -183,23 +190,25 @@ static PyObject* module_register_adapter(PyObject* self, PyObject* args) Py_RETURN_NONE; } -PyDoc_STRVAR(module_register_adapter_doc, -"register_adapter(type, callable)\n\ -\n\ -Registers an adapter with pysqlite's adapter registry. Non-standard."); +/*[clinic input] +_sqlite3.register_converter as pysqlite_register_converter -static PyObject* module_register_converter(PyObject* self, PyObject* args) + name as orig_name: unicode + converter as callable: object + / + +Registers a converter with pysqlite. Non-standard. +[clinic start generated code]*/ + +static PyObject * +pysqlite_register_converter_impl(PyObject *module, PyObject *orig_name, + PyObject *callable) +/*[clinic end generated code: output=a2f2bfeed7230062 input=e074cf7f4890544f]*/ { - PyObject* orig_name; PyObject* name = NULL; - PyObject* callable; PyObject* retval = NULL; _Py_IDENTIFIER(upper); - if (!PyArg_ParseTuple(args, "UO", &orig_name, &callable)) { - return NULL; - } - /* convert the name to upper case */ name = _PyObject_CallMethodIdNoArgs(orig_name, &PyId_upper); if (!name) { @@ -217,24 +226,42 @@ error: return retval; } -PyDoc_STRVAR(module_register_converter_doc, -"register_converter(typename, callable)\n\ -\n\ -Registers a converter with pysqlite. Non-standard."); +/*[clinic input] +_sqlite3.enable_callback_tracebacks as pysqlite_enable_callback_trace -static PyObject* enable_callback_tracebacks(PyObject* self, PyObject* args) + enable: int + / + +Enable or disable callback functions throwing errors to stderr. +[clinic start generated code]*/ + +static PyObject * +pysqlite_enable_callback_trace_impl(PyObject *module, int enable) +/*[clinic end generated code: output=4ff1d051c698f194 input=cb79d3581eb77c40]*/ { - if (!PyArg_ParseTuple(args, "i", &_pysqlite_enable_callback_tracebacks)) { - return NULL; - } + _pysqlite_enable_callback_tracebacks = enable; Py_RETURN_NONE; } -PyDoc_STRVAR(enable_callback_tracebacks_doc, -"enable_callback_tracebacks(flag)\n\ -\n\ -Enable or disable callback functions throwing errors to stderr."); +/*[clinic input] +_sqlite3.adapt as pysqlite_adapt + + obj: object + proto: object(c_default='(PyObject*)pysqlite_PrepareProtocolType') = PrepareProtocolType + alt: object = NULL + / + +Adapt given object to given protocol. Non-standard. +[clinic start generated code]*/ + +static PyObject * +pysqlite_adapt_impl(PyObject *module, PyObject *obj, PyObject *proto, + PyObject *alt) +/*[clinic end generated code: output=0c3927c5fcd23dd9 input=a58ab77fb5ae22dd]*/ +{ + return pysqlite_microprotocols_adapt(obj, proto, alt); +} static void converters_init(PyObject* module) { @@ -252,18 +279,12 @@ static void converters_init(PyObject* module) static PyMethodDef module_methods[] = { {"connect", (PyCFunction)(void(*)(void))module_connect, METH_VARARGS | METH_KEYWORDS, module_connect_doc}, - {"complete_statement", (PyCFunction)(void(*)(void))module_complete, - METH_VARARGS | METH_KEYWORDS, module_complete_doc}, - {"enable_shared_cache", (PyCFunction)(void(*)(void))module_enable_shared_cache, - METH_VARARGS | METH_KEYWORDS, module_enable_shared_cache_doc}, - {"register_adapter", (PyCFunction)module_register_adapter, - METH_VARARGS, module_register_adapter_doc}, - {"register_converter", (PyCFunction)module_register_converter, - METH_VARARGS, module_register_converter_doc}, - {"adapt", (PyCFunction)pysqlite_adapt, METH_VARARGS, - pysqlite_adapt_doc}, - {"enable_callback_tracebacks", (PyCFunction)enable_callback_tracebacks, - METH_VARARGS, enable_callback_tracebacks_doc}, + PYSQLITE_ADAPT_METHODDEF + PYSQLITE_COMPLETE_STATEMENT_METHODDEF + PYSQLITE_ENABLE_CALLBACK_TRACE_METHODDEF + PYSQLITE_ENABLE_SHARED_CACHE_METHODDEF + PYSQLITE_REGISTER_ADAPTER_METHODDEF + PYSQLITE_REGISTER_CONVERTER_METHODDEF {NULL, NULL} };