]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
fix: fix possible errors calling __repr__ from __del__.
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Sun, 23 Jul 2023 19:33:05 +0000 (20:33 +0100)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Sun, 23 Jul 2023 19:42:03 +0000 (20:42 +0100)
The errors get ignored but print a warning on program exit and eclipse a
genuine warning.

The error is caused by the `pq.misc` module getting gc'd on interpreter
shutdown before `connection_summary()` is called. The solution is to
import `connection_summary` in the module namespace, which is similar to
the solution that proved working for #198. It is less robust than the
solution used by the Python devs to import the function in the method
via an argument default, but it should work adequately (as nobody
complained about #198 anymore).

In #591 discussion, I proposed that connection_summary is too complex to
be considered safe to call on __del__. Actually, looking at it, it seems
innocent enough, as it only calls objects methods, no functions from
module namespaces. As a consequence we assume that this commit fixes the
issue. As I can't reproduce it, will ask the OP if this is the case.

Close #591.

docs/news.rst
psycopg/psycopg/_pipeline.py
psycopg/psycopg/connection.py
psycopg/psycopg/copy.py
psycopg/psycopg/cursor.py
psycopg/psycopg/transaction.py

index bd8e0c4ff926a39a63f6c965182c6843a7314f96..e526b49b23ac9399b0f2735c670981bc71ca75f8 100644 (file)
@@ -20,6 +20,7 @@ Psycopg 3.1.10 (unreleased)
   `OperationalError` in case of connection failure. `Error.pgconn` is now a
   shallow copy of the real libpq connection, and the latter is closed before
   the exception propagates (:ticket:`#565`).
+- Fix possible (ignored) exception on objects deletion (:ticket:`#591`).
 - Don't clobber a Python exception raised during COPY FROM with the resulting
   `!QueryCanceled` raised as a consequence (:ticket:`#593`).
 
index e0c564a21d59d722fde0b0a7e02054226e1bc773..3c73f7eeae595e66b70a4f57f30f7f06bc801dec 100644 (file)
@@ -13,6 +13,7 @@ from . import pq
 from . import errors as e
 from .abc import PipelineCommand, PQGen
 from ._compat import Deque
+from .pq.misc import connection_summary
 from ._encodings import pgconn_encoding
 from ._preparing import Key, Prepare
 from .generators import pipeline_communicate, fetch_many, send
@@ -51,7 +52,7 @@ class BasePipeline:
 
     def __repr__(self) -> str:
         cls = f"{self.__class__.__module__}.{self.__class__.__qualname__}"
-        info = pq.misc.connection_summary(self._conn.pgconn)
+        info = connection_summary(self._conn.pgconn)
         return f"<{cls} {info} at 0x{id(self):x}>"
 
     @property
index 299c4f3ff6280b2826968a976a171b550bd769b4..195c784e4a3deeab471a722f7b27048dc48750c1 100644 (file)
@@ -29,6 +29,7 @@ from .adapt import AdaptersMap
 from ._enums import IsolationLevel
 from .cursor import Cursor
 from ._compat import LiteralString
+from .pq.misc import connection_summary
 from .conninfo import make_conninfo, conninfo_to_dict, ConnectionInfo
 from ._pipeline import BasePipeline, Pipeline
 from .generators import notifies, connect, execute
@@ -161,7 +162,7 @@ class BaseConnection(Generic[Row]):
 
     def __repr__(self) -> str:
         cls = f"{self.__class__.__module__}.{self.__class__.__qualname__}"
-        info = pq.misc.connection_summary(self.pgconn)
+        info = connection_summary(self.pgconn)
         return f"<{cls} {info} at 0x{id(self):x}>"
 
     @property
index 7bae6d22d6de193189cce3a6284d4469d9a1986e..df2975f6e1498b3163c2701fefb572626e335868 100644 (file)
@@ -19,6 +19,7 @@ from . import adapt
 from . import errors as e
 from .abc import Buffer, ConnectionType, PQGen, Transformer
 from ._compat import create_task
+from .pq.misc import connection_summary
 from ._cmodule import _psycopg
 from ._encodings import pgconn_encoding
 from .generators import copy_from, copy_to, copy_end
@@ -112,7 +113,7 @@ class BaseCopy(Generic[ConnectionType]):
 
     def __repr__(self) -> str:
         cls = f"{self.__class__.__module__}.{self.__class__.__qualname__}"
-        info = pq.misc.connection_summary(self._pgconn)
+        info = connection_summary(self._pgconn)
         return f"<{cls} {info} at 0x{id(self):x}>"
 
     def _enter(self) -> None:
index 148ea10bb34eeaf6f3d7b8abbcad52ea7907f0f1..6048bbf664e116e8d819a7f1a9b0b3f9e06a4062 100644 (file)
@@ -18,6 +18,7 @@ from .abc import ConnectionType, Query, Params, PQGen
 from .copy import Copy, Writer as CopyWriter
 from .rows import Row, RowMaker, RowFactory
 from ._column import Column
+from .pq.misc import connection_summary
 from ._queries import PostgresQuery, PostgresClientQuery
 from ._pipeline import Pipeline
 from ._encodings import pgconn_encoding
@@ -83,7 +84,7 @@ class BaseCursor(Generic[ConnectionType, Row]):
 
     def __repr__(self) -> str:
         cls = f"{self.__class__.__module__}.{self.__class__.__qualname__}"
-        info = pq.misc.connection_summary(self._pgconn)
+        info = connection_summary(self._pgconn)
         if self._closed:
             status = "closed"
         elif self.pgresult:
index e13486e984c91beccaf8bc73fcdb6e74e31d3d51..fae3c2ab557b5d746be71432abd69a53b9b06a20 100644 (file)
@@ -13,6 +13,7 @@ from . import pq
 from . import sql
 from . import errors as e
 from .abc import ConnectionType, PQGen
+from .pq.misc import connection_summary
 
 if TYPE_CHECKING:
     from typing import Any
@@ -77,7 +78,7 @@ class BaseTransaction(Generic[ConnectionType]):
 
     def __repr__(self) -> str:
         cls = f"{self.__class__.__module__}.{self.__class__.__qualname__}"
-        info = pq.misc.connection_summary(self.pgconn)
+        info = connection_summary(self.pgconn)
         if not self._entered:
             status = "inactive"
         elif not self._exited: