From: Daniele Varrazzo Date: Mon, 25 Oct 2021 08:59:09 +0000 (+0100) Subject: Remove the pgresult structure from the cursor on close X-Git-Tag: 3.0.2~28 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1bc77c921a88acde6144c989062c7dfc35ce6320;p=thirdparty%2Fpsycopg.git Remove the pgresult structure from the cursor on close This is what the dbapi demands and helps with make the cursor unavailable after close. --- diff --git a/psycopg/psycopg/cursor.py b/psycopg/psycopg/cursor.py index 36d50fd0f..cbc1dda97 100644 --- a/psycopg/psycopg/cursor.py +++ b/psycopg/psycopg/cursor.py @@ -73,13 +73,15 @@ class BaseCursor(Generic[ConnectionType, Row]): self._last_query: Optional[Query] = None self._reset() - def _reset(self) -> None: + def _reset(self, reset_query: bool = True) -> None: self._results: List["PGresult"] = [] self.pgresult: Optional["PGresult"] = None self._pos = 0 self._iresult = 0 self._rowcount = -1 - self._query: Optional[PostgresQuery] = None + self._query: Optional[PostgresQuery] + if reset_query: + self._query = None def __repr__(self) -> str: cls = f"{self.__class__.__module__}.{self.__class__.__qualname__}" @@ -490,6 +492,10 @@ class BaseCursor(Generic[ConnectionType, Row]): self._pos = newpos def _close(self) -> None: + """Non-blocking part of closing. Common to sync/async.""" + # Don't reset the query because it may be useful to investigate after + # an error. + self._reset(reset_query=False) self._closed = True diff --git a/tests/test_cursor.py b/tests/test_cursor.py index eab60206f..a72b617fe 100644 --- a/tests/test_cursor.py +++ b/tests/test_cursor.py @@ -42,6 +42,14 @@ def test_weakref(conn): assert w() is None +def test_pgresult(conn): + cur = conn.cursor() + cur.execute("select 1") + assert cur.pgresult + cur.close() + assert not cur.pgresult + + def test_statusmessage(conn): cur = conn.cursor() assert cur.statusmessage is None @@ -274,9 +282,6 @@ def test_rowcount(conn): ) assert cur.rowcount == 42 - cur.close() - assert cur.rowcount == 42 - def test_rownumber(conn): cur = conn.cursor() diff --git a/tests/test_cursor_async.py b/tests/test_cursor_async.py index 3aaa43560..7f297ab54 100644 --- a/tests/test_cursor_async.py +++ b/tests/test_cursor_async.py @@ -42,6 +42,14 @@ async def test_weakref(aconn): assert w() is None +async def test_pgresult(aconn): + cur = aconn.cursor() + await cur.execute("select 1") + assert cur.pgresult + await cur.close() + assert not cur.pgresult + + async def test_statusmessage(aconn): cur = aconn.cursor() assert cur.statusmessage is None @@ -276,9 +284,6 @@ async def test_rowcount(aconn): ) assert cur.rowcount == 42 - await cur.close() - assert cur.rowcount == 42 - async def test_rownumber(aconn): cur = aconn.cursor() diff --git a/tests/test_server_cursor.py b/tests/test_server_cursor.py index 132fa1a93..6686621d6 100644 --- a/tests/test_server_cursor.py +++ b/tests/test_server_cursor.py @@ -138,6 +138,14 @@ def test_close_on_error(conn): cur.close() +def test_pgresult(conn): + cur = conn.cursor() + cur.execute("select 1") + assert cur.pgresult + cur.close() + assert not cur.pgresult + + def test_context(conn, recwarn, retries): for retry in retries: with retry: diff --git a/tests/test_server_cursor_async.py b/tests/test_server_cursor_async.py index d240ac39d..a2b5486e1 100644 --- a/tests/test_server_cursor_async.py +++ b/tests/test_server_cursor_async.py @@ -145,6 +145,14 @@ async def test_close_on_error(aconn): await cur.close() +async def test_pgresult(aconn): + cur = aconn.cursor() + await cur.execute("select 1") + assert cur.pgresult + await cur.close() + assert not cur.pgresult + + async def test_context(aconn, recwarn, retries): async for retry in retries: with retry: