[tor-commits] [nyx/master] Centralize pausing in Controller

atagar at torproject.org atagar at torproject.org
Fri Jul 15 17:33:39 UTC 2016


commit e7385ff70800c162699c72de30822139b053982e
Author: Damian Johnson <atagar at torproject.org>
Date:   Thu Jul 14 10:24:59 2016 -0700

    Centralize pausing in Controller
    
    Pausing is a global state. We never pause only some of our interface, as such
    this belongs in the Controller. There's a couple panels that need special
    handling but otherwise a pretty straight forward move.
---
 nyx/controller.py       | 42 +++++++++++++++++++++++++++++++++---------
 nyx/panel/__init__.py   | 42 ++++--------------------------------------
 nyx/panel/connection.py |  6 ++++--
 nyx/panel/graph.py      | 12 +++++++-----
 nyx/panel/header.py     |  5 +++--
 nyx/panel/log.py        |  5 ++---
 test/panel/header.py    |  1 +
 7 files changed, 54 insertions(+), 59 deletions(-)

diff --git a/nyx/controller.py b/nyx/controller.py
index 964e27d..fc38185 100644
--- a/nyx/controller.py
+++ b/nyx/controller.py
@@ -120,7 +120,8 @@ class Controller(object):
 
     self.quit_signal = False
     self._page = 0
-    self._is_paused = False
+    self._paused = False
+    self._pause_time = -1
     self._force_redraw = False
     self._last_drawn = 0
 
@@ -171,23 +172,46 @@ class Controller(object):
 
   def is_paused(self):
     """
-    True if the interface is paused, false otherwise.
+    Provides if the interface is configured to be paused or not.
+
+    :returns: **True** if the interface is paused and **False** otherwise
     """
 
-    return self._is_paused
+    return self._paused
 
   def set_paused(self, is_pause):
     """
-    Sets the interface to be paused or unpaused.
+    Pauses or unpauses the interface.
+
+    :param bool is_pause: suspends the interface if **True**, resumes it
+      otherwise
     """
 
-    if is_pause != self._is_paused:
-      self._is_paused = is_pause
-      self._force_redraw = True
-      self.header_panel().redraw()
+    if is_pause != self._paused:
+      if is_pause:
+        self._pause_time = time.time()
+
+      # Couple panels have their own pausing behavior. I'll later change this to
+      # a listener approach or someting else that's less hacky.
 
       for panel_impl in self.get_all_panels():
-        panel_impl.set_paused(is_pause)
+        if isinstance(panel_impl, nyx.panel.graph.GraphPanel) or isinstance(panel_impl, nyx.panel.log.LogPanel):
+          panel_impl.set_paused(is_pause)
+
+      self._paused = is_pause
+
+      for panel_impl in self.get_display_panels():
+        panel_impl.redraw()
+
+  def get_pause_time(self):
+    """
+    Provides the time that we were last paused, returning -1 if we've never
+    been paused.
+
+    :returns: **float** with the unix timestamp for when we were last paused
+    """
+
+    return self._pause_time
 
   def header_panel(self):
     return self._header_panel
diff --git a/nyx/panel/__init__.py b/nyx/panel/__init__.py
index ee938dc..1d6ae9f 100644
--- a/nyx/panel/__init__.py
+++ b/nyx/panel/__init__.py
@@ -72,9 +72,6 @@ class Panel(object):
   def __init__(self):
     self._visible = False
 
-    self._paused = False
-    self._pause_time = -1
-
     self._top = 0
     self._left = 0
     self._height = -1
@@ -90,40 +87,6 @@ class Panel(object):
 
     self._visible = is_visible
 
-  def is_paused(self):
-    """
-    Provides if the panel's configured to be paused or not.
-    """
-
-    return self._paused
-
-  def set_paused(self, is_pause):
-    """
-    Toggles if the panel is paused or not. This causes the panel to be redrawn
-    when toggling is pause state unless told to do otherwise. This is
-    important when pausing since otherwise the panel's display could change
-    when redrawn for other reasons.
-
-    Arguments:
-      is_pause        - freezes the state of the pause attributes if true, makes
-                        them editable otherwise
-    """
-
-    if is_pause != self._paused:
-      if is_pause:
-        self._pause_time = time.time()
-
-      self._paused = is_pause
-      self.redraw()
-
-  def get_pause_time(self):
-    """
-    Provides the time that we were last paused, returning -1 if we've never
-    been paused.
-    """
-
-    return self._pause_time
-
   def get_top(self):
     """
     Provides the top position used for subwindows.
@@ -234,10 +197,13 @@ class DaemonPanel(Panel, threading.Thread):
     Performs our _update() action at the given rate.
     """
 
+    import nyx.controller
+
     last_ran = -1
+    nyx_controller = nyx.controller.get_controller()
 
     while not self._halt:
-      if self.is_paused() or (time.time() - last_ran) < self._update_rate:
+      if nyx_controller.is_paused() or (time.time() - last_ran) < self._update_rate:
         with self._pause_condition:
           if not self._halt:
             self._pause_condition.wait(0.2)
diff --git a/nyx/panel/connection.py b/nyx/panel/connection.py
index 8e032e6..bd78a9b 100644
--- a/nyx/panel/connection.py
+++ b/nyx/panel/connection.py
@@ -11,6 +11,7 @@ import collections
 import curses
 import itertools
 
+import nyx.controller
 import nyx.curses
 import nyx.panel
 import nyx.popups
@@ -401,6 +402,7 @@ class ConnectionPanel(nyx.panel.DaemonPanel):
 
   def draw(self, subwindow):
     controller = tor_controller()
+    nyx_controller = nyx.controller.get_controller()
     entries = self._entries
 
     lines = list(itertools.chain.from_iterable([entry.get_lines() for entry in entries]))
@@ -408,8 +410,8 @@ class ConnectionPanel(nyx.panel.DaemonPanel):
     details_offset = DETAILS_HEIGHT + 1 if is_showing_details else 0
     selected, scroll = self._scroller.selection(lines, subwindow.height - details_offset - 1)
 
-    if self.is_paused():
-      current_time = self.get_pause_time()
+    if nyx_controller.is_paused():
+      current_time = nyx_controller.get_pause_time()
     elif not controller.is_alive():
       current_time = controller.connection_time()
     else:
diff --git a/nyx/panel/graph.py b/nyx/panel/graph.py
index 029f417..e5f9cc7 100644
--- a/nyx/panel/graph.py
+++ b/nyx/panel/graph.py
@@ -481,8 +481,9 @@ class GraphPanel(nyx.panel.Panel):
     if not self.displayed_stat:
       return 0
 
+    nyx_controller = nyx.controller.get_controller()
     height = DEFAULT_CONTENT_HEIGHT + self._graph_height
-    accounting_stats = self._accounting_stats if self.is_paused() else self._accounting_stats_paused
+    accounting_stats = self._accounting_stats if nyx_controller.is_paused() else self._accounting_stats_paused
 
     if self.displayed_stat == GraphStat.BANDWIDTH and accounting_stats:
       height += 3
@@ -556,13 +557,13 @@ class GraphPanel(nyx.panel.Panel):
       self._accounting_stats_paused = copy.copy(self._accounting_stats)
       self._stats_paused = dict([(key, type(self._stats[key])(self._stats[key])) for key in self._stats])
 
-    nyx.panel.Panel.set_paused(self, is_pause)
-
   def draw(self, subwindow):
     if not self.displayed_stat:
       return
 
-    if not self.is_paused():
+    nyx_controller = nyx.controller.get_controller()
+
+    if not nyx_controller.is_paused():
       stat = self._stats[self.displayed_stat]
       accounting_stats = self._accounting_stats
     else:
@@ -586,10 +587,11 @@ class GraphPanel(nyx.panel.Panel):
     if not CONFIG['features.graph.bw.accounting.show']:
       self._accounting_stats = None
     elif not self._accounting_stats or time.time() - self._accounting_stats.retrieved >= ACCOUNTING_RATE:
+      nyx_controller = nyx.controller.get_controller()
       old_accounting_stats = self._accounting_stats
       self._accounting_stats = tor_controller().get_accounting_stats(None)
 
-      if not self.is_paused():
+      if not nyx_controller.is_paused():
         # if we either added or removed accounting info then redraw the whole
         # screen to account for resizing
 
diff --git a/nyx/panel/header.py b/nyx/panel/header.py
index a2a5ae7..5f33f4f 100644
--- a/nyx/panel/header.py
+++ b/nyx/panel/header.py
@@ -148,9 +148,10 @@ class HeaderPanel(nyx.panel.DaemonPanel):
 
     # space available for content
 
+    nyx_controller = nyx.controller.get_controller()
     left_width = max(subwindow.width / 2, 77) if is_wide else subwindow.width
     right_width = subwindow.width - left_width
-    pause_time = self.get_pause_time() if self.is_paused() else None
+    pause_time = nyx_controller.get_pause_time() if nyx_controller.is_paused() else None
 
     _draw_platform_section(subwindow, 0, 0, left_width, vals)
 
@@ -175,7 +176,7 @@ class HeaderPanel(nyx.panel.DaemonPanel):
         _draw_fingerprint_and_fd_usage(subwindow, 0, 3, left_width, vals)
         _draw_flags(subwindow, 0, 4, vals.flags)
 
-    _draw_status(subwindow, 0, self.get_height() - 1, self.is_paused(), self._message, *self._message_attr)
+    _draw_status(subwindow, 0, self.get_height() - 1, nyx_controller.is_paused(), self._message, *self._message_attr)
 
   def reset_listener(self, controller, event_type, _):
     self._update()
diff --git a/nyx/panel/log.py b/nyx/panel/log.py
index 81b7a64..02cd7fe 100644
--- a/nyx/panel/log.py
+++ b/nyx/panel/log.py
@@ -250,17 +250,16 @@ class LogPanel(nyx.panel.DaemonPanel):
     if is_pause:
       self._event_log_paused = self._event_log.clone()
 
-    nyx.panel.Panel.set_paused(self, is_pause)
-
   def draw(self, subwindow):
     scroll = self._scroller.location(self._last_content_height, subwindow.height - 1)
 
+    nyx_controller = nyx.controller.get_controller()
     event_filter = self._filter.clone()
     event_types = list(self._event_types)
     last_content_height = self._last_content_height
     show_duplicates = self._show_duplicates
 
-    event_log = self._event_log_paused if self.is_paused() else self._event_log
+    event_log = self._event_log_paused if nyx_controller.is_paused() else self._event_log
     event_log = filter(lambda entry: event_filter.match(entry.display_message), event_log)
     event_log = filter(lambda entry: not entry.is_duplicate or show_duplicates, event_log)
 
diff --git a/test/panel/header.py b/test/panel/header.py
index 3e47afa..c14b404 100644
--- a/test/panel/header.py
+++ b/test/panel/header.py
@@ -73,6 +73,7 @@ class TestHeaderPanel(unittest.TestCase):
   @patch('nyx.panel.header.tor_controller')
   @patch('nyx.panel.header.Sampling.create')
   def test_rendering_panel(self, sampling_mock, tor_controller_mock, nyx_controller_mock):
+    nyx_controller_mock().is_paused.return_value = False
     nyx_controller_mock().get_page.return_value = 1
     nyx_controller_mock().get_page_count.return_value = 4
     sampling_mock.return_value = test_sampling()





More information about the tor-commits mailing list