From 1a1bfc28912a39b500c578e9f10a8a222638d411 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 22 Aug 2023 13:10:29 +0200 Subject: [PATCH] gh-105539: Emit ResourceWarning if sqlite3 database is not closed explicitly (#108015) --- Doc/library/sqlite3.rst | 6 ++++++ Doc/whatsnew/3.13.rst | 7 +++++++ Lib/test/test_sqlite3/test_dbapi.py | 6 ++++++ .../2023-08-16-14-30-13.gh-issue-105539.29lA6c.rst | 3 +++ Modules/_sqlite/connection.c | 8 ++++++++ 5 files changed, 30 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2023-08-16-14-30-13.gh-issue-105539.29lA6c.rst diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst index 5f1676e5ae2..d2745b0dbce 100644 --- a/Doc/library/sqlite3.rst +++ b/Doc/library/sqlite3.rst @@ -630,6 +630,12 @@ Connection objects * :ref:`sqlite3-connection-shortcuts` * :ref:`sqlite3-connection-context-manager` + + .. versionchanged:: 3.13 + + A :exc:`ResourceWarning` is emitted if :meth:`close` is not called before + a :class:`!Connection` object is deleted. + An SQLite database connection has the following attributes and methods: .. method:: cursor(factory=Cursor) diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index bfab868d1c5..8509e18a7d7 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -158,6 +158,13 @@ pathlib :meth:`~pathlib.Path.is_dir`. (Contributed by Barney Gale in :gh:`77609` and :gh:`105793`.) +sqlite3 +------- + +* A :exc:`ResourceWarning` is now emitted if a :class:`sqlite3.Connection` + object is not :meth:`closed ` explicitly. + (Contributed by Erlend E. Aasland in :gh:`105539`.) + tkinter ------- diff --git a/Lib/test/test_sqlite3/test_dbapi.py b/Lib/test/test_sqlite3/test_dbapi.py index df3c2ea8d1d..d80ad7af320 100644 --- a/Lib/test/test_sqlite3/test_dbapi.py +++ b/Lib/test/test_sqlite3/test_dbapi.py @@ -583,6 +583,12 @@ class ConnectionTests(unittest.TestCase): cx.close() self.assertEqual(cm.filename, __file__) + def test_connection_resource_warning(self): + with self.assertWarns(ResourceWarning): + cx = sqlite.connect(":memory:") + del cx + gc_collect() + class UninitialisedConnectionTests(unittest.TestCase): def setUp(self): diff --git a/Misc/NEWS.d/next/Library/2023-08-16-14-30-13.gh-issue-105539.29lA6c.rst b/Misc/NEWS.d/next/Library/2023-08-16-14-30-13.gh-issue-105539.29lA6c.rst new file mode 100644 index 00000000000..0098c7f2438 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-08-16-14-30-13.gh-issue-105539.29lA6c.rst @@ -0,0 +1,3 @@ +:mod:`sqlite3` now emits an :exc:`ResourceWarning` if a +:class:`sqlite3.Connection` object is not :meth:`closed +` explicitly. Patch by Erlend E. Aasland. diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index 282855f8865..e133977b28c 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -493,6 +493,14 @@ connection_finalize(PyObject *self) } /* Clean up if user has not called .close() explicitly. */ + if (con->db) { + if (PyErr_ResourceWarning(self, 1, "unclosed database in %R", self)) { + /* Spurious errors can appear at shutdown */ + if (PyErr_ExceptionMatches(PyExc_Warning)) { + PyErr_WriteUnraisable(self); + } + } + } if (connection_close(con) < 0) { if (teardown) { PyErr_Clear();