]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-42064: Move `sqlite3` exceptions to global state, part 1 of 2 (GH-26745)
authorErlend Egeberg Aasland <erlend.aasland@innova.no>
Wed, 23 Jun 2021 12:56:40 +0000 (14:56 +0200)
committerGitHub <noreply@github.com>
Wed, 23 Jun 2021 12:56:40 +0000 (05:56 -0700)
Also adds a test to verify the (borrowed) exceptions in `sqlite3.Connection`.

Lib/sqlite3/test/dbapi.py
Modules/_sqlite/connection.c
Modules/_sqlite/cursor.c
Modules/_sqlite/module.c
Modules/_sqlite/module.h
Modules/_sqlite/statement.c
Modules/_sqlite/util.c
Tools/c-analyzer/cpython/ignored.tsv

index c9bcac9bb832757754a3239cf68db17dcc654f11..7e44cac76f5b351ef95035be0ca91fd4614a785d 100644 (file)
@@ -208,6 +208,24 @@ class ConnectionTests(unittest.TestCase):
         with self.assertRaises(AttributeError):
             self.cx.in_transaction = True
 
+    def test_connection_exceptions(self):
+        exceptions = [
+            "DataError",
+            "DatabaseError",
+            "Error",
+            "IntegrityError",
+            "InterfaceError",
+            "NotSupportedError",
+            "OperationalError",
+            "ProgrammingError",
+            "Warning",
+        ]
+        for exc in exceptions:
+            with self.subTest(exc=exc):
+                self.assertTrue(hasattr(self.cx, exc))
+                self.assertIs(getattr(sqlite, exc), getattr(self.cx, exc))
+
+
 class OpenTests(unittest.TestCase):
     _sql = "create table test(id integer)"
 
index 11656b8a90034261061363a57f3974037ae80cb1..3e12679cd14c0a1209ca91055dc1526afe82a4d3 100644 (file)
@@ -182,14 +182,15 @@ pysqlite_connection_init_impl(pysqlite_Connection *self,
         return -1;
     }
 
-    self->Warning               = pysqlite_Warning;
-    self->Error                 = pysqlite_Error;
-    self->InterfaceError        = pysqlite_InterfaceError;
-    self->DatabaseError         = pysqlite_DatabaseError;
+    pysqlite_state *state = pysqlite_get_state(NULL);
+    self->Warning               = state->Warning;
+    self->Error                 = state->Error;
+    self->InterfaceError        = state->InterfaceError;
+    self->DatabaseError         = state->DatabaseError;
     self->DataError             = pysqlite_DataError;
     self->OperationalError      = pysqlite_OperationalError;
     self->IntegrityError        = pysqlite_IntegrityError;
-    self->InternalError         = pysqlite_InternalError;
+    self->InternalError         = state->InternalError;
     self->ProgrammingError      = pysqlite_ProgrammingError;
     self->NotSupportedError     = pysqlite_NotSupportedError;
 
index 8e7d65faa2851e6badd0fb2906bd31485aa66805..451742b3ecda5362e87867aa75c7f96b64b7ad36 100644 (file)
@@ -272,7 +272,8 @@ _pysqlite_fetch_one_row(pysqlite_Cursor* self)
     PyObject* error_msg;
 
     if (self->reset) {
-        PyErr_SetString(pysqlite_InterfaceError, errmsg_fetch_across_rollback);
+        PyObject *exc = self->connection->InterfaceError;
+        PyErr_SetString(exc, errmsg_fetch_across_rollback);
         return NULL;
     }
 
@@ -822,7 +823,8 @@ pysqlite_cursor_iternext(pysqlite_Cursor *self)
     }
 
     if (self->reset) {
-        PyErr_SetString(pysqlite_InterfaceError, errmsg_fetch_across_rollback);
+        PyObject *exc = self->connection->InterfaceError;
+        PyErr_SetString(exc, errmsg_fetch_across_rollback);
         return NULL;
     }
 
index 6adadf69216396e7e47237a818f01c9ab0fc350d..2607c6ee3b475a79ce9ce21b2eb40199798d965c 100644 (file)
@@ -43,11 +43,6 @@ module _sqlite3
 
 /* static objects at module-level */
 
-PyObject *pysqlite_Error = NULL;
-PyObject *pysqlite_Warning = NULL;
-PyObject *pysqlite_InterfaceError = NULL;
-PyObject *pysqlite_DatabaseError = NULL;
-PyObject *pysqlite_InternalError = NULL;
 PyObject *pysqlite_OperationalError = NULL;
 PyObject *pysqlite_ProgrammingError = NULL;
 PyObject *pysqlite_IntegrityError = NULL;
@@ -409,20 +404,27 @@ PyMODINIT_FUNC PyInit__sqlite3(void)
     ADD_TYPE(module, state->RowType);
 
     /*** Create DB-API Exception hierarchy */
-    ADD_EXCEPTION(module, "Error", pysqlite_Error, PyExc_Exception);
-    ADD_EXCEPTION(module, "Warning", pysqlite_Warning, PyExc_Exception);
+    ADD_EXCEPTION(module, "Error", state->Error, PyExc_Exception);
+    ADD_EXCEPTION(module, "Warning", state->Warning, PyExc_Exception);
 
     /* Error subclasses */
-    ADD_EXCEPTION(module, "InterfaceError", pysqlite_InterfaceError, pysqlite_Error);
-    ADD_EXCEPTION(module, "DatabaseError", pysqlite_DatabaseError, pysqlite_Error);
-
-    /* pysqlite_DatabaseError subclasses */
-    ADD_EXCEPTION(module, "InternalError", pysqlite_InternalError, pysqlite_DatabaseError);
-    ADD_EXCEPTION(module, "OperationalError", pysqlite_OperationalError, pysqlite_DatabaseError);
-    ADD_EXCEPTION(module, "ProgrammingError", pysqlite_ProgrammingError, pysqlite_DatabaseError);
-    ADD_EXCEPTION(module, "IntegrityError", pysqlite_IntegrityError, pysqlite_DatabaseError);
-    ADD_EXCEPTION(module, "DataError", pysqlite_DataError, pysqlite_DatabaseError);
-    ADD_EXCEPTION(module, "NotSupportedError", pysqlite_NotSupportedError, pysqlite_DatabaseError);
+    ADD_EXCEPTION(module, "InterfaceError", state->InterfaceError,
+                  state->Error);
+    ADD_EXCEPTION(module, "DatabaseError", state->DatabaseError, state->Error);
+
+    /* DatabaseError subclasses */
+    ADD_EXCEPTION(module, "InternalError", state->InternalError,
+                  state->DatabaseError);
+    ADD_EXCEPTION(module, "OperationalError", pysqlite_OperationalError,
+                  state->DatabaseError);
+    ADD_EXCEPTION(module, "ProgrammingError", pysqlite_ProgrammingError,
+                  state->DatabaseError);
+    ADD_EXCEPTION(module, "IntegrityError", pysqlite_IntegrityError,
+                  state->DatabaseError);
+    ADD_EXCEPTION(module, "DataError", pysqlite_DataError,
+                  state->DatabaseError);
+    ADD_EXCEPTION(module, "NotSupportedError", pysqlite_NotSupportedError,
+                  state->DatabaseError);
 
     /* Set integer constants */
     if (add_integer_constants(module) < 0) {
index 3f29035b5fe68a547f846d91f24f6f94981ce47a..a745096a8ecf61052a3a1760537c410676115ebb 100644 (file)
 #define MODULE_NAME "sqlite3"
 
 typedef struct {
+    PyObject *DatabaseError;
+    PyObject *Error;
+    PyObject *InterfaceError;
+    PyObject *InternalError;
+    PyObject *Warning;
     PyObject *lru_cache;
     PyTypeObject *ConnectionType;
     PyTypeObject *CursorType;
@@ -46,11 +51,6 @@ pysqlite_get_state(PyObject *Py_UNUSED(module))
     return &pysqlite_global_state;
 }
 
-extern PyObject* pysqlite_Error;
-extern PyObject* pysqlite_Warning;
-extern PyObject* pysqlite_InterfaceError;
-extern PyObject* pysqlite_DatabaseError;
-extern PyObject* pysqlite_InternalError;
 extern PyObject* pysqlite_OperationalError;
 extern PyObject* pysqlite_ProgrammingError;
 extern PyObject* pysqlite_IntegrityError;
index fcf13809763f3eb4c70887e473b477118c4e7dc8..035023dc009a84379ad81aceb3b854d674f1c28e 100644 (file)
@@ -51,12 +51,13 @@ typedef enum {
 pysqlite_Statement *
 pysqlite_statement_create(pysqlite_Connection *connection, PyObject *sql)
 {
+    pysqlite_state *state = pysqlite_get_state(NULL);
     assert(PyUnicode_Check(sql));
     Py_ssize_t size;
     const char *sql_cstr = PyUnicode_AsUTF8AndSize(sql, &size);
     if (sql_cstr == NULL) {
-        PyErr_Format(pysqlite_Warning,
-                     "SQL is of wrong type ('%s'). Must be string.",
+        PyObject *exc = connection->Warning;
+        PyErr_Format(exc, "SQL is of wrong type ('%s'). Must be string.",
                      Py_TYPE(sql)->tp_name);
         return NULL;
     }
@@ -86,8 +87,8 @@ pysqlite_statement_create(pysqlite_Connection *connection, PyObject *sql)
     }
 
     if (pysqlite_check_remaining_sql(tail)) {
-        PyErr_SetString(pysqlite_Warning,
-                        "You can only execute one statement at a time.");
+        PyObject *exc = connection->Warning;
+        PyErr_SetString(exc, "You can only execute one statement at a time.");
         goto error;
     }
 
@@ -110,7 +111,6 @@ pysqlite_statement_create(pysqlite_Connection *connection, PyObject *sql)
         break;
     }
 
-    pysqlite_state *state = pysqlite_get_state(NULL);
     pysqlite_Statement *self = PyObject_GC_New(pysqlite_Statement,
                                                state->StatementType);
     if (self == NULL) {
@@ -288,7 +288,9 @@ void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* para
 
             if (rc != SQLITE_OK) {
                 if (!PyErr_Occurred()) {
-                    PyErr_Format(pysqlite_InterfaceError, "Error binding parameter %d - probably unsupported type.", i);
+                    PyErr_Format(state->InterfaceError,
+                                 "Error binding parameter %d - "
+                                 "probably unsupported type.", i);
                 }
                 return;
             }
@@ -342,7 +344,9 @@ void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* para
 
             if (rc != SQLITE_OK) {
                 if (!PyErr_Occurred()) {
-                    PyErr_Format(pysqlite_InterfaceError, "Error binding parameter :%s - probably unsupported type.", binding_name);
+                    PyErr_Format(state->InterfaceError,
+                                 "Error binding parameter :%s - "
+                                 "probably unsupported type.", binding_name);
                 }
                 return;
            }
index 2de819e9e85293774ed9869e34253f1282f93d27..2684773b6d3940783277445ac424953f53dbedbb 100644 (file)
@@ -43,6 +43,7 @@ pysqlite_step(sqlite3_stmt *statement)
 int
 _pysqlite_seterror(sqlite3 *db)
 {
+    pysqlite_state *state = pysqlite_get_state(NULL);
     int errorcode = sqlite3_errcode(db);
 
     switch (errorcode)
@@ -52,7 +53,7 @@ _pysqlite_seterror(sqlite3 *db)
             break;
         case SQLITE_INTERNAL:
         case SQLITE_NOTFOUND:
-            PyErr_SetString(pysqlite_InternalError, sqlite3_errmsg(db));
+            PyErr_SetString(state->InternalError, sqlite3_errmsg(db));
             break;
         case SQLITE_NOMEM:
             (void)PyErr_NoMemory();
@@ -73,7 +74,7 @@ _pysqlite_seterror(sqlite3 *db)
             PyErr_SetString(pysqlite_OperationalError, sqlite3_errmsg(db));
             break;
         case SQLITE_CORRUPT:
-            PyErr_SetString(pysqlite_DatabaseError, sqlite3_errmsg(db));
+            PyErr_SetString(state->DatabaseError, sqlite3_errmsg(db));
             break;
         case SQLITE_TOOBIG:
             PyErr_SetString(pysqlite_DataError, sqlite3_errmsg(db));
@@ -86,7 +87,7 @@ _pysqlite_seterror(sqlite3 *db)
             PyErr_SetString(pysqlite_ProgrammingError, sqlite3_errmsg(db));
             break;
         default:
-            PyErr_SetString(pysqlite_DatabaseError, sqlite3_errmsg(db));
+            PyErr_SetString(state->DatabaseError, sqlite3_errmsg(db));
             break;
     }
 
index d8407ed3745fafa2b41f555e1c3130eb82538f1c..b002703b352f192371fdd6ad47c987e2b55d933d 100644 (file)
@@ -49,11 +49,6 @@ Modules/_io/_iomodule.h      -       _PyIO_str_write -
 Modules/_io/_iomodule.h        -       _PyIO_empty_str -
 Modules/_io/_iomodule.h        -       _PyIO_empty_bytes       -
 Modules/_multiprocessing/multiprocessing.h     -       _PyMp_SemLockType       -
-Modules/_sqlite/module.c       -       pysqlite_Error  -
-Modules/_sqlite/module.c       -       pysqlite_Warning        -
-Modules/_sqlite/module.c       -       pysqlite_InterfaceError -
-Modules/_sqlite/module.c       -       pysqlite_DatabaseError  -
-Modules/_sqlite/module.c       -       pysqlite_InternalError  -
 Modules/_sqlite/module.c       -       pysqlite_OperationalError       -
 Modules/_sqlite/module.c       -       pysqlite_ProgrammingError       -
 Modules/_sqlite/module.c       -       pysqlite_IntegrityError -
@@ -2371,11 +2366,6 @@ Modules/_ctypes/_ctypes.c        -       PyExc_ArgError  -
 Modules/_cursesmodule.c        -       PyCursesError   -
 Modules/_decimal/_decimal.c    -       DecimalException        -
 Modules/_queuemodule.c -       EmptyError      -
-Modules/_sqlite/module.h       -       pysqlite_Error  -
-Modules/_sqlite/module.h       -       pysqlite_Warning        -
-Modules/_sqlite/module.h       -       pysqlite_InterfaceError -
-Modules/_sqlite/module.h       -       pysqlite_DatabaseError  -
-Modules/_sqlite/module.h       -       pysqlite_InternalError  -
 Modules/_sqlite/module.h       -       pysqlite_OperationalError       -
 Modules/_sqlite/module.h       -       pysqlite_ProgrammingError       -
 Modules/_sqlite/module.h       -       pysqlite_IntegrityError -