Skip to content

Commit

Permalink
Add support for configuration profiles
Browse files Browse the repository at this point in the history
  • Loading branch information
dlax committed Feb 19, 2024
1 parent 05776f6 commit f7a86c3
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 10 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
### Added

* The *rollback ratio* is now displayed in the "global" header (#385).
* Configuration profiles can now be defined at
`${XDG_CONFIG_HOME:~/.config}/pg_activity/<profile>.conf` or
`/etc/pg_activity/<profile>.conf` as selected from the command line through
`--profile <profile>`.

### Changed

Expand Down
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ ex:

pg_activity [options] [connection string]

Configuration:
--profile PROFILE Configuration profile matching a PROFILE.conf file in
${XDG_CONFIG_HOME:~/.config}/pg_activity/ or
/etc/pg_activity/.

Options:
--blocksize BLOCKSIZE
Filesystem blocksize (default: 4096).
Expand Down Expand Up @@ -140,7 +145,7 @@ ex:

## Configuration

`pg_activity` may be configured through configuration file, in [INI format][],
`pg_activity` may be configured through a configuration file, in [INI format][],
read from `${XDG_CONFIG_HOME:~/.config}/pg_activity.conf` or
`/etc/pg_activity.conf` in that order. Command-line options may override
configuration file settings.
Expand All @@ -153,6 +158,13 @@ hidden = yes
width = 9
```

Alternatively, the user might define *configuration profiles* in the form of
files located at `${XDG_CONFIG_HOME:~/.config}/pg_activity/<my-profile>.conf` or
`/etc/pg_activity/<my-profile>.conf`; these can then be used through the
`--profile <my-profile>` command-line option. The format of these files is the
same as the main configuration file.


[INI format]: https://docs.python.org/3/library/configparser.html#supported-ini-file-structure

## Notes
Expand Down
7 changes: 7 additions & 0 deletions docs/man/pg_activity.1
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,13 @@ required by another session. It shows following information:
.PD
.SH "COMMAND-LINE OPTIONS"
.IX Header "COMMAND-LINE OPTIONS"
.SS "\s-1CONFIGURATION\s0"
.IX Subsection "CONFIGURATION"
.IP "\fB\-\-profile=PROFILE\fR" 2
.IX Item "--profile=PROFILE"
.Vb 1
\& Configuration profile matching a PROFILE.conf file in ${XDG_CONFIG_HOME:~/.config}/pg_activity/ or /etc/pg_activity/.
.Ve
.SS "\s-1OPTIONS\s0"
.IX Subsection "OPTIONS"
.IP "\fB\-\-blocksize=BLOCKSIZE\fR" 2
Expand Down
10 changes: 10 additions & 0 deletions docs/man/pg_activity.pod
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,16 @@ required by another session. It shows following information:

=head1 COMMAND-LINE OPTIONS

=head2 CONFIGURATION

=over 2

=item B<--profile=PROFILE>

Configuration profile matching a PROFILE.conf file in ${XDG_CONFIG_HOME:~/.config}/pg_activity/ or /etc/pg_activity/.

=back

=head2 OPTIONS

=over 2
Expand Down
15 changes: 13 additions & 2 deletions pgactivity/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,17 @@ def get_parser() -> ArgumentParser:
add_help=False,
)

group = parser.add_argument_group(
"Configuration",
)
group.add_argument(
"--profile",
help=(
"Configuration profile matching a PROFILE.conf file in "
"${XDG_CONFIG_HOME:~/.config}/pg_activity/ or /etc/pg_activity/."
),
)

group = parser.add_argument_group(
"Options",
)
Expand Down Expand Up @@ -387,8 +398,8 @@ def main() -> None:
args.notempfile = True

try:
cfg = Configuration.lookup()
except ConfigurationError as e:
cfg = Configuration.lookup(args.profile)
except (ConfigurationError, FileNotFoundError) as e:
parser.error(str(e))

try:
Expand Down
21 changes: 16 additions & 5 deletions pgactivity/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,14 +261,25 @@ def parse(cls: Type[_T], f: IO[str], name: str) -> _T:
@classmethod
def lookup(
cls: Type[_T],
profile: Optional[str],
*,
user_config_home: Path = USER_CONFIG_HOME,
etc: Path = ETC,
) -> Optional[_T]:
for base in (user_config_home, etc):
fpath = base / "pg_activity.conf"
if profile is None:
for base in (user_config_home, etc):
fpath = base / "pg_activity.conf"
if fpath.exists():
with fpath.open() as f:
return cls.parse(f, str(fpath))
return None

assert profile # per argument validation
fname = f"{profile}.conf"
bases = (user_config_home / "pg_activity", etc / "pg_activity")
for base in bases:
fpath = base / fname
if fpath.exists():
with fpath.open() as f:
value = cls.parse(f, str(fpath))
return value
return None
return cls.parse(f, str(fpath))
raise FileNotFoundError(f"profile {profile!r} not found")
15 changes: 13 additions & 2 deletions tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from typing import Any, Dict

import attr
import pytest

from pgactivity.config import Configuration, Flag, UISection

Expand Down Expand Up @@ -78,9 +79,19 @@ def test_lookup(tmp_path: Path) -> None:
def asdict(cfg: Configuration) -> Dict[str, Any]:
return {k: attr.asdict(v) for k, v in cfg.items()}

cfg = Configuration.lookup(user_config_home=tmp_path)
cfg = Configuration.lookup(None, user_config_home=tmp_path)
assert cfg is None

(tmp_path / "pg_activity.conf").write_text("\n".join(["[client]", "width=5"]))
cfg = Configuration.lookup(user_config_home=tmp_path)
cfg = Configuration.lookup(None, user_config_home=tmp_path)
assert cfg is not None and asdict(cfg) == {"client": {"hidden": False, "width": 5}}

(tmp_path / "pg_activity").mkdir()
(tmp_path / "pg_activity" / "x.conf").write_text(
"\n".join(["[database]", "hidden= on", "width = 3 "])
)
cfg = Configuration.lookup("x", user_config_home=tmp_path)
assert cfg is not None and asdict(cfg) == {"database": {"hidden": True, "width": 3}}

with pytest.raises(FileNotFoundError):
Configuration.lookup("y", user_config_home=tmp_path)

0 comments on commit f7a86c3

Please sign in to comment.