]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
Added PGconn.info wrapping PQconninfo
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Sat, 14 Mar 2020 05:09:14 +0000 (18:09 +1300)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Sat, 14 Mar 2020 05:09:14 +0000 (18:09 +1300)
psycopg3/_pq_ctypes.py
psycopg3/pq_ctypes.py
tests/test_pq.py

index d2a0f188c3019619f7ae126fa63a9fcfaa16122e..78bcd22cdf6b0f0ed1139f36709c280046f439da 100644 (file)
@@ -19,9 +19,6 @@ class PGconn_struct(Structure):
     _fields_ = []
 
 
-PGconn_ptr = POINTER(PGconn_struct)
-
-
 class PQconninfoOption_struct(Structure):
     _fields_ = [
         ("keyword", c_char_p),
@@ -34,6 +31,10 @@ class PQconninfoOption_struct(Structure):
     ]
 
 
+PGconn_ptr = POINTER(PGconn_struct)
+PQconninfoOption_ptr = POINTER(PQconninfoOption_struct)
+
+
 # Function definitions as explained in PostgreSQL 12 documentation
 
 # 33.1. Database Connection Control Functions
@@ -59,12 +60,16 @@ PQconnectPoll.restype = c_int
 
 PQconndefaults = pq.PQconndefaults
 PQconndefaults.argtypes = []
-PQconndefaults.restype = POINTER(PQconninfoOption_struct)
+PQconndefaults.restype = PQconninfoOption_ptr
 
 PQconninfoFree = pq.PQconninfoFree
-PQconninfoFree.argtypes = [POINTER(PQconninfoOption_struct)]
+PQconninfoFree.argtypes = [PQconninfoOption_ptr]
 PQconninfoFree.restype = None
 
+PQconninfo = pq.PQconninfo
+PQconninfo.argtypes = [PGconn_ptr]
+PQconninfo.restype = PQconninfoOption_ptr
+
 
 # 33.2. Connection Status Functions
 
index b85480b425ca36cd0bfe63bcd746ef5debe0a9c2..8a37b45b544cfec69a75341f170c48d7e7b0a719 100644 (file)
@@ -51,27 +51,20 @@ class PGconn:
         opts = impl.PQconndefaults()
         if not opts:
             raise MemoryError("couldn't allocate connection defaults")
-
-        def gets(opt, kw):
-            rv = getattr(opt, kw)
-            if rv is not None:
-                rv = rv.decode("utf8", "replace")
-            return rv
-
         try:
-            rv = []
-            skws = "keyword envvar compiled val label dispatcher".split()
-            for opt in opts:
-                if not opt.keyword:
-                    break
-                d = {kw: gets(opt, kw) for kw in skws}
-                d["dispsize"] = opt.dispsize
-                rv.append(ConninfoOption(**d))
-
+            return _conninfoopts_from_array(opts)
         finally:
             impl.PQconninfoFree(opts)
 
-        return rv
+    @property
+    def info(self):
+        opts = impl.PQconninfo(self.pgconn_ptr)
+        if not opts:
+            raise MemoryError("couldn't allocate connection info")
+        try:
+            return _conninfoopts_from_array(opts)
+        finally:
+            impl.PQconninfoFree(opts)
 
     @property
     def status(self):
@@ -91,3 +84,22 @@ class PGconn:
 ConninfoOption = namedtuple(
     "ConninfoOption", "keyword envvar compiled val label dispatcher dispsize"
 )
+
+
+def _conninfoopts_from_array(opts):
+    def gets(opt, kw):
+        rv = getattr(opt, kw)
+        if rv is not None:
+            rv = rv.decode("utf8", "replace")
+        return rv
+
+    rv = []
+    skws = "keyword envvar compiled val label dispatcher".split()
+    for opt in opts:
+        if not opt.keyword:
+            break
+        d = {kw: gets(opt, kw) for kw in skws}
+        d["dispsize"] = opt.dispsize
+        rv.append(ConninfoOption(**d))
+
+    return rv
index 539584a0754a2227725c494a3b7c289b99e23172..3c8aa1d84113cfb437a2b69c1a8a38a7f0e6b97a 100644 (file)
@@ -1,3 +1,4 @@
+import os
 from select import select
 
 import pytest
@@ -61,11 +62,33 @@ def test_connect_async_bad(pq, dsn):
 
 
 def test_defaults(pq):
-    defs = pq.PGconn.get_defaults()
+    oldport = os.environ.get("PGPORT")
+    try:
+        os.environ["PGPORT"] = "15432"
+        defs = pq.PGconn.get_defaults()
+    finally:
+        if oldport is not None:
+            os.environ["PGPORT"] = oldport
+        else:
+            del os.environ["PGPORT"]
+
     assert len(defs) > 20
     port = [d for d in defs if d.keyword == "port"][0]
     assert port.envvar == "PGPORT"
     assert port.compiled == "5432"
+    assert port.val == "15432"
     assert port.label == "Database-Port"
     assert port.dispatcher == ""
     assert port.dispsize == 6
+
+
+def test_info(pq, dsn):
+    conn = pq.PGconn.connectdb(dsn)
+    info = conn.info
+    assert len(info) > 20
+    dbname = [d for d in info if d.keyword == "dbname"][0]
+    assert dbname.envvar == "PGDATABASE"
+    assert dbname.val == "psycopg3_test"  # TODO: parse from dsn
+    assert dbname.label == "Database-Name"
+    assert dbname.dispatcher == ""
+    assert dbname.dispsize == 20