Skip to content

Commit d3e5134

Browse files
committed
Support .pgpass files for migra
This eases the whole connection URI setup for developers who make use of the .pgpass file. Signed-off-by: Wesley Schwengle <[email protected]>
1 parent 5d7d2f4 commit d3e5134

File tree

3 files changed

+59
-2
lines changed

3 files changed

+59
-2
lines changed

docs/installing_and_connecting.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ The general form is as follows:
2626
:::bash
2727
connectiontype://username:password@databasehostname/databasename?extraparam1=a&extraparam2=b
2828

29+
If you have a .pgpass file in your $HOME dir, you can make use of that as well
30+
as you don't need to enter the password in the connection string:
31+
32+
:::bash
33+
postgresql://username@hostname/databasename
34+
2935
These can be left out if not necessary. For instance, if connecting locally, using your default system username and passwordless "trust" login, only a connection type and database name is required:
3036

3137
:::bash

migra/command.py

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
from __future__ import print_function, unicode_literals
22

33
import argparse
4+
import pgpasslib
45
import sys
5-
from contextlib import contextmanager
6+
import getpass
67

8+
from contextlib import contextmanager
9+
from sqlalchemy.engine.url import make_url
710
from sqlbag import S
811

912
from .migra import Migration
@@ -75,14 +78,61 @@ def parse_args(args):
7578
return parser.parse_args(args)
7679

7780

81+
def get_password_from_pgpass(host, port, database, username):
82+
if not host:
83+
host = 'localhost'
84+
85+
if not port:
86+
port = 5432
87+
88+
if not username:
89+
username = getpass.getuser()
90+
91+
if not database:
92+
database = username
93+
94+
try:
95+
return pgpasslib.getpass(
96+
host,
97+
port,
98+
database,
99+
username,
100+
)
101+
except pgpasslib.FileNotFound:
102+
return None
103+
104+
return None
105+
106+
107+
def get_password_from_uri(uri):
108+
109+
uri = make_url(uri)
110+
111+
if not uri.password:
112+
password = get_password_from_pgpass(
113+
uri.host,
114+
uri.port,
115+
uri.database,
116+
uri.username
117+
)
118+
if password:
119+
uri.set(password=password)
120+
121+
return uri
122+
123+
78124
def run(args, out=None, err=None):
79125
schema = args.schema
80126
exclude_schema = args.exclude_schema
81127
if not out:
82128
out = sys.stdout # pragma: no cover
83129
if not err:
84130
err = sys.stderr # pragma: no cover
85-
with arg_context(args.dburl_from) as ac0, arg_context(args.dburl_target) as ac1:
131+
132+
db_from = get_password_from_uri(args.dburl_from)
133+
db_to = get_password_from_uri(args.dburl_target)
134+
135+
with arg_context(db_from) as ac0, arg_context(db_to) as ac1:
86136
m = Migration(
87137
ac0,
88138
ac1,

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ six = "*"
1616
# schemainspect = {path="../schemainspect", develop=true}
1717
schemainspect = ">=3.1.1652015119"
1818
psycopg2-binary = { version="*", optional = true }
19+
pgpasslib = "*"
1920

2021
[tool.poetry.dev-dependencies]
2122
sqlbag = "*"

0 commit comments

Comments
 (0)