From 9aa24dd6806559f186075973c7d67da184e73399 Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Sun, 15 Mar 2020 01:38:49 +1300 Subject: [PATCH] Added needs_password, used_password, ssl_in_use on PGconn --- psycopg3/_pq_ctypes.py | 12 ++++++++++++ psycopg3/pq_ctypes.py | 12 ++++++++++++ tests/fix_tempenv.py | 3 +++ tests/test_pq.py | 39 +++++++++++++++++++++++++++++++++++++-- 4 files changed, 64 insertions(+), 2 deletions(-) diff --git a/psycopg3/_pq_ctypes.py b/psycopg3/_pq_ctypes.py index 6fcac5184..21358b726 100644 --- a/psycopg3/_pq_ctypes.py +++ b/psycopg3/_pq_ctypes.py @@ -161,6 +161,18 @@ PQbackendPID = pq.PQbackendPID PQbackendPID.argtypes = [PGconn_ptr] PQbackendPID.restype = c_int +PQconnectionNeedsPassword = pq.PQconnectionNeedsPassword +PQconnectionNeedsPassword.argtypes = [PGconn_ptr] +PQconnectionNeedsPassword.restype = c_int + +PQconnectionUsedPassword = pq.PQconnectionUsedPassword +PQconnectionUsedPassword.argtypes = [PGconn_ptr] +PQconnectionUsedPassword.restype = c_int + +PQsslInUse = pq.PQsslInUse +PQsslInUse.argtypes = [PGconn_ptr] +PQsslInUse.restype = c_int + # 33.11. Miscellaneous Functions diff --git a/psycopg3/pq_ctypes.py b/psycopg3/pq_ctypes.py index 77448a220..fba097c81 100644 --- a/psycopg3/pq_ctypes.py +++ b/psycopg3/pq_ctypes.py @@ -193,6 +193,18 @@ class PGconn: def backend_pid(self): return impl.PQbackendPID(self.pgconn_ptr) + @property + def needs_password(self): + return bool(impl.PQconnectionNeedsPassword(self.pgconn_ptr)) + + @property + def used_password(self): + return bool(impl.PQconnectionUsedPassword(self.pgconn_ptr)) + + @property + def ssl_in_use(self): + return bool(impl.PQsslInUse(self.pgconn_ptr)) + def _encode(self, s): if isinstance(s, bytes): return s diff --git a/tests/fix_tempenv.py b/tests/fix_tempenv.py index 2f1e0897a..9f3f35bd7 100644 --- a/tests/fix_tempenv.py +++ b/tests/fix_tempenv.py @@ -20,6 +20,9 @@ class TempEnv: self._prev.setdefault(item, os.environ.get(item)) del os.environ[item] + def __contains__(self, item): + return item in os.environ + def restore(self): for k, v in self._prev.items(): if v is not None: diff --git a/tests/test_pq.py b/tests/test_pq.py index 9a4e5a76c..e77f1d5ae 100644 --- a/tests/test_pq.py +++ b/tests/test_pq.py @@ -177,8 +177,8 @@ def test_transaction_status(pq, pgconn): def test_parameter_status(pq, dsn, tempenv): tempenv["PGAPPNAME"] = "psycopg3 tests" pgconn = pq.PGconn.connect(dsn) - assert pgconn.parameter_status('application_name') == "psycopg3 tests" - assert pgconn.parameter_status('wat') is None + assert pgconn.parameter_status("application_name") == "psycopg3 tests" + assert pgconn.parameter_status("wat") is None def test_protocol_version(pgconn): @@ -191,3 +191,38 @@ def test_server_version(pgconn): def test_backend_pid(pgconn): assert 2 <= pgconn.backend_pid <= 65535 # Unless increased in kernel? + + +def test_needs_password(pgconn): + # assume connection worked so an eventually needed password wasn't missing + assert pgconn.needs_password is False + + +def test_used_password(pgconn, tempenv, dsn): + assert isinstance(pgconn.used_password, bool) + + # Assume that if a password was passed then it was needed. + # Note that the server may still need a password passed via pgpass + # so it may be that has_password is false but still a password was + # requested by the server and passed by libpq. + info = pgconn.parse_conninfo(dsn) + has_password = ( + "PGPASSWORD" in tempenv + or [i for i in info if i.keyword == "password"][0].val is not None + ) + if has_password: + assert pgconn.used_password + + +def test_ssl_in_use(pgconn): + assert isinstance(pgconn.ssl_in_use, bool) + + # If connecting via socket then ssl is not in use + if pgconn.host.startswith("/"): + assert not pgconn.ssl_in_use + else: + sslmode = [i.val for i in pgconn.info if i.keyword == "sslmode"][0] + if sslmode not in ("disable", "allow"): + # 'prefer' may still connect without ssl + # but maybe unlikely in the tests environment? + assert pgconn.ssl_in_use -- 2.47.3