]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
fix: allow to use cancel() on a closed connection
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Mon, 2 May 2022 00:45:21 +0000 (02:45 +0200)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Mon, 2 May 2022 00:55:25 +0000 (02:55 +0200)
docs/news.rst
psycopg/psycopg/connection.py
tests/test_connection.py
tests/test_connection_async.py

index 1ed40085dc3ace1b5fe26980b07353f0a14e2aff..08ad5151fd62103f6a31190b5f64bfba42a05e04 100644 (file)
@@ -29,6 +29,8 @@ Psycopg 3.0.13 (unreleased)
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 - Fix `Cursor.stream()` slowness (:ticket:`#286`).
+- Make `Connection.cancel()` on a closed connection a no-op instead of an
+  error.
 
 
 Current release
index 2efd7c4b694fd63296d8a8dd2369cb32fafe037d..65bc2f658ef2d68aa645a4fdb2d7b4ee6e616e8b 100644 (file)
@@ -283,6 +283,12 @@ class BaseConnection(Generic[Row]):
 
     def cancel(self) -> None:
         """Cancel the current operation on the connection."""
+        # No-op if the connection is closed
+        # this allows to use the method as callback handler without caring
+        # about its life.
+        if self.closed:
+            return
+
         if self._tpc and self._tpc[1]:
             raise e.ProgrammingError(
                 "cancel() cannot be used with a prepared two-phase transaction"
index 4013a16a02a4ed39516705584422ce5c54f10953..800c5a11a1eac06876d2d735ed85f0b861adc51d 100644 (file)
@@ -737,3 +737,8 @@ def test_connect_context_copy(dsn, conn):
     cur = conn2.execute("select %b", ["hello"])
     assert cur.fetchone()[0] == "hellob"  # type: ignore[index]
     conn2.close()
+
+
+def test_cancel_closed(conn):
+    conn.close()
+    conn.cancel()
index 804c7bcd251c4b97afe05e1939f3c235ca168ec6..dd10ed6fc63ed30857625d44788b88b98dc3ad8f 100644 (file)
@@ -686,3 +686,8 @@ async def test_connect_context_copy(dsn, aconn):
     cur = await aconn2.execute("select %b", ["hello"])
     assert (await cur.fetchone())[0] == "hellob"  # type: ignore[index]
     await aconn2.close()
+
+
+async def test_cancel_closed(aconn):
+    await aconn.close()
+    aconn.cancel()