pgtoolkit.pgpass
This module provides support for .pgpass file format. Here are some highlights :
Supports
:
and\
escape.Sorts entry by precision (even if commented).
Preserves comments order when sorting.
See The Password File section in PostgreSQL documentation.
- pgtoolkit.pgpass.parse(file: Path | str | IO[str]) PassFile [source]
Parses a .pgpass file.
- Parameters:
file – Either a line iterator such as a file-like object or a file path to open and parse.
- Return type:
- pgtoolkit.pgpass.edit(fpath: Path | str) Iterator[PassFile] [source]
Context manager to edit a .pgpass file.
If the file does not exists, it is created with 600 permissions. Upon exit of the context manager, the file is saved, if no error occurred.
- class pgtoolkit.pgpass.PassEntry(hostname: str, port: int | str, database: str, username: str, password: str)[source]
Holds a .pgpass entry.
- classmethod parse(line: str) PassEntry [source]
Parse a single line.
- Parameters:
line – string containing a serialized .pgpass entry.
- Returns:
PassEntry
object holding entry data.- Raises:
ValueError – on invalid line.
- matches(**attrs: int | str) bool [source]
Tells if the current entry is matching provided attributes.
- Parameters:
attrs – keyword/values pairs correspond to one or more PassEntry attributes (ie. hostname, port, etc…)
- hostname
Server hostname, the first field.
- port
Server port, the second field.
- database
Database, the third field.
- username
Username, the fourth field.
- password
Password, the fifth field.
PassEntry
object is sortable. APassEntry
object is lower than another if it is more specific. The more an entry has wildcard, the less it is specific.
- class pgtoolkit.pgpass.PassComment[source]
A .pgpass comment, including spaces and
#
.It’s a child of
str
.>>> comm = PassComment("# my comment") >>> comm.comment 'my comment'
- matches(**attrs: int | str) bool [source]
In case of a commented entry, tells if it is matching provided attributes. Returns False otherwise.
- Parameters:
attrs – keyword/values pairs correspond to one or more PassEntry attributes (ie. hostname, port, etc…)
- comment
The actual message of the comment. Surrounding whitespaces stripped.
- class pgtoolkit.pgpass.PassFile(entries: list[PassComment | PassEntry] | None = None, *, path: str | None = None)[source]
Holds .pgpass file entries and comments.
- parse(fo: Iterable[str]) None [source]
Parse lines
- Parameters:
fo – A line iterator such as a file-like object.
Raises
ParseError
if a bad line is found.
- __iter__() Iterator[PassEntry] [source]
Iterate entries
Yield
PassEntry
instance from parsed file, ignoring comments.
- sort() None [source]
Sort entries preserving comments.
libpq use the first entry from .pgpass matching connexion informations. Thus, less specific entries should be last in the file. This is the purpose of
sort()
method.About comments. Comments are supposed to bear with the entrie below. Thus comments block are sorted according to the first entry below.
Commented entries are sorted like entries, not like comment.
- save(fo: IO[str] | None = None) None [source]
Save entries and comment in a file.
- Parameters:
fo – a file-like object. Is not required if
path
is set.
- remove(filter: Callable[[PassComment | PassEntry | str], bool] | None = None, **attrs: int | str) None [source]
Remove entries matching the provided attributes.
One can for example remove all entries for which port is 5433.
Note: commented entries matching will also be removed.
- Parameters:
filter – a function to be used as filter. It is passed the line to test against. If it returns True, the line is removed. It is kept otherwise.
attrs – keyword/values pairs correspond to one or more PassEntry attributes (ie. hostname, port, etc…)
Usage examples:
pgpass.remove(port=5432) pgpass.remove(filter=lambda r: r.port != 5432)
Editing a .pgpass file
with open('.pgpass') as fo:
pgpass = parse(fo)
pgpass.lines.append(PassEntry(username='toto', password='confidentiel'))
pgpass.sort()
with open('.pgpass', 'w') as fo:
pgpass.save(fo)
Shorter version using the file directly in parse:
pgpass = parse('.pgpass')
pgpass.lines.append(PassEntry(username='toto', password='confidentiel'))
pgpass.sort()
pgpass.save()
Alternatively, this can be done with the edit context manager:
with edit('.pgpass') as pgpass:
pgpass.lines.append((PassEntry(username='toto', password='confidentiel'))
passfile.sort()
Using as a script
You can call pgtoolkit.pgpass
module as a CLI script. It accepts a file
path as first argument, read it, validate it, sort it and output it in stdout.
$ python -m pgtoolkit.pgpass ~/.pgpass
more:5432:precise:entry:0revea\\ed
#disabled:5432:*:entry:0secret
# Multiline
# comment.
other:5432:*:username:0unveiled
*:*:*:postgres:c0nfident\:el