Skip to content

Commit 2feac0e

Browse files
committed
Make cell (default) color configurable
This only applies to columns with a fixed color, i.e. that does not depend on the value (like do the 'time' or 'state' columns). Although this limitation is not handled in the Configuration class, we intercept invalid 'color' option in column configuration while loading the types.UI object and still return a ConfigurationError so that the user experience is quite similar.
1 parent d50700c commit 2feac0e

File tree

6 files changed

+40
-6
lines changed

6 files changed

+40
-6
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
## pg\_activity 3.6.0 - UNRELEASED
44

5+
### Added
6+
7+
* The color of cells in the process table can now be customized through the
8+
configuration file.
9+
510
### Changed
611

712
* Exit with status 0 upon keyboard interrupt.

README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,24 @@ same as the main configuration file.
180180
- `minimal`, providing an even more minimal user interface with header
181181
information hidden
182182

183+
Columns of the process table in pg\_activity user interface can be assigned a
184+
custom color in the configuration file, e.g.:
185+
```ini
186+
[client]
187+
color = magenta
188+
189+
[relation]
190+
color = red
191+
```
192+
193+
The `color` option illustrated above defines the color used to render the cell
194+
independently of its value, i.e. the "normal" color. Some columns may be
195+
colorized differently depending on the value of their cells; for example, the
196+
`time` column can handle tree colors depending on whether the time value is
197+
*high*, *medium* or *low*. The color of such columns cannot be currently
198+
customized and attempting to do so will result in pg\_activity to exit early
199+
with an error message.
200+
183201
[INI format]: https://docs.python.org/3/library/configparser.html#supported-ini-file-structure
184202

185203
## Notes

pgactivity/cli.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,8 @@ def main() -> None:
425425
while True:
426426
try:
427427
ui.main(term, cfg, dataobj, host, args)
428+
except ConfigurationError as e:
429+
parser.exit(1, f"error: {e}")
428430
except OperationalError:
429431
while True:
430432
print(term.clear + term.home, end="")

pgactivity/config.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ def from_config_section(cls: type[_T], section: configparser.SectionProxy) -> _T
202202
class UISection(BaseSectionMixin):
203203
hidden: bool = False
204204
width: int | None = attr.ib(default=None, validator=validators.optional(gt(0)))
205+
color: str | None = attr.ib(default=None)
205206

206207
_T = TypeVar("_T", bound="UISection")
207208

@@ -213,6 +214,7 @@ def from_config_section(cls: type[_T], section: configparser.SectionProxy) -> _T
213214
if hidden is not None:
214215
values["hidden"] = hidden
215216
values["width"] = section.getint("width")
217+
values["color"] = section.get("color")
216218
return cls(**values)
217219

218220

@@ -262,12 +264,12 @@ def parse(cls: type[_T], f: IO[str], name: str) -> _T:
262264
>>> from io import StringIO
263265
>>> from pprint import pprint
264266
265-
>>> f = StringIO('[header]\nshow_workers=false\n[client]\nhidden=true\n')
267+
>>> f = StringIO('[header]\nshow_workers=false\n[client]\nhidden=true\ncolor=green\n')
266268
>>> cfg = Configuration.parse(f, "f.ini")
267269
>>> cfg.name
268270
'f.ini'
269271
>>> pprint(cfg.values)
270-
{'client': UISection(hidden=True, width=None),
272+
{'client': UISection(hidden=True, width=None, color='green'),
271273
'header': HeaderSection(show_instance=True, show_system=True, show_workers=False)}
272274
273275
>>> bad = StringIO("[global]\nx=1")

pgactivity/types.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,12 @@ def add_column(key: str, name: str, **kwargs: Any) -> None:
301301
assert isinstance(cfg, UISection), cfg
302302
if cfg.width is not None:
303303
kwargs["min_width"] = kwargs["max_width"] = cfg.width
304+
if cfg.color is not None:
305+
if kwargs.get("value_color"):
306+
raise config.error(
307+
f"the color for '{name}' column (option '{key}') cannot be configured"
308+
)
309+
kwargs["default_color"] = cfg.color
304310
assert key not in possible_columns, f"duplicated key {key}"
305311
possible_columns[key] = Column(key=key, name=name, **kwargs)
306312

tests/test_config.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,14 +101,15 @@ def test_lookup(tmp_path: Path) -> None:
101101
[
102102
"[client]",
103103
"width=5",
104+
"color=cyan",
104105
"[header]",
105106
"show_instance=no",
106107
]
107108
)
108109
)
109110
cfg = Configuration.lookup(None, user_config_home=tmp_path)
110111
assert cfg is not None and asdict(cfg) == {
111-
"client": {"hidden": False, "width": 5},
112+
"client": {"hidden": False, "width": 5, "color": "cyan"},
112113
"header": {"show_instance": False, "show_system": True, "show_workers": True},
113114
}
114115

@@ -120,7 +121,7 @@ def test_lookup(tmp_path: Path) -> None:
120121
)
121122
cfg = Configuration.lookup("x", user_config_home=tmp_path)
122123
assert cfg is not None and asdict(cfg) == {
123-
"database": {"hidden": True, "width": 3},
124+
"database": {"hidden": True, "width": 3, "color": None},
124125
"header": {"show_instance": True, "show_system": True, "show_workers": False},
125126
}
126127

@@ -132,8 +133,8 @@ def test_lookup(tmp_path: Path) -> None:
132133
"header": {k: False for k in ("show_instance", "show_system", "show_workers")}
133134
}
134135
columns = ("database", "user", "client", "cpu", "mem", "read", "write", "appname")
135-
narrow = {k: {"hidden": True, "width": None} for k in columns}
136-
wide = {k: {"hidden": False, "width": None} for k in columns}
136+
narrow = {k: {"hidden": True, "width": None, "color": None} for k in columns}
137+
wide = {k: {"hidden": False, "width": None, "color": None} for k in columns}
137138
minimal = {**no_header, **narrow}
138139

139140

0 commit comments

Comments
 (0)