]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
feat: add `ConnectionInfo.full_protocol_version` 1098/head
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Sat, 5 Jul 2025 12:54:39 +0000 (14:54 +0200)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Sun, 7 Sep 2025 11:47:24 +0000 (13:47 +0200)
Add matching Capabilities methods too to allow checking if supported.

docs/api/objects.rst
docs/news.rst
psycopg/psycopg/_capabilities.py
psycopg/psycopg/_connection_info.py
tests/test_capabilities.py
tests/test_connection_info.py

index fb9714e3bbfa5d04202664dc68513718d0f61351..d18192568b7f693dadd3446f5aa9997ce28f1ba2 100644 (file)
@@ -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
index ab5562426e67b602b65e295a7ce96eee827e7b2d..7ec03e50d2caa7bd84c6dc62692bb05cc9f2f506 100644 (file)
@@ -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
 
index 49aef12f8f9b0d0147b9f4230ff01e9b8cb6ecef..b0ca96098e7970fa500ffeec1c91d400d0eccef7 100644 (file)
@@ -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.
 
index 84554c6f97029aecdd9a29d5e17a8abd8ebce7dd..344f68495fbfbe274764e65bafcd90403e544957 100644 (file)
@@ -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:
         """
index f58471a15065defb7bb8707edba1b33d3db533ce..3697f122705cab3a38e35e7dcd7d2e5d99befc3a 100644 (file)
@@ -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),
index 2ff96e06cea4ed36aae95685d6c15828ad3c170f..2dda3a2db1b55a4cfdef0f2523519fe5bb88df2d 100644 (file)
@@ -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):