7
7
from __future__ import annotations
8
8
9
9
import asyncio
10
+ import configparser
10
11
import collections
11
12
from collections .abc import Callable
12
13
import enum
@@ -87,6 +88,9 @@ class SSLNegotiation(compat.StrEnum):
87
88
PGPASSFILE = '.pgpass'
88
89
89
90
91
+ PG_SERVICEFILE = '.pg_service.conf'
92
+
93
+
90
94
def _read_password_file (passfile : pathlib .Path ) \
91
95
-> typing .List [typing .Tuple [str , ...]]:
92
96
@@ -268,7 +272,7 @@ def _dot_postgresql_path(filename) -> typing.Optional[pathlib.Path]:
268
272
269
273
270
274
def _parse_connect_dsn_and_args (* , dsn , host , port , user ,
271
- password , passfile , database , ssl ,
275
+ password , passfile , database , ssl , service ,
272
276
direct_tls , server_settings ,
273
277
target_session_attrs , krbsrvname , gsslib ):
274
278
# `auth_hosts` is the version of host information for the purposes
@@ -278,6 +282,120 @@ def _parse_connect_dsn_and_args(*, dsn, host, port, user,
278
282
ssl_min_protocol_version = ssl_max_protocol_version = None
279
283
sslnegotiation = None
280
284
285
+ if dsn :
286
+ parsed = urllib .parse .urlparse (dsn )
287
+ if parsed .query :
288
+ query = urllib .parse .parse_qs (parsed .query , strict_parsing = True )
289
+ for key , val in query .items ():
290
+ if isinstance (val , list ):
291
+ query [key ] = val [- 1 ]
292
+
293
+ if 'service' in query :
294
+ val = query .pop ('service' )
295
+ if not service and val :
296
+ service = val
297
+
298
+ connection_service_file = os .getenv ('PGSERVICEFILE' )
299
+ if connection_service_file is None :
300
+ homedir = compat .get_pg_home_directory ()
301
+ if homedir :
302
+ connection_service_file = homedir / PG_SERVICEFILE
303
+ else :
304
+ connection_service_file = None
305
+ else :
306
+ connection_service_file = pathlib .Path (connection_service_file )
307
+
308
+ if connection_service_file is not None and service is not None :
309
+ # TODO Open and parse connection service file
310
+ pg_service = configparser .ConfigParser ()
311
+ pg_service .read (connection_service_file )
312
+ if service in pg_service .sections ():
313
+ service_params = pg_service [service ]
314
+ if 'port' in service_params :
315
+ val = service_params .pop ('port' )
316
+ if not port and val :
317
+ port = [int (p ) for p in val .split (',' )]
318
+
319
+ if 'host' in service_params :
320
+ val = service_params .pop ('host' )
321
+ if not host and val :
322
+ host , port = _parse_hostlist (val , port )
323
+
324
+ if 'dbname' in service_params :
325
+ val = service_params .pop ('dbname' )
326
+ if database is None :
327
+ database = val
328
+
329
+ if 'database' in service_params :
330
+ val = service_params .pop ('database' )
331
+ if database is None :
332
+ database = val
333
+
334
+ if 'user' in service_params :
335
+ val = service_params .pop ('user' )
336
+ if user is None :
337
+ user = val
338
+
339
+ if 'password' in service_params :
340
+ val = service_params .pop ('password' )
341
+ if password is None :
342
+ password = val
343
+
344
+ if 'passfile' in service_params :
345
+ val = service_params .pop ('passfile' )
346
+ if passfile is None :
347
+ passfile = val
348
+
349
+ if 'sslmode' in service_params :
350
+ val = service_params .pop ('sslmode' )
351
+ if ssl is None :
352
+ ssl = val
353
+
354
+ if 'sslcert' in service_params :
355
+ sslcert = service_params .pop ('sslcert' )
356
+
357
+ if 'sslkey' in service_params :
358
+ sslkey = service_params .pop ('sslkey' )
359
+
360
+ if 'sslrootcert' in service_params :
361
+ sslrootcert = service_params .pop ('sslrootcert' )
362
+
363
+ if 'sslnegotiation' in service_params :
364
+ sslnegotiation = service_params .pop ('sslnegotiation' )
365
+
366
+ if 'sslcrl' in service_params :
367
+ sslcrl = service_params .pop ('sslcrl' )
368
+
369
+ if 'sslpassword' in service_params :
370
+ sslpassword = service_params .pop ('sslpassword' )
371
+
372
+ if 'ssl_min_protocol_version' in service_params :
373
+ ssl_min_protocol_version = service_params .pop (
374
+ 'ssl_min_protocol_version'
375
+ )
376
+
377
+ if 'ssl_max_protocol_version' in service_params :
378
+ ssl_max_protocol_version = service_params .pop (
379
+ 'ssl_max_protocol_version'
380
+ )
381
+
382
+ if 'target_session_attrs' in service_params :
383
+ dsn_target_session_attrs = service_params .pop (
384
+ 'target_session_attrs'
385
+ )
386
+ if target_session_attrs is None :
387
+ target_session_attrs = dsn_target_session_attrs
388
+
389
+ if 'krbsrvname' in service_params :
390
+ val = service_params .pop ('krbsrvname' )
391
+ if krbsrvname is None :
392
+ krbsrvname = val
393
+
394
+ if 'gsslib' in service_params :
395
+ val = service_params .pop ('gsslib' )
396
+ if gsslib is None :
397
+ gsslib = val
398
+
281
399
if dsn :
282
400
parsed = urllib .parse .urlparse (dsn )
283
401
@@ -406,6 +524,9 @@ def _parse_connect_dsn_and_args(*, dsn, host, port, user,
406
524
if gsslib is None :
407
525
gsslib = val
408
526
527
+ if 'service' in query :
528
+ val = query .pop ('service' )
529
+
409
530
if query :
410
531
if server_settings is None :
411
532
server_settings = query
@@ -491,6 +612,7 @@ def _parse_connect_dsn_and_args(*, dsn, host, port, user,
491
612
database = database , user = user ,
492
613
passfile = passfile )
493
614
615
+
494
616
addrs = []
495
617
have_tcp_addrs = False
496
618
for h , p in zip (host , port ):
@@ -724,7 +846,7 @@ def _parse_connect_arguments(*, dsn, host, port, user, password, passfile,
724
846
max_cached_statement_lifetime ,
725
847
max_cacheable_statement_size ,
726
848
ssl , direct_tls , server_settings ,
727
- target_session_attrs , krbsrvname , gsslib ):
849
+ target_session_attrs , krbsrvname , gsslib , service ):
728
850
local_vars = locals ()
729
851
for var_name in {'max_cacheable_statement_size' ,
730
852
'max_cached_statement_lifetime' ,
@@ -754,7 +876,7 @@ def _parse_connect_arguments(*, dsn, host, port, user, password, passfile,
754
876
direct_tls = direct_tls , database = database ,
755
877
server_settings = server_settings ,
756
878
target_session_attrs = target_session_attrs ,
757
- krbsrvname = krbsrvname , gsslib = gsslib )
879
+ krbsrvname = krbsrvname , gsslib = gsslib , service = service )
758
880
759
881
config = _ClientConfiguration (
760
882
command_timeout = command_timeout ,
0 commit comments