From: Daniele Varrazzo Date: Sun, 23 Jul 2023 19:33:05 +0000 (+0100) Subject: fix: fix possible errors calling __repr__ from __del__. X-Git-Tag: 3.1.10~9^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=09ee4705acb79c9976e12d276ec298c8829c8926;p=thirdparty%2Fpsycopg.git fix: fix possible errors calling __repr__ from __del__. 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. --- diff --git a/docs/news.rst b/docs/news.rst index bd8e0c4ff..e526b49b2 100644 --- a/docs/news.rst +++ b/docs/news.rst @@ -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`). diff --git a/psycopg/psycopg/_pipeline.py b/psycopg/psycopg/_pipeline.py index e0c564a21..3c73f7eea 100644 --- a/psycopg/psycopg/_pipeline.py +++ b/psycopg/psycopg/_pipeline.py @@ -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 diff --git a/psycopg/psycopg/connection.py b/psycopg/psycopg/connection.py index 299c4f3ff..195c784e4 100644 --- a/psycopg/psycopg/connection.py +++ b/psycopg/psycopg/connection.py @@ -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 diff --git a/psycopg/psycopg/copy.py b/psycopg/psycopg/copy.py index 7bae6d22d..df2975f6e 100644 --- a/psycopg/psycopg/copy.py +++ b/psycopg/psycopg/copy.py @@ -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: diff --git a/psycopg/psycopg/cursor.py b/psycopg/psycopg/cursor.py index 148ea10bb..6048bbf66 100644 --- a/psycopg/psycopg/cursor.py +++ b/psycopg/psycopg/cursor.py @@ -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: diff --git a/psycopg/psycopg/transaction.py b/psycopg/psycopg/transaction.py index e13486e98..fae3c2ab5 100644 --- a/psycopg/psycopg/transaction.py +++ b/psycopg/psycopg/transaction.py @@ -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: