]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-93057: Deprecate positional use of optional sqlite3.connect() params (#107948)
authorErlend E. Aasland <erlend@python.org>
Tue, 15 Aug 2023 08:09:56 +0000 (10:09 +0200)
committerGitHub <noreply@github.com>
Tue, 15 Aug 2023 08:09:56 +0000 (08:09 +0000)
Doc/library/sqlite3.rst
Doc/whatsnew/3.13.rst
Lib/test/test_sqlite3/test_dbapi.py
Lib/test/test_sqlite3/test_factory.py
Misc/NEWS.d/next/Library/2023-08-14-19-49-02.gh-issue-93057.5nJwO5.rst [new file with mode: 0644]
Modules/_sqlite/clinic/_sqlite3.connect.c.h
Modules/_sqlite/clinic/connection.c.h
Modules/_sqlite/connection.c
Modules/_sqlite/module.c

index 50344058c26041cffad9976219623bad5ef836af..5f1676e5ae2f562acf7be1958607af1e6a8e2a4d 100644 (file)
@@ -355,6 +355,12 @@ Module functions
    .. versionadded:: 3.12
       The *autocommit* parameter.
 
+   .. versionchanged:: 3.13
+      Positional use of the parameters *timeout*, *detect_types*,
+      *isolation_level*, *check_same_thread*, *factory*, *cached_statements*,
+      and *uri* is deprecated.
+      They will become keyword-only parameters in Python 3.15.
+
 .. function:: complete_statement(statement)
 
    Return ``True`` if the string *statement* appears to contain
index 63cdee6cf1a4f39dfd6d146cd5f16677196d4dea..a65a98bae13579ea80085dbac08cc341a83b122d 100644 (file)
@@ -219,6 +219,11 @@ Deprecated
   They will be removed in Python 3.15.
   (Contributed by Victor Stinner in :gh:`105096`.)
 
+* 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`.)
+
 Pending Removal in Python 3.14
 ------------------------------
 
index 3f9bd0248a8b96d27fd31fed72b560a01be4ab94..c9a9e1353938c6c6d4706f3d1a4ec1fe95a7b21f 100644 (file)
@@ -582,6 +582,19 @@ class ConnectionTests(unittest.TestCase):
             with self.assertRaisesRegex(sqlite.IntegrityError, "constraint"):
                 cx.execute("insert into u values(0)")
 
+    def test_connect_positional_arguments(self):
+        regex = (
+            r"Passing more than 1 positional argument to sqlite3.connect\(\)"
+            " is deprecated. Parameters 'timeout', 'detect_types', "
+            "'isolation_level', 'check_same_thread', 'factory', "
+            "'cached_statements' and 'uri' will become keyword-only "
+            "parameters in Python 3.15."
+        )
+        with self.assertWarnsRegex(DeprecationWarning, regex) as cm:
+            sqlite.connect(":memory:", 1.0)
+        self.assertEqual(cm.filename, __file__)
+
+
 
 class UninitialisedConnectionTests(unittest.TestCase):
     def setUp(self):
index 7c36135ecadccd7cb26169fd3cf67f883b819977..d63589483e1042a9204ca030ea2c5492624b8fc7 100644 (file)
@@ -66,7 +66,16 @@ class ConnectionFactoryTests(unittest.TestCase):
             def __init__(self, *args, **kwargs):
                 super(Factory, self).__init__(*args, **kwargs)
 
-        con = sqlite.connect(":memory:", 5.0, 0, None, True, Factory)
+        regex = (
+            r"Passing more than 1 positional argument to _sqlite3.Connection\(\) "
+            r"is deprecated. Parameters 'timeout', 'detect_types', "
+            r"'isolation_level', 'check_same_thread', 'factory', "
+            r"'cached_statements' and 'uri' will become keyword-only "
+            r"parameters in Python 3.15."
+        )
+        with self.assertWarnsRegex(DeprecationWarning, regex) as cm:
+            con = sqlite.connect(":memory:", 5.0, 0, None, True, Factory)
+        self.assertEqual(cm.filename, __file__)
         self.assertIsNone(con.isolation_level)
         self.assertIsInstance(con, Factory)
 
diff --git a/Misc/NEWS.d/next/Library/2023-08-14-19-49-02.gh-issue-93057.5nJwO5.rst b/Misc/NEWS.d/next/Library/2023-08-14-19-49-02.gh-issue-93057.5nJwO5.rst
new file mode 100644 (file)
index 0000000..6a4feaa
--- /dev/null
@@ -0,0 +1,3 @@
+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. Patch by Erlend E. Aasland.
index 0c4ebdf0590c9e9d730a6cefc3af79c5c96de1ef..998c8de1e09f1648f1e1909009d7a9a94a9ec07f 100644 (file)
@@ -18,8 +18,14 @@ PyDoc_STRVAR(pysqlite_connect__doc__,
 "Open a connection to the SQLite database file \'database\'.\n"
 "\n"
 "You can use \":memory:\" to open a database connection to a database that\n"
-"resides in RAM instead of on disk.");
+"resides in RAM instead of on disk.\n"
+"\n"
+"Note: Passing more than 1 positional argument to _sqlite3.connect() is\n"
+"deprecated. Parameters \'timeout\', \'detect_types\', \'isolation_level\',\n"
+"\'check_same_thread\', \'factory\', \'cached_statements\' and \'uri\' will\n"
+"become keyword-only parameters in Python 3.15.\n"
+"");
 
 #define PYSQLITE_CONNECT_METHODDEF    \
     {"connect", _PyCFunction_CAST(pysqlite_connect), METH_FASTCALL|METH_KEYWORDS, pysqlite_connect__doc__},
-/*[clinic end generated code: output=6a8458c9edf8fb7f input=a9049054013a1b77]*/
+/*[clinic end generated code: output=8d49736db880f09a input=a9049054013a1b77]*/
index e869d7d9e9384c571ce191abb51ede21dbc4023f..af98d61ea7ccccb9b507f5a53eb4a5b2a1a62f73 100644 (file)
@@ -59,6 +59,39 @@ pysqlite_connection_init(PyObject *self, PyObject *args, PyObject *kwargs)
     int uri = 0;
     enum autocommit_mode autocommit = LEGACY_TRANSACTION_CONTROL;
 
+    // Emit compiler warnings when we get to Python 3.15.
+    #if PY_VERSION_HEX >= 0x030f00C0
+    #  error \
+            "In connection.c, update parameter(s) 'timeout', 'detect_types', " \
+            "'isolation_level', 'check_same_thread', 'factory', " \
+            "'cached_statements' and 'uri' in the clinic input of " \
+            "'_sqlite3.Connection.__init__' to be keyword-only."
+    #elif PY_VERSION_HEX >= 0x030f00A0
+    #  ifdef _MSC_VER
+    #    pragma message ( \
+            "In connection.c, update parameter(s) 'timeout', 'detect_types', " \
+            "'isolation_level', 'check_same_thread', 'factory', " \
+            "'cached_statements' and 'uri' in the clinic input of " \
+            "'_sqlite3.Connection.__init__' to be keyword-only.")
+    #  else
+    #    warning \
+            "In connection.c, update parameter(s) 'timeout', 'detect_types', " \
+            "'isolation_level', 'check_same_thread', 'factory', " \
+            "'cached_statements' and 'uri' in the clinic input of " \
+            "'_sqlite3.Connection.__init__' to be keyword-only."
+    #  endif
+    #endif
+    if (nargs > 1 && nargs <= 8) {
+        if (PyErr_WarnEx(PyExc_DeprecationWarning,
+                "Passing more than 1 positional argument to _sqlite3.Connection()"
+                " is deprecated. Parameters 'timeout', 'detect_types', "
+                "'isolation_level', 'check_same_thread', 'factory', "
+                "'cached_statements' and 'uri' will become keyword-only "
+                "parameters in Python 3.15.", 1))
+        {
+                goto exit;
+        }
+    }
     fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 1, 8, 0, argsbuf);
     if (!fastargs) {
         goto exit;
@@ -1659,4 +1692,4 @@ exit:
 #ifndef DESERIALIZE_METHODDEF
     #define DESERIALIZE_METHODDEF
 #endif /* !defined(DESERIALIZE_METHODDEF) */
-/*[clinic end generated code: output=d3c6cb9326736ea5 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=5a05e5294ad9d2ce input=a9049054013a1b77]*/
index 3d2fcd3ae0788efb6225c2d9e9049a2030479f46..0819acd09409648e6b0b10bfcedb7b7f551b4706 100644 (file)
@@ -216,6 +216,7 @@ class sqlite3_int64_converter(CConverter):
 _sqlite3.Connection.__init__ as pysqlite_connection_init
 
     database: object
+    * [from 3.15]
     timeout: double = 5.0
     detect_types: int = 0
     isolation_level: IsolationLevel = ""
@@ -234,7 +235,7 @@ pysqlite_connection_init_impl(pysqlite_Connection *self, PyObject *database,
                               int check_same_thread, PyObject *factory,
                               int cache_size, int uri,
                               enum autocommit_mode autocommit)
-/*[clinic end generated code: output=cba057313ea7712f input=9b0ab6c12f674fa3]*/
+/*[clinic end generated code: output=cba057313ea7712f input=219c3dbecbae7d99]*/
 {
     if (PySys_Audit("sqlite3.connect", "O", database) < 0) {
         return -1;
index 0c503dfbebbd6c7b7cbcaf7f86a05f87c85f09da..dd45ffc1988f7e5d91fe3eedebd32f8b86a6c9d3 100644 (file)
@@ -64,6 +64,17 @@ pysqlite_connect(PyObject *module, PyObject *const *args, Py_ssize_t nargsf,
 
     static const int FACTORY_POS = 5;
     Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
+    if (nargs > 1 && nargs <= 8) {
+        if (PyErr_WarnEx(PyExc_DeprecationWarning,
+                "Passing more than 1 positional argument to sqlite3.connect()"
+                " is deprecated. Parameters 'timeout', 'detect_types', "
+                "'isolation_level', 'check_same_thread', 'factory', "
+                "'cached_statements' and 'uri' will become keyword-only "
+                "parameters in Python 3.15.", 1))
+        {
+                return NULL;
+        }
+    }
     if (nargs > FACTORY_POS) {
         factory = args[FACTORY_POS];
     }