From: Daniele Varrazzo Date: Mon, 2 May 2022 00:45:21 +0000 (+0200) Subject: fix: allow to use cancel() on a closed connection X-Git-Tag: 3.1~123 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b0796add5ebda8df2693fb2f387bbc181a10c84b;p=thirdparty%2Fpsycopg.git fix: allow to use cancel() on a closed connection --- diff --git a/docs/news.rst b/docs/news.rst index 1ed40085d..08ad5151f 100644 --- a/docs/news.rst +++ b/docs/news.rst @@ -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 diff --git a/psycopg/psycopg/connection.py b/psycopg/psycopg/connection.py index 2efd7c4b6..65bc2f658 100644 --- a/psycopg/psycopg/connection.py +++ b/psycopg/psycopg/connection.py @@ -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" diff --git a/tests/test_connection.py b/tests/test_connection.py index 4013a16a0..800c5a11a 100644 --- a/tests/test_connection.py +++ b/tests/test_connection.py @@ -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() diff --git a/tests/test_connection_async.py b/tests/test_connection_async.py index 804c7bcd2..dd10ed6fc 100644 --- a/tests/test_connection_async.py +++ b/tests/test_connection_async.py @@ -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()