From 4f89b4cd228ceef06dc2caacafc6c465e2bb9e6f Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 22 Aug 2023 13:41:40 +0200 Subject: [PATCH 1/7] gh-108278: Clean up some sqlite3 connection APIs Deprecate passing name, number of arguments, and the callable as keyword arguments, for the following sqlite3.Connection APIs: - create_function(name, nargs, callable, ...) - create_aggregate(name, nargs, callable) Deprecate passing the callback as a keyword argument, for the following sqlite3.Connection APIs: - set_authorizer(callback) - set_progress_handler(callback, n) - set_trace_callback(callback) The affected parameters will become positional-only in Python 3.15. --- Doc/whatsnew/3.13.rst | 19 ++- ...-08-22-13-51-10.gh-issue-108278.11d_qG.rst | 16 ++ Modules/_sqlite/clinic/connection.c.h | 143 +++++++++++++++++- Modules/_sqlite/connection.c | 15 +- 4 files changed, 181 insertions(+), 12 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2023-08-22-13-51-10.gh-issue-108278.11d_qG.rst diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index 8509e18a7d792e..451c5635cef69b 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -252,7 +252,24 @@ Deprecated * Passing more than one positional argument to :func:`sqlite3.connect` and the :class:`sqlite3.Connection` constructor is deprecated. The remaining parameters will become keyword-only in Python 3.15. - (Contributed by Erlend E. Aasland in :gh:`107948`.) + + Deprecate passing name, number of arguments, and the callable as keyword + arguments, for the following :class:`sqlite3.Connection` APIs: + + - :meth:`~sqlite3.Connection.create_function` + - :meth:`~sqlite3.Connection.create_aggregate` + + The affected parameters will become positional-only in Python 3.15. + + Deprecate passing the callback as a keyword argument, for the following + :class:`sqlite3.Connection` APIs: + + - :meth:`~sqlite3.Connection.set_authorizer` + - :meth:`~sqlite3.Connection.set_progress_handler` + - :meth:`~sqlite3.Connection.set_trace_callback` + + The affected parameters will become positional-only in Python 3.15. + (Contributed by Erlend E. Aasland in :gh:`107948` and :gh:`108278`.) Pending Removal in Python 3.14 ------------------------------ diff --git a/Misc/NEWS.d/next/Library/2023-08-22-13-51-10.gh-issue-108278.11d_qG.rst b/Misc/NEWS.d/next/Library/2023-08-22-13-51-10.gh-issue-108278.11d_qG.rst new file mode 100644 index 00000000000000..d4b32cade54ecb --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-08-22-13-51-10.gh-issue-108278.11d_qG.rst @@ -0,0 +1,16 @@ +Deprecate passing name, number of arguments, and the callable as keyword +arguments, for the following :class:`sqlite3.Connection` APIs: + +- :meth:`~sqlite3.Connection.create_function` - +:meth:`~sqlite3.Connection.create_aggregate` + +Deprecate passing the callback as a keyword argument, for the following +:class:`sqlite3.Connection` APIs: + +- :meth:`~sqlite3.Connection.set_authorizer` - +:meth:`~sqlite3.Connection.set_progress_handler` - +:meth:`~sqlite3.Connection.set_trace_callback` + +The affected parameters will become positional-only in Python 3.15. + +Patch by Erlend E. Aasland. diff --git a/Modules/_sqlite/clinic/connection.c.h b/Modules/_sqlite/clinic/connection.c.h index fe2196d0f7ee54..492ce980ee9b27 100644 --- a/Modules/_sqlite/clinic/connection.c.h +++ b/Modules/_sqlite/clinic/connection.c.h @@ -418,7 +418,12 @@ PyDoc_STRVAR(pysqlite_connection_create_function__doc__, "create_function($self, /, name, narg, func, *, deterministic=False)\n" "--\n" "\n" -"Creates a new function."); +"Creates a new function.\n" +"\n" +"Note: Passing keyword arguments \'name\', \'narg\' and \'func\' to\n" +"_sqlite3.Connection.create_function() is deprecated. Parameters\n" +"\'name\', \'narg\' and \'func\' will become positional-only in Python 3.15.\n" +""); #define PYSQLITE_CONNECTION_CREATE_FUNCTION_METHODDEF \ {"create_function", _PyCFunction_CAST(pysqlite_connection_create_function), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, pysqlite_connection_create_function__doc__}, @@ -429,6 +434,17 @@ pysqlite_connection_create_function_impl(pysqlite_Connection *self, int narg, PyObject *func, int deterministic); +// Emit compiler warnings when we get to Python 3.15. +#if PY_VERSION_HEX >= 0x030f00C0 +# error "Update the clinic input of '_sqlite3.Connection.create_function'." +#elif PY_VERSION_HEX >= 0x030f00A0 +# ifdef _MSC_VER +# pragma message ("Update the clinic input of '_sqlite3.Connection.create_function'.") +# else +# warning "Update the clinic input of '_sqlite3.Connection.create_function'." +# endif +#endif + static PyObject * pysqlite_connection_create_function(pysqlite_Connection *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { @@ -469,6 +485,16 @@ pysqlite_connection_create_function(pysqlite_Connection *self, PyTypeObject *cls if (!args) { goto exit; } + if (nargs < 3) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing keyword arguments 'name', 'narg' and 'func' to " + "_sqlite3.Connection.create_function() is deprecated. Parameters " + "'name', 'narg' and 'func' will become positional-only in Python " + "3.15.", 1)) + { + goto exit; + } + } if (!PyUnicode_Check(args[0])) { _PyArg_BadArgument("create_function", "argument 'name'", "str", args[0]); goto exit; @@ -582,7 +608,13 @@ PyDoc_STRVAR(pysqlite_connection_create_aggregate__doc__, "create_aggregate($self, /, name, n_arg, aggregate_class)\n" "--\n" "\n" -"Creates a new aggregate."); +"Creates a new aggregate.\n" +"\n" +"Note: Passing keyword arguments \'name\', \'n_arg\' and \'aggregate_class\'\n" +"to _sqlite3.Connection.create_aggregate() is deprecated. Parameters\n" +"\'name\', \'n_arg\' and \'aggregate_class\' will become positional-only in\n" +"Python 3.15.\n" +""); #define PYSQLITE_CONNECTION_CREATE_AGGREGATE_METHODDEF \ {"create_aggregate", _PyCFunction_CAST(pysqlite_connection_create_aggregate), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, pysqlite_connection_create_aggregate__doc__}, @@ -593,6 +625,17 @@ pysqlite_connection_create_aggregate_impl(pysqlite_Connection *self, const char *name, int n_arg, PyObject *aggregate_class); +// Emit compiler warnings when we get to Python 3.15. +#if PY_VERSION_HEX >= 0x030f00C0 +# error "Update the clinic input of '_sqlite3.Connection.create_aggregate'." +#elif PY_VERSION_HEX >= 0x030f00A0 +# ifdef _MSC_VER +# pragma message ("Update the clinic input of '_sqlite3.Connection.create_aggregate'.") +# else +# warning "Update the clinic input of '_sqlite3.Connection.create_aggregate'." +# endif +#endif + static PyObject * pysqlite_connection_create_aggregate(pysqlite_Connection *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { @@ -631,6 +674,16 @@ pysqlite_connection_create_aggregate(pysqlite_Connection *self, PyTypeObject *cl if (!args) { goto exit; } + if (nargs < 3) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing keyword arguments 'name', 'n_arg' and 'aggregate_class' " + "to _sqlite3.Connection.create_aggregate() is deprecated. " + "Parameters 'name', 'n_arg' and 'aggregate_class' will become " + "positional-only in Python 3.15.", 1)) + { + goto exit; + } + } if (!PyUnicode_Check(args[0])) { _PyArg_BadArgument("create_aggregate", "argument 'name'", "str", args[0]); goto exit; @@ -659,7 +712,12 @@ PyDoc_STRVAR(pysqlite_connection_set_authorizer__doc__, "set_authorizer($self, /, authorizer_callback)\n" "--\n" "\n" -"Sets authorizer callback."); +"Sets authorizer callback.\n" +"\n" +"Note: Passing keyword argument \'authorizer_callback\' to\n" +"_sqlite3.Connection.set_authorizer() is deprecated. Parameter\n" +"\'authorizer_callback\' will become positional-only in Python 3.15.\n" +""); #define PYSQLITE_CONNECTION_SET_AUTHORIZER_METHODDEF \ {"set_authorizer", _PyCFunction_CAST(pysqlite_connection_set_authorizer), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, pysqlite_connection_set_authorizer__doc__}, @@ -669,6 +727,17 @@ pysqlite_connection_set_authorizer_impl(pysqlite_Connection *self, PyTypeObject *cls, PyObject *callable); +// Emit compiler warnings when we get to Python 3.15. +#if PY_VERSION_HEX >= 0x030f00C0 +# error "Update the clinic input of '_sqlite3.Connection.set_authorizer'." +#elif PY_VERSION_HEX >= 0x030f00A0 +# ifdef _MSC_VER +# pragma message ("Update the clinic input of '_sqlite3.Connection.set_authorizer'.") +# else +# warning "Update the clinic input of '_sqlite3.Connection.set_authorizer'." +# endif +#endif + static PyObject * pysqlite_connection_set_authorizer(pysqlite_Connection *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { @@ -705,6 +774,16 @@ pysqlite_connection_set_authorizer(pysqlite_Connection *self, PyTypeObject *cls, if (!args) { goto exit; } + if (nargs < 1) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing keyword argument 'authorizer_callback' to " + "_sqlite3.Connection.set_authorizer() is deprecated. Parameter " + "'authorizer_callback' will become positional-only in Python " + "3.15.", 1)) + { + goto exit; + } + } callable = args[0]; return_value = pysqlite_connection_set_authorizer_impl(self, cls, callable); @@ -716,7 +795,12 @@ PyDoc_STRVAR(pysqlite_connection_set_progress_handler__doc__, "set_progress_handler($self, /, progress_handler, n)\n" "--\n" "\n" -"Sets progress handler callback."); +"Sets progress handler callback.\n" +"\n" +"Note: Passing keyword argument \'progress_handler\' to\n" +"_sqlite3.Connection.set_progress_handler() is deprecated. Parameter\n" +"\'progress_handler\' will become positional-only in Python 3.15.\n" +""); #define PYSQLITE_CONNECTION_SET_PROGRESS_HANDLER_METHODDEF \ {"set_progress_handler", _PyCFunction_CAST(pysqlite_connection_set_progress_handler), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, pysqlite_connection_set_progress_handler__doc__}, @@ -726,6 +810,17 @@ pysqlite_connection_set_progress_handler_impl(pysqlite_Connection *self, PyTypeObject *cls, PyObject *callable, int n); +// Emit compiler warnings when we get to Python 3.15. +#if PY_VERSION_HEX >= 0x030f00C0 +# error "Update the clinic input of '_sqlite3.Connection.set_progress_handler'." +#elif PY_VERSION_HEX >= 0x030f00A0 +# ifdef _MSC_VER +# pragma message ("Update the clinic input of '_sqlite3.Connection.set_progress_handler'.") +# else +# warning "Update the clinic input of '_sqlite3.Connection.set_progress_handler'." +# endif +#endif + static PyObject * pysqlite_connection_set_progress_handler(pysqlite_Connection *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { @@ -763,6 +858,16 @@ pysqlite_connection_set_progress_handler(pysqlite_Connection *self, PyTypeObject if (!args) { goto exit; } + if (nargs < 1) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing keyword argument 'progress_handler' to " + "_sqlite3.Connection.set_progress_handler() is deprecated. " + "Parameter 'progress_handler' will become positional-only in " + "Python 3.15.", 1)) + { + goto exit; + } + } callable = args[0]; n = _PyLong_AsInt(args[1]); if (n == -1 && PyErr_Occurred()) { @@ -778,7 +883,12 @@ PyDoc_STRVAR(pysqlite_connection_set_trace_callback__doc__, "set_trace_callback($self, /, trace_callback)\n" "--\n" "\n" -"Sets a trace callback called for each SQL statement (passed as unicode)."); +"Sets a trace callback called for each SQL statement (passed as unicode).\n" +"\n" +"Note: Passing keyword argument \'trace_callback\' to\n" +"_sqlite3.Connection.set_trace_callback() is deprecated. Parameter\n" +"\'trace_callback\' will become positional-only in Python 3.15.\n" +""); #define PYSQLITE_CONNECTION_SET_TRACE_CALLBACK_METHODDEF \ {"set_trace_callback", _PyCFunction_CAST(pysqlite_connection_set_trace_callback), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, pysqlite_connection_set_trace_callback__doc__}, @@ -788,6 +898,17 @@ pysqlite_connection_set_trace_callback_impl(pysqlite_Connection *self, PyTypeObject *cls, PyObject *callable); +// Emit compiler warnings when we get to Python 3.15. +#if PY_VERSION_HEX >= 0x030f00C0 +# error "Update the clinic input of '_sqlite3.Connection.set_trace_callback'." +#elif PY_VERSION_HEX >= 0x030f00A0 +# ifdef _MSC_VER +# pragma message ("Update the clinic input of '_sqlite3.Connection.set_trace_callback'.") +# else +# warning "Update the clinic input of '_sqlite3.Connection.set_trace_callback'." +# endif +#endif + static PyObject * pysqlite_connection_set_trace_callback(pysqlite_Connection *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { @@ -824,6 +945,16 @@ pysqlite_connection_set_trace_callback(pysqlite_Connection *self, PyTypeObject * if (!args) { goto exit; } + if (nargs < 1) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing keyword argument 'trace_callback' to " + "_sqlite3.Connection.set_trace_callback() is deprecated. " + "Parameter 'trace_callback' will become positional-only in Python" + " 3.15.", 1)) + { + goto exit; + } + } callable = args[0]; return_value = pysqlite_connection_set_trace_callback_impl(self, cls, callable); @@ -1681,4 +1812,4 @@ getconfig(pysqlite_Connection *self, PyObject *arg) #ifndef DESERIALIZE_METHODDEF #define DESERIALIZE_METHODDEF #endif /* !defined(DESERIALIZE_METHODDEF) */ -/*[clinic end generated code: output=0ad9d55977a51b8f input=a9049054013a1b77]*/ +/*[clinic end generated code: output=9caa8f706e0d6f50 input=a9049054013a1b77]*/ diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index e133977b28c378..c38ca906c35898 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -1139,6 +1139,7 @@ _sqlite3.Connection.create_function as pysqlite_connection_create_function name: str narg: int func: object + / [from 3.15] * deterministic: bool = False @@ -1150,7 +1151,7 @@ pysqlite_connection_create_function_impl(pysqlite_Connection *self, PyTypeObject *cls, const char *name, int narg, PyObject *func, int deterministic) -/*[clinic end generated code: output=8a811529287ad240 input=b3e8e1d8ddaffbef]*/ +/*[clinic end generated code: output=8a811529287ad240 input=c7c313b0ca8b519e]*/ { int rc; int flags = SQLITE_UTF8; @@ -1341,6 +1342,7 @@ _sqlite3.Connection.create_aggregate as pysqlite_connection_create_aggregate name: str n_arg: int aggregate_class: object + / [from 3.15] Creates a new aggregate. [clinic start generated code]*/ @@ -1350,7 +1352,7 @@ pysqlite_connection_create_aggregate_impl(pysqlite_Connection *self, PyTypeObject *cls, const char *name, int n_arg, PyObject *aggregate_class) -/*[clinic end generated code: output=1b02d0f0aec7ff96 input=68a2a26366d4c686]*/ +/*[clinic end generated code: output=1b02d0f0aec7ff96 input=8087056db6eae1cf]*/ { int rc; @@ -1499,6 +1501,7 @@ _sqlite3.Connection.set_authorizer as pysqlite_connection_set_authorizer cls: defining_class / authorizer_callback as callable: object + / [from 3.15] Sets authorizer callback. [clinic start generated code]*/ @@ -1507,7 +1510,7 @@ static PyObject * pysqlite_connection_set_authorizer_impl(pysqlite_Connection *self, PyTypeObject *cls, PyObject *callable) -/*[clinic end generated code: output=75fa60114fc971c3 input=605d32ba92dd3eca]*/ +/*[clinic end generated code: output=75fa60114fc971c3 input=d4bf5013974daf98]*/ { if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; @@ -1541,6 +1544,7 @@ _sqlite3.Connection.set_progress_handler as pysqlite_connection_set_progress_han cls: defining_class / progress_handler as callable: object + / [from 3.15] n: int Sets progress handler callback. @@ -1550,7 +1554,7 @@ static PyObject * pysqlite_connection_set_progress_handler_impl(pysqlite_Connection *self, PyTypeObject *cls, PyObject *callable, int n) -/*[clinic end generated code: output=0739957fd8034a50 input=f7c1837984bd86db]*/ +/*[clinic end generated code: output=0739957fd8034a50 input=9c8776d84cefd42b]*/ { if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; @@ -1578,6 +1582,7 @@ _sqlite3.Connection.set_trace_callback as pysqlite_connection_set_trace_callback cls: defining_class / trace_callback as callable: object + / [from 3.15] Sets a trace callback called for each SQL statement (passed as unicode). [clinic start generated code]*/ @@ -1586,7 +1591,7 @@ static PyObject * pysqlite_connection_set_trace_callback_impl(pysqlite_Connection *self, PyTypeObject *cls, PyObject *callable) -/*[clinic end generated code: output=d91048c03bfcee05 input=351a94210c5f81bb]*/ +/*[clinic end generated code: output=d91048c03bfcee05 input=69944bec571b97d2]*/ { if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; From 634217b3edd1e95e7c95b0e641076f67b9e74d35 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 22 Aug 2023 14:21:51 +0200 Subject: [PATCH 2/7] Sphinx fixup --- Doc/whatsnew/3.13.rst | 10 +++++----- .../2023-08-22-13-51-10.gh-issue-108278.11d_qG.rst | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index 451c5635cef69b..556677ebf92cfd 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -256,17 +256,17 @@ Deprecated Deprecate passing name, number of arguments, and the callable as keyword arguments, for the following :class:`sqlite3.Connection` APIs: - - :meth:`~sqlite3.Connection.create_function` - - :meth:`~sqlite3.Connection.create_aggregate` + * :meth:`~sqlite3.Connection.create_function` + * :meth:`~sqlite3.Connection.create_aggregate` The affected parameters will become positional-only in Python 3.15. Deprecate passing the callback as a keyword argument, for the following :class:`sqlite3.Connection` APIs: - - :meth:`~sqlite3.Connection.set_authorizer` - - :meth:`~sqlite3.Connection.set_progress_handler` - - :meth:`~sqlite3.Connection.set_trace_callback` + * :meth:`~sqlite3.Connection.set_authorizer` + * :meth:`~sqlite3.Connection.set_progress_handler` + * :meth:`~sqlite3.Connection.set_trace_callback` The affected parameters will become positional-only in Python 3.15. (Contributed by Erlend E. Aasland in :gh:`107948` and :gh:`108278`.) diff --git a/Misc/NEWS.d/next/Library/2023-08-22-13-51-10.gh-issue-108278.11d_qG.rst b/Misc/NEWS.d/next/Library/2023-08-22-13-51-10.gh-issue-108278.11d_qG.rst index d4b32cade54ecb..0128c9ee270828 100644 --- a/Misc/NEWS.d/next/Library/2023-08-22-13-51-10.gh-issue-108278.11d_qG.rst +++ b/Misc/NEWS.d/next/Library/2023-08-22-13-51-10.gh-issue-108278.11d_qG.rst @@ -1,15 +1,15 @@ Deprecate passing name, number of arguments, and the callable as keyword arguments, for the following :class:`sqlite3.Connection` APIs: -- :meth:`~sqlite3.Connection.create_function` - -:meth:`~sqlite3.Connection.create_aggregate` +* :meth:`~sqlite3.Connection.create_function` +* :meth:`~sqlite3.Connection.create_aggregate` Deprecate passing the callback as a keyword argument, for the following :class:`sqlite3.Connection` APIs: -- :meth:`~sqlite3.Connection.set_authorizer` - -:meth:`~sqlite3.Connection.set_progress_handler` - -:meth:`~sqlite3.Connection.set_trace_callback` +* :meth:`~sqlite3.Connection.set_authorizer` +* :meth:`~sqlite3.Connection.set_progress_handler` +* :meth:`~sqlite3.Connection.set_trace_callback` The affected parameters will become positional-only in Python 3.15. From cedd33a0d6a402708925a5388c0528c60ba3692c Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 23 Aug 2023 10:36:19 +0200 Subject: [PATCH 3/7] Restrict PR to only touch the UDF creation APIs --- Doc/whatsnew/3.13.rst | 7 -- ...-08-22-13-51-10.gh-issue-108278.11d_qG.rst | 7 -- Modules/_sqlite/clinic/connection.c.h | 86 +------------------ Modules/_sqlite/connection.c | 9 +- 4 files changed, 7 insertions(+), 102 deletions(-) diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index 556677ebf92cfd..0f7c267aa0bc5f 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -261,13 +261,6 @@ Deprecated The affected parameters will become positional-only in Python 3.15. - Deprecate passing the callback as a keyword argument, for the following - :class:`sqlite3.Connection` APIs: - - * :meth:`~sqlite3.Connection.set_authorizer` - * :meth:`~sqlite3.Connection.set_progress_handler` - * :meth:`~sqlite3.Connection.set_trace_callback` - The affected parameters will become positional-only in Python 3.15. (Contributed by Erlend E. Aasland in :gh:`107948` and :gh:`108278`.) diff --git a/Misc/NEWS.d/next/Library/2023-08-22-13-51-10.gh-issue-108278.11d_qG.rst b/Misc/NEWS.d/next/Library/2023-08-22-13-51-10.gh-issue-108278.11d_qG.rst index 0128c9ee270828..85bedc1f3f852d 100644 --- a/Misc/NEWS.d/next/Library/2023-08-22-13-51-10.gh-issue-108278.11d_qG.rst +++ b/Misc/NEWS.d/next/Library/2023-08-22-13-51-10.gh-issue-108278.11d_qG.rst @@ -4,13 +4,6 @@ arguments, for the following :class:`sqlite3.Connection` APIs: * :meth:`~sqlite3.Connection.create_function` * :meth:`~sqlite3.Connection.create_aggregate` -Deprecate passing the callback as a keyword argument, for the following -:class:`sqlite3.Connection` APIs: - -* :meth:`~sqlite3.Connection.set_authorizer` -* :meth:`~sqlite3.Connection.set_progress_handler` -* :meth:`~sqlite3.Connection.set_trace_callback` - The affected parameters will become positional-only in Python 3.15. Patch by Erlend E. Aasland. diff --git a/Modules/_sqlite/clinic/connection.c.h b/Modules/_sqlite/clinic/connection.c.h index 492ce980ee9b27..3b029ee1981788 100644 --- a/Modules/_sqlite/clinic/connection.c.h +++ b/Modules/_sqlite/clinic/connection.c.h @@ -712,12 +712,7 @@ PyDoc_STRVAR(pysqlite_connection_set_authorizer__doc__, "set_authorizer($self, /, authorizer_callback)\n" "--\n" "\n" -"Sets authorizer callback.\n" -"\n" -"Note: Passing keyword argument \'authorizer_callback\' to\n" -"_sqlite3.Connection.set_authorizer() is deprecated. Parameter\n" -"\'authorizer_callback\' will become positional-only in Python 3.15.\n" -""); +"Sets authorizer callback."); #define PYSQLITE_CONNECTION_SET_AUTHORIZER_METHODDEF \ {"set_authorizer", _PyCFunction_CAST(pysqlite_connection_set_authorizer), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, pysqlite_connection_set_authorizer__doc__}, @@ -727,17 +722,6 @@ pysqlite_connection_set_authorizer_impl(pysqlite_Connection *self, PyTypeObject *cls, PyObject *callable); -// Emit compiler warnings when we get to Python 3.15. -#if PY_VERSION_HEX >= 0x030f00C0 -# error "Update the clinic input of '_sqlite3.Connection.set_authorizer'." -#elif PY_VERSION_HEX >= 0x030f00A0 -# ifdef _MSC_VER -# pragma message ("Update the clinic input of '_sqlite3.Connection.set_authorizer'.") -# else -# warning "Update the clinic input of '_sqlite3.Connection.set_authorizer'." -# endif -#endif - static PyObject * pysqlite_connection_set_authorizer(pysqlite_Connection *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { @@ -774,16 +758,6 @@ pysqlite_connection_set_authorizer(pysqlite_Connection *self, PyTypeObject *cls, if (!args) { goto exit; } - if (nargs < 1) { - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "Passing keyword argument 'authorizer_callback' to " - "_sqlite3.Connection.set_authorizer() is deprecated. Parameter " - "'authorizer_callback' will become positional-only in Python " - "3.15.", 1)) - { - goto exit; - } - } callable = args[0]; return_value = pysqlite_connection_set_authorizer_impl(self, cls, callable); @@ -795,12 +769,7 @@ PyDoc_STRVAR(pysqlite_connection_set_progress_handler__doc__, "set_progress_handler($self, /, progress_handler, n)\n" "--\n" "\n" -"Sets progress handler callback.\n" -"\n" -"Note: Passing keyword argument \'progress_handler\' to\n" -"_sqlite3.Connection.set_progress_handler() is deprecated. Parameter\n" -"\'progress_handler\' will become positional-only in Python 3.15.\n" -""); +"Sets progress handler callback."); #define PYSQLITE_CONNECTION_SET_PROGRESS_HANDLER_METHODDEF \ {"set_progress_handler", _PyCFunction_CAST(pysqlite_connection_set_progress_handler), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, pysqlite_connection_set_progress_handler__doc__}, @@ -810,17 +779,6 @@ pysqlite_connection_set_progress_handler_impl(pysqlite_Connection *self, PyTypeObject *cls, PyObject *callable, int n); -// Emit compiler warnings when we get to Python 3.15. -#if PY_VERSION_HEX >= 0x030f00C0 -# error "Update the clinic input of '_sqlite3.Connection.set_progress_handler'." -#elif PY_VERSION_HEX >= 0x030f00A0 -# ifdef _MSC_VER -# pragma message ("Update the clinic input of '_sqlite3.Connection.set_progress_handler'.") -# else -# warning "Update the clinic input of '_sqlite3.Connection.set_progress_handler'." -# endif -#endif - static PyObject * pysqlite_connection_set_progress_handler(pysqlite_Connection *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { @@ -858,16 +816,6 @@ pysqlite_connection_set_progress_handler(pysqlite_Connection *self, PyTypeObject if (!args) { goto exit; } - if (nargs < 1) { - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "Passing keyword argument 'progress_handler' to " - "_sqlite3.Connection.set_progress_handler() is deprecated. " - "Parameter 'progress_handler' will become positional-only in " - "Python 3.15.", 1)) - { - goto exit; - } - } callable = args[0]; n = _PyLong_AsInt(args[1]); if (n == -1 && PyErr_Occurred()) { @@ -883,12 +831,7 @@ PyDoc_STRVAR(pysqlite_connection_set_trace_callback__doc__, "set_trace_callback($self, /, trace_callback)\n" "--\n" "\n" -"Sets a trace callback called for each SQL statement (passed as unicode).\n" -"\n" -"Note: Passing keyword argument \'trace_callback\' to\n" -"_sqlite3.Connection.set_trace_callback() is deprecated. Parameter\n" -"\'trace_callback\' will become positional-only in Python 3.15.\n" -""); +"Sets a trace callback called for each SQL statement (passed as unicode)."); #define PYSQLITE_CONNECTION_SET_TRACE_CALLBACK_METHODDEF \ {"set_trace_callback", _PyCFunction_CAST(pysqlite_connection_set_trace_callback), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, pysqlite_connection_set_trace_callback__doc__}, @@ -898,17 +841,6 @@ pysqlite_connection_set_trace_callback_impl(pysqlite_Connection *self, PyTypeObject *cls, PyObject *callable); -// Emit compiler warnings when we get to Python 3.15. -#if PY_VERSION_HEX >= 0x030f00C0 -# error "Update the clinic input of '_sqlite3.Connection.set_trace_callback'." -#elif PY_VERSION_HEX >= 0x030f00A0 -# ifdef _MSC_VER -# pragma message ("Update the clinic input of '_sqlite3.Connection.set_trace_callback'.") -# else -# warning "Update the clinic input of '_sqlite3.Connection.set_trace_callback'." -# endif -#endif - static PyObject * pysqlite_connection_set_trace_callback(pysqlite_Connection *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { @@ -945,16 +877,6 @@ pysqlite_connection_set_trace_callback(pysqlite_Connection *self, PyTypeObject * if (!args) { goto exit; } - if (nargs < 1) { - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "Passing keyword argument 'trace_callback' to " - "_sqlite3.Connection.set_trace_callback() is deprecated. " - "Parameter 'trace_callback' will become positional-only in Python" - " 3.15.", 1)) - { - goto exit; - } - } callable = args[0]; return_value = pysqlite_connection_set_trace_callback_impl(self, cls, callable); @@ -1812,4 +1734,4 @@ getconfig(pysqlite_Connection *self, PyObject *arg) #ifndef DESERIALIZE_METHODDEF #define DESERIALIZE_METHODDEF #endif /* !defined(DESERIALIZE_METHODDEF) */ -/*[clinic end generated code: output=9caa8f706e0d6f50 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=575f9a692378ad6a input=a9049054013a1b77]*/ diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index c38ca906c35898..0fc0d8d4cbc3e4 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -1501,7 +1501,6 @@ _sqlite3.Connection.set_authorizer as pysqlite_connection_set_authorizer cls: defining_class / authorizer_callback as callable: object - / [from 3.15] Sets authorizer callback. [clinic start generated code]*/ @@ -1510,7 +1509,7 @@ static PyObject * pysqlite_connection_set_authorizer_impl(pysqlite_Connection *self, PyTypeObject *cls, PyObject *callable) -/*[clinic end generated code: output=75fa60114fc971c3 input=d4bf5013974daf98]*/ +/*[clinic end generated code: output=75fa60114fc971c3 input=605d32ba92dd3eca]*/ { if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; @@ -1544,7 +1543,6 @@ _sqlite3.Connection.set_progress_handler as pysqlite_connection_set_progress_han cls: defining_class / progress_handler as callable: object - / [from 3.15] n: int Sets progress handler callback. @@ -1554,7 +1552,7 @@ static PyObject * pysqlite_connection_set_progress_handler_impl(pysqlite_Connection *self, PyTypeObject *cls, PyObject *callable, int n) -/*[clinic end generated code: output=0739957fd8034a50 input=9c8776d84cefd42b]*/ +/*[clinic end generated code: output=0739957fd8034a50 input=f7c1837984bd86db]*/ { if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; @@ -1582,7 +1580,6 @@ _sqlite3.Connection.set_trace_callback as pysqlite_connection_set_trace_callback cls: defining_class / trace_callback as callable: object - / [from 3.15] Sets a trace callback called for each SQL statement (passed as unicode). [clinic start generated code]*/ @@ -1591,7 +1588,7 @@ static PyObject * pysqlite_connection_set_trace_callback_impl(pysqlite_Connection *self, PyTypeObject *cls, PyObject *callable) -/*[clinic end generated code: output=d91048c03bfcee05 input=69944bec571b97d2]*/ +/*[clinic end generated code: output=d91048c03bfcee05 input=351a94210c5f81bb]*/ { if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; From 54e35d53a675f7d8ed16f0acc39fe1c1688981f3 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 23 Aug 2023 10:39:14 +0200 Subject: [PATCH 4/7] Update docs --- Doc/library/sqlite3.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst index 0b53f97b284f07..0d7abae6de2694 100644 --- a/Doc/library/sqlite3.rst +++ b/Doc/library/sqlite3.rst @@ -763,6 +763,11 @@ Connection objects ... print(row) ('acbd18db4cc2f85cedef654fccc4a4d8',) + .. versionchanged:: 3.13 + + Passing *name*, *narg*, and *func* as keyword arguments is deprecated. + These parameters will become positional-only in Python 3.15. + .. method:: create_aggregate(name, n_arg, aggregate_class) @@ -817,6 +822,11 @@ Connection objects 3 + .. versionchanged:: 3.13 + + Passing *name*, *n_arg*, and *aggregate_class* as keyword arguments is deprecated. + These parameters will become positional-only in Python 3.15. + .. method:: create_window_function(name, num_params, aggregate_class, /) From 833197abe60f2cfdf61dad8dfb0216dee922072f Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 23 Aug 2023 11:18:03 +0200 Subject: [PATCH 5/7] Add test --- Lib/test/test_sqlite3/test_userfunctions.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Lib/test/test_sqlite3/test_userfunctions.py b/Lib/test/test_sqlite3/test_userfunctions.py index 5d12636dcd2b63..8ae04ddbf989a6 100644 --- a/Lib/test/test_sqlite3/test_userfunctions.py +++ b/Lib/test/test_sqlite3/test_userfunctions.py @@ -421,6 +421,26 @@ def test_func_return_illegal_value(self): self.assertRaisesRegex(sqlite.OperationalError, msg, self.con.execute, "select badreturn()") + def test_func_keyword_args(self): + regex = ( + r"Passing keyword arguments 'name', 'narg' and 'func' to " + r"_sqlite3.Connection.create_function\(\) is deprecated. " + r"Parameters 'name', 'narg' and 'func' will become " + r"positional-only in Python 3.15." + ) + + def check(*args, **kwds): + with self.assertWarnsRegex(DeprecationWarning, regex) as cm: + self.con.create_function(*args, **kwds) + self.assertEqual(cm.filename, __file__) + + def noop(): + return None + + check("noop", 0, func=noop) + check("noop", narg=0, func=noop) + check(name="noop", narg=0, func=noop) + class WindowSumInt: def __init__(self): From 661cd7a842c2ef7bdfdc1c0eb6f6587b7b7bc087 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 23 Aug 2023 11:21:28 +0200 Subject: [PATCH 6/7] Update Doc/whatsnew/3.13.rst --- Doc/whatsnew/3.13.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index 0f7c267aa0bc5f..a866ef2e35e883 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -261,7 +261,6 @@ Deprecated The affected parameters will become positional-only in Python 3.15. - The affected parameters will become positional-only in Python 3.15. (Contributed by Erlend E. Aasland in :gh:`107948` and :gh:`108278`.) Pending Removal in Python 3.14 From 15cf809c2526ccbab89761fb9e604628ecd1f08c Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Mon, 28 Aug 2023 14:48:28 +0200 Subject: [PATCH 7/7] Address review: inline tests --- Lib/test/test_sqlite3/test_userfunctions.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/Lib/test/test_sqlite3/test_userfunctions.py b/Lib/test/test_sqlite3/test_userfunctions.py index 8ae04ddbf989a6..d86b8c6025f671 100644 --- a/Lib/test/test_sqlite3/test_userfunctions.py +++ b/Lib/test/test_sqlite3/test_userfunctions.py @@ -429,17 +429,20 @@ def test_func_keyword_args(self): r"positional-only in Python 3.15." ) - def check(*args, **kwds): - with self.assertWarnsRegex(DeprecationWarning, regex) as cm: - self.con.create_function(*args, **kwds) - self.assertEqual(cm.filename, __file__) - def noop(): return None - check("noop", 0, func=noop) - check("noop", narg=0, func=noop) - check(name="noop", narg=0, func=noop) + with self.assertWarnsRegex(DeprecationWarning, regex) as cm: + self.con.create_function("noop", 0, func=noop) + self.assertEqual(cm.filename, __file__) + + with self.assertWarnsRegex(DeprecationWarning, regex) as cm: + self.con.create_function("noop", narg=0, func=noop) + self.assertEqual(cm.filename, __file__) + + with self.assertWarnsRegex(DeprecationWarning, regex) as cm: + self.con.create_function(name="noop", narg=0, func=noop) + self.assertEqual(cm.filename, __file__) class WindowSumInt: