From f17bb69bc809ccf31fc44fdc09a2f7dce32b2b51 Mon Sep 17 00:00:00 2001 From: Denis Laxalde Date: Fri, 11 Dec 2020 14:40:14 +0100 Subject: [PATCH] Make UI type mutable --- pgactivity/types.py | 36 +++++++++++++++++++++--------------- pgactivity/ui.py | 4 ++-- tests/test_views.txt | 10 +++++----- 3 files changed, 28 insertions(+), 22 deletions(-) diff --git a/pgactivity/types.py b/pgactivity/types.py index 3d83dff2..5c4fa6f5 100644 --- a/pgactivity/types.py +++ b/pgactivity/types.py @@ -363,7 +363,7 @@ def color(self, value: Any) -> str: return self.color_key -@attr.s(auto_attribs=True, frozen=True, slots=True) +@attr.s(auto_attribs=True, slots=True) class UI: """State of the UI.""" @@ -569,7 +569,7 @@ def start_interactive(self) -> None: >>> ui.interactive_timeout 3 """ - object.__setattr__(self, "interactive_timeout", 3) + self.interactive_timeout = 3 def end_interactive(self) -> None: """End interactive mode. @@ -581,7 +581,7 @@ def end_interactive(self) -> None: >>> ui.end_interactive() >>> ui.interactive_timeout """ - object.__setattr__(self, "interactive_timeout", None) + self.interactive_timeout = None def tick_interactive(self) -> None: """End interactive mode. @@ -610,36 +610,37 @@ def tick_interactive(self) -> None: if self.interactive_timeout is None: raise RuntimeError("cannot tick interactive mode") assert self.interactive_timeout > 0, self.interactive_timeout - new_value = (self.interactive_timeout - 1) or None - object.__setattr__(self, "interactive_timeout", new_value) + self.interactive_timeout = (self.interactive_timeout - 1) or None - def toggle_pause(self) -> "UI": + def toggle_pause(self) -> None: """Toggle 'in_pause' attribute. >>> ui = UI.make() >>> ui.in_pause False - >>> ui.toggle_pause().in_pause + >>> ui.toggle_pause() + >>> ui.in_pause True - >>> ui.toggle_pause().toggle_pause().in_pause + >>> ui.toggle_pause() + >>> ui.in_pause False """ - return attr.evolve(self, in_pause=not self.in_pause) + self.in_pause = not self.in_pause - def evolve(self, **changes: Any) -> "UI": + def evolve(self, **changes: Any) -> None: """Return a new UI with 'changes' applied. >>> ui = UI.make() >>> ui.query_mode.value 'running queries' - >>> new_ui = ui.evolve(query_mode=QueryMode.blocking, sort_key=SortKey.write) - >>> new_ui.query_mode.value + >>> ui.evolve(query_mode=QueryMode.blocking, sort_key=SortKey.write) + >>> ui.query_mode.value 'blocking queries' - >>> new_ui.sort_key.name + >>> ui.sort_key.name 'write' """ if self.in_pause: - return self + return forbidden = set(changes) - { "duration_mode", "verbose_mode", @@ -648,7 +649,12 @@ def evolve(self, **changes: Any) -> "UI": "refresh_time", } assert not forbidden, forbidden - return attr.evolve(self, **changes) + fields = attr.fields(self.__class__) + for field_name, value in changes.items(): + field = getattr(fields, field_name) + if field.converter: + value = field.converter(value) + setattr(self, field_name, value) def column(self, key: str) -> Column: """Return the column matching 'key'. diff --git a/pgactivity/ui.py b/pgactivity/ui.py index b09c96de..c8c980e9 100644 --- a/pgactivity/ui.py +++ b/pgactivity/ui.py @@ -74,7 +74,7 @@ def main( elif key == keys.EXIT: break elif not ui.interactive() and key == keys.SPACE: - ui = ui.toggle_pause() + ui.toggle_pause() elif options.nodbsize and key == keys.REFRESH_DB_SIZE: skip_sizes = False elif key is not None: @@ -152,7 +152,7 @@ def main( sort_key = handlers.sort_key_for(key, query_mode, flag) if sort_key is not None: changes["sort_key"] = sort_key - ui = ui.evolve(**changes) + ui.evolve(**changes) if in_help: # Only draw help screen once. diff --git a/tests/test_views.txt b/tests/test_views.txt index 236c201d..6ed45228 100644 --- a/tests/test_views.txt +++ b/tests/test_views.txt @@ -122,7 +122,7 @@ MEM% state Query >>> columns_header(term, ui, width=150) PID DATABASE APP CLIENT RELATION state Query ->>> ui = ui.evolve(query_mode=QueryMode.activities) +>>> ui.evolve(query_mode=QueryMode.activities) >>> columns_header(term, ui, width=150) PID DATABASE APP CLIENT W state Query @@ -196,13 +196,13 @@ p.name FROM products p LEFT JOIN sales s USING (product_id) WHERE s.date > CURRENT_DATE - INTERVAL '4 weeks' GROUP BY product_id, p.name, p.price, p.cost HAVING sum(p.price * s.units) > 5000; ->>> ui = ui.evolve(verbose_mode=QueryDisplayMode.truncate) +>>> ui.evolve(verbose_mode=QueryDisplayMode.truncate) >>> processes_rows(term, ui, SelectableProcesses(processes1)) 6239 pgbench 0.1 1.0 idle in trans UPDATE pgbench_accounts 6228 pgbench 0.2 1.0 active \_ UPDATE pgbench_accou 1234 business 2.4 1.0 active SELECT product_id, p.na ->>> ui = ui.evolve(verbose_mode=QueryDisplayMode.wrap) +>>> ui.evolve(verbose_mode=QueryDisplayMode.wrap) >>> processes_rows(term, ui, SelectableProcesses(processes1)) 6239 pgbench 0.1 1.0 idle in trans UPDATE pgbench_accounts SET abalance = abalance @@ -244,7 +244,7 @@ Terminal is too narrow given selected flags, we switch to wrap_noindent mode 6228 pgbench active \_ UPDATE pgbench_accounts SET abal 1234 business active SELECT product_id, p.name FROM prod ->>> ui = ui.evolve(verbose_mode=QueryDisplayMode.wrap) +>>> ui.evolve(verbose_mode=QueryDisplayMode.wrap) >>> processes_rows(term, ui, SelectableProcesses(processes1)) 6239 pgbench idle in trans UPDATE pgbench_accounts SET abalance = abalance + 141 WHERE aid @@ -288,7 +288,7 @@ Terminal is too narrow given selected flags, we switch to wrap_noindent mode ... query="UPDATE pgbench_branches SET bbalance = bbalance + 1788 WHERE bid = 68;", ... ), ... ] ->>> ui = ui.evolve(query_mode=QueryMode.waiting) +>>> ui.evolve(query_mode=QueryMode.waiting) >>> processes_rows(term, ui, SelectableProcesses(processes2)) 6239 pgbench active END; 6228 pgbench idle in trans UPDATE pgbench_branches SET