From: Daniele Varrazzo Date: Mon, 2 Aug 2021 09:59:20 +0000 (+0200) Subject: Add ConnectionInfo.dsn property X-Git-Tag: 3.0.dev2~15 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4cff009a37f6e1e7f5b3edbb7be67528eb044a5a;p=thirdparty%2Fpsycopg.git Add ConnectionInfo.dsn property --- diff --git a/docs/api/connections.rst b/docs/api/connections.rst index 3e1ca25cb..cb3db196d 100644 --- a/docs/api/connections.rst +++ b/docs/api/connections.rst @@ -358,6 +358,11 @@ Connection support objects The object is usually returned by `Connection.info`. + .. autoattribute:: dsn + + .. note:: The `get_parameters()` method returns the same information + as a dict. + .. autoattribute:: status The status can be one of a number of values. However, only two of diff --git a/psycopg/psycopg/conninfo.py b/psycopg/psycopg/conninfo.py index 9dfff1339..9700c356f 100644 --- a/psycopg/psycopg/conninfo.py +++ b/psycopg/psycopg/conninfo.py @@ -161,8 +161,9 @@ class ConnectionInfo: """Return the connection parameters values. Return all the parameters set to a non-default value, which might come - either from the connection string or from environment variables. Don't - report the password (you can read it using the `password` attribute). + either from the connection string and parameters passed to + `~Connection.connect()` or from environment variables. The password + is never returned (you can read it using the `password` attribute). """ pyenc = self._pyenc @@ -184,6 +185,18 @@ class ConnectionInfo: and i.val != defaults.get(i.keyword) } + @property + def dsn(self) -> str: + """Return the conneciton string to connect to the database. + + The string contains all the parameters set to a non-default value, + which might come either from the connection string and parameters + passed to `~Connection.connect()` or from environment variables. The + password is never returned (you can read it using the `password` + attribute). + """ + return make_conninfo(**self.get_parameters()) + @property def status(self) -> pq.ConnStatus: """The status of the connection. See :pq:`PQstatus`.""" diff --git a/tests/test_conninfo.py b/tests/test_conninfo.py index 563e7d451..100e1e995 100644 --- a/tests/test_conninfo.py +++ b/tests/test_conninfo.py @@ -167,6 +167,13 @@ class TestConnectionInfo: else: assert k not in info + def test_dsn(self, conn, dsn): + dsn = conn.info.dsn + assert "password" not in dsn + for k, v in conninfo_to_dict(dsn).items(): + if k != "password": + assert f"{k}=" in dsn + def test_get_params_env(self, dsn, monkeypatch): dsn = conninfo_to_dict(dsn) dsn.pop("application_name", None) @@ -181,6 +188,18 @@ class TestConnectionInfo: conn.info.get_parameters()["application_name"] == "hello test" ) + def test_dsn_env(self, dsn, monkeypatch): + dsn = conninfo_to_dict(dsn) + dsn.pop("application_name", None) + + monkeypatch.delenv("PGAPPNAME", raising=False) + with psycopg.connect(**dsn) as conn: + assert "application_name=" not in conn.info.dsn + + monkeypatch.setenv("PGAPPNAME", "hello test") + with psycopg.connect(**dsn) as conn: + assert "application_name='hello test'" in conn.info.dsn + def test_status(self, conn): assert conn.info.status.name == "OK" conn.close() @@ -199,6 +218,14 @@ class TestConnectionInfo: assert "password" not in info.get_parameters() assert info.get_parameters()["dbname"] == info.dbname + def test_dsn_no_password(self, dsn): + dsn2 = make_conninfo(dsn, password="the-pass-word") + pgconn = psycopg.pq.PGconn.connect_start(dsn2.encode("utf8")) + info = ConnectionInfo(pgconn) + assert info.password == "the-pass-word" + assert "password" not in info.dsn + assert f"dbname={info.dbname}" in info.dsn + def test_parameter_status(self, conn): assert conn.info.parameter_status("nosuchparam") is None tz = conn.info.parameter_status("TimeZone")