From: Daniele Varrazzo Date: Sat, 5 Jul 2025 12:54:39 +0000 (+0200) Subject: feat: add `ConnectionInfo.full_protocol_version` X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fpull%2F1098%2Fhead;p=thirdparty%2Fpsycopg.git feat: add `ConnectionInfo.full_protocol_version` Add matching Capabilities methods too to allow checking if supported. --- diff --git a/docs/api/objects.rst b/docs/api/objects.rst index fb9714e3b..d18192568 100644 --- a/docs/api/objects.rst +++ b/docs/api/objects.rst @@ -52,6 +52,10 @@ Connection information second group of digits is always 00. For example, version 9.3.5 is returned as 90305, version 10.2 as 100002. + .. autoattribute:: full_protocol_version + + .. versionadded:: 3.3 + .. autoattribute:: error_message .. automethod:: get_parameters @@ -76,7 +80,7 @@ Connection information Only available if the libpq used is from PostgreSQL 12 or newer. Raise `~psycopg.NotSupportedError` otherwise. You can use the - `~Capabilities.has_hostaddr` capability to check for support. + `~Capabilities.has_hostaddr` capability to check for its support. .. autoattribute:: port .. autoattribute:: dbname @@ -146,6 +150,10 @@ Libpq capabilities information .. versionadded:: 3.2 + .. automethod:: has_full_protocol_version + + .. versionadded:: 3.3 + .. automethod:: has_encrypt_password .. automethod:: has_hostaddr .. automethod:: has_pipeline diff --git a/docs/news.rst b/docs/news.rst index ab5562426..7ec03e50d 100644 --- a/docs/news.rst +++ b/docs/news.rst @@ -25,8 +25,8 @@ Psycopg 3.3.0 (unreleased) - Add `pq.PGconn.used_gssapi` attribute and `Capabilities.has_used_gssapi()` function (:ticket:`#1138`). -- Add support for the :pq:`PQfullProtocolVersion()` function, introduced in - libpq v18 (:ticket:`#1079`). +- Add `ConnectionInfo.full_protocol_version` attribute, + `Capabilities.has_full_protocol_version()` function (:ticket:`#1079`). .. rubric:: Other changes diff --git a/psycopg/psycopg/_capabilities.py b/psycopg/psycopg/_capabilities.py index 49aef12f8..b0ca96098 100644 --- a/psycopg/psycopg/_capabilities.py +++ b/psycopg/psycopg/_capabilities.py @@ -18,6 +18,18 @@ class Capabilities: def __init__(self) -> None: self._cache: dict[str, str] = {} + def has_full_protocol_version(self, check: bool = False) -> bool: + """Check if the `PGconn.full_protocol_version()` method is implemented. + + If the method is implemented, then `ConnectionInfo.full_protocol_version` + will return a meaningful value. + + The feature requires libpq 18.0 and greater. + """ + return self._has_feature( + "pq.PGconn.full_protocol_version()", 180000, check=check + ) + def has_encrypt_password(self, check: bool = False) -> bool: """Check if the `PGconn.encrypt_password()` method is implemented. diff --git a/psycopg/psycopg/_connection_info.py b/psycopg/psycopg/_connection_info.py index 84554c6f9..344f68495 100644 --- a/psycopg/psycopg/_connection_info.py +++ b/psycopg/psycopg/_connection_info.py @@ -152,6 +152,24 @@ class ConnectionInfo: """ return self.pgconn.server_version + @property + def full_protocol_version(self) -> int: + """ + An integer representing the server full protocol version. + + Return a value in the format described in :pq:`PQfullProtocolVersion()`. + + Only meaningful if the libpq used is version 18 or greater. If the + version is lesser than that, return the value reported by + :pq:`PQprotocolVersion()` (but in the same format as above, e.g. 30000 + for version 3). You can use `Capabilities.has_full_protocol_version()` + to verify if the value can be considered reliable. + """ + try: + return self.pgconn.full_protocol_version + except e.NotSupportedError: + return self.pgconn.protocol_version * 10000 + @property def backend_pid(self) -> int: """ diff --git a/tests/test_capabilities.py b/tests/test_capabilities.py index f58471a15..3697f1227 100644 --- a/tests/test_capabilities.py +++ b/tests/test_capabilities.py @@ -11,6 +11,7 @@ except ImportError: pass caps = [ + ("has_full_protocol_version", "pq.PGconn.full_protocol_version()", 18), ("has_encrypt_password", "pq.PGconn.encrypt_password()", 10), ("has_hostaddr", "Connection.info.hostaddr", 12), ("has_pipeline", "Connection.pipeline()", 14), diff --git a/tests/test_connection_info.py b/tests/test_connection_info.py index 2ff96e06c..2dda3a2db 100644 --- a/tests/test_connection_info.py +++ b/tests/test_connection_info.py @@ -44,6 +44,13 @@ def test_port(conn): conn.info.port +def test_full_protocol_version(conn): + assert conn.info.full_protocol_version >= 30000 + conn.close() + with pytest.raises(psycopg.OperationalError): + conn.info.full_protocol_version + + @pytest.mark.skipif(psycopg.pq.__impl__ != "python", reason="can't monkeypatch C") def test_blank_port(conn, monkeypatch):