userver: en/testsuite/databases/pgsql/connection.py Source File
Loading...
Searching...
No Matches
connection.py
1# pylint: disable=no-member
2import typing
3import urllib.parse
4
5import psycopg2.extensions
6
7
8class _NotSet:
9 pass
10
11
12class PgConnectionInfo(typing.NamedTuple):
13 """
14 PostgreSQL connection parameters
15 """
16
17 host: str | None = None
18 port: int | None = None
19 user: str | None = None
20 password: str | None = None
21 options: str | None = None
22 sslmode: str | None = None
23 dbname: str | None = None
24
25 def get_dsn(self) -> str:
26 """PostgreSQL connection string in DSN format"""
27 return psycopg2.extensions.make_dsn(
28 host=self.host,
29 port=self.port,
30 user=self.user,
31 password=self.password,
32 options=self.options,
33 sslmode=self.sslmode,
34 dbname=self.dbname,
35 )
36
37 def get_uri(self) -> str:
38 """PostgreSQL connection string in URI format"""
39 return get_connection_uri(**self._asdict())
40
41 def replace(self, **kwargs) -> 'PgConnectionInfo':
42 """Return a new :py:class:`PgConnectionInfo` value replacing specified
43 fields with new values
44 """
45 return self._replace(**kwargs)
46
47
48def parse_connection_string(connstr: str) -> PgConnectionInfo:
49 """Parse PostgreSQL connection string.
50 :param connstr: connection string in DSN or URI format as specified in
51 https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING
52 """
53 kwargs = psycopg2.extensions.parse_dsn(connstr)
54 for key, value in kwargs.items():
55 if key not in PgConnectionInfo._fields:
56 continue
57 if key == 'port':
58 kwargs[key] = int(value)
59 else:
60 kwargs[key] = value
61 return PgConnectionInfo(**kwargs)
62
63
64def get_connection_uri(**kwargs):
65 kwargs = {key: value for key, value in kwargs.items() if value is not None}
66 dbname = kwargs.pop('dbname', '')
67 if kwargs:
68 items = (
69 (key, urllib.parse.quote(str(value)))
70 for key, value in kwargs.items()
71 )
72 query = '?' + '&'.join(f'{key}={value}' for key, value in items)
73 else:
74 query = ''
75 return f'postgresql:///{dbname}{query}'