[tor-commits] [nyx/master] Fix log panel's ability to pause

atagar at torproject.org atagar at torproject.org
Sun Mar 20 00:17:45 UTC 2016


commit 78355ab3700aa86eeae14e56b75368a082677362
Author: Damian Johnson <atagar at torproject.org>
Date:   Sat Mar 19 15:41:55 2016 -0700

    Fix log panel's ability to pause
    
    When paused the log panel didn't actually freeze its content. To do this
    implementing clone method for our LogGroup.
---
 nyx/controller.py       |  2 +-
 nyx/log.py              | 32 ++++++++++++++++++++++++--------
 nyx/panel/__init__.py   |  9 +++------
 nyx/panel/config.py     |  2 +-
 nyx/panel/connection.py |  2 +-
 nyx/panel/graph.py      |  2 +-
 nyx/panel/header.py     |  2 +-
 nyx/panel/log.py        | 13 +++++++++----
 nyx/popups.py           |  6 ++----
 9 files changed, 43 insertions(+), 27 deletions(-)

diff --git a/nyx/controller.py b/nyx/controller.py
index 32f4db5..e469358 100644
--- a/nyx/controller.py
+++ b/nyx/controller.py
@@ -64,7 +64,7 @@ class LabelPanel(nyx.panel.Panel):
   """
 
   def __init__(self):
-    nyx.panel.Panel.__init__(self, 'msg', 0, height=1)
+    nyx.panel.Panel.__init__(self, 'msg', height = 1)
     self.msg_text = ''
     self.msg_attr = NORMAL
 
diff --git a/nyx/log.py b/nyx/log.py
index 642e97c..aeae399 100644
--- a/nyx/log.py
+++ b/nyx/log.py
@@ -19,11 +19,13 @@ runlevels.
 
   LogGroup - thread safe, deduplicated grouping of events
     |- add - adds an event to the group
-    +- pop - removes and returns an event
+    |- pop - removes and returns an event
+    +- clone - deep copy of this LogGroup
 
   LogEntry - individual log event
     |- is_duplicate_of - checks if a duplicate message of another LogEntry
-    +- day_count - number of days since this even occured
+    |- day_count - number of days since this even occured
+    +- clone - deep copy of this LogEntry
 
   LogFileOutput - writes log events to a file
     +- write - persist a given message
@@ -33,7 +35,7 @@ runlevels.
     |- selection - current regex filter
     |- latest_selections - past regex selections
     |- match - checks if a LogEntry matches this filter
-    +- clone - deep clone of this LogFilters
+    +- clone - deep copy of this LogFilters
 """
 
 import collections
@@ -261,6 +263,12 @@ class LogGroup(object):
       if last_entry.is_duplicate:
         last_entry.duplicates.pop()
 
+  def clone(self):
+    with self._lock:
+      copy = LogGroup(self._max_size, self._group_by_day)
+      copy._entries = [entry.clone() for entry in self._entries]
+      return copy
+
   def __len__(self):
     with self._lock:
       return len(self._entries)
@@ -285,7 +293,7 @@ class LogEntry(object):
 
   :var bool is_duplicate: true if this matches other messages in the group and
     isn't the first
-  :var list duplicates: messages that are identical to thsi one
+  :var list duplicates: messages that are identical to this one
   """
 
   def __init__(self, timestamp, type, message):
@@ -340,6 +348,13 @@ class LogEntry(object):
 
     return day_count(self.timestamp)
 
+  def clone(self):
+    copy = LogEntry(self.timestamp, self.type, self.message)
+    copy.is_duplicate = self.is_duplicate
+    copy.duplicates = None if self.duplicates is None else list(self.duplicates)
+
+    return copy
+
   def __eq__(self, other):
     if isinstance(other, LogEntry):
       return hash(self) == hash(other)
@@ -431,10 +446,11 @@ class LogFilters(object):
 
   def clone(self):
     with self._lock:
-      clone = LogFilters(max_filters = self._max_filters)
-      clone._selected = self._selected
-      clone._past_filters = self._past_filters
-      return clone
+      copy = LogFilters(max_filters = self._max_filters)
+      copy._selected = self._selected
+      copy._past_filters = self._past_filters
+
+      return copy
 
 
 def trace(msg, **attr):
diff --git a/nyx/panel/__init__.py b/nyx/panel/__init__.py
index bab0cc7..c47ac59 100644
--- a/nyx/panel/__init__.py
+++ b/nyx/panel/__init__.py
@@ -122,7 +122,7 @@ class Panel(object):
   redraw().
   """
 
-  def __init__(self, name, top, left = 0, height = -1, width = -1):
+  def __init__(self, name, top = 0, left = 0, height = -1, width = -1):
     """
     Creates a durable wrapper for a curses subwindow in the given parent.
 
@@ -257,7 +257,7 @@ class Panel(object):
     current_value = self.__dict__.get(attr)
     return copy.copy(current_value)
 
-  def set_paused(self, is_pause, suppress_redraw = False):
+  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
@@ -269,7 +269,6 @@ class Panel(object):
     Arguments:
       is_pause        - freezes the state of the pause attributes if true, makes
                         them editable otherwise
-      suppress_redraw - if true then this will never redraw the panel
     """
 
     if is_pause != self.paused:
@@ -284,9 +283,7 @@ class Panel(object):
         for attr in self.pause_attr:
           self.pause_buffer[attr] = self.copy_attr(attr)
 
-      if not suppress_redraw:
-        self.redraw(True)
-
+      self.redraw(True)
       return True
     else:
       return False
diff --git a/nyx/panel/config.py b/nyx/panel/config.py
index fc6dad1..765345a 100644
--- a/nyx/panel/config.py
+++ b/nyx/panel/config.py
@@ -119,7 +119,7 @@ class ConfigPanel(nyx.panel.Panel):
   """
 
   def __init__(self):
-    nyx.panel.Panel.__init__(self, 'configuration', 0)
+    nyx.panel.Panel.__init__(self, 'configuration')
 
     self._contents = []
     self._scroller = nyx.curses.CursorScroller()
diff --git a/nyx/panel/connection.py b/nyx/panel/connection.py
index 09efafb..3d571ec 100644
--- a/nyx/panel/connection.py
+++ b/nyx/panel/connection.py
@@ -260,7 +260,7 @@ class ConnectionPanel(nyx.panel.Panel, threading.Thread):
   """
 
   def __init__(self):
-    nyx.panel.Panel.__init__(self, 'connections', 0)
+    nyx.panel.Panel.__init__(self, 'connections')
     threading.Thread.__init__(self)
     self.setDaemon(True)
 
diff --git a/nyx/panel/graph.py b/nyx/panel/graph.py
index e4a0ce7..20a6110 100644
--- a/nyx/panel/graph.py
+++ b/nyx/panel/graph.py
@@ -382,7 +382,7 @@ class GraphPanel(nyx.panel.Panel):
   """
 
   def __init__(self):
-    nyx.panel.Panel.__init__(self, 'graph', 0)
+    nyx.panel.Panel.__init__(self, 'graph')
 
     self._displayed_stat = None if CONFIG['features.graph.type'] == 'none' else CONFIG['features.graph.type']
     self._update_interval = CONFIG['features.graph.interval']
diff --git a/nyx/panel/header.py b/nyx/panel/header.py
index c3bba36..0c7aa1b 100644
--- a/nyx/panel/header.py
+++ b/nyx/panel/header.py
@@ -38,7 +38,7 @@ class HeaderPanel(nyx.panel.Panel, threading.Thread):
   """
 
   def __init__(self):
-    nyx.panel.Panel.__init__(self, 'header', 0)
+    nyx.panel.Panel.__init__(self, 'header')
     threading.Thread.__init__(self)
     self.setDaemon(True)
 
diff --git a/nyx/panel/log.py b/nyx/panel/log.py
index d6e00de..159469a 100644
--- a/nyx/panel/log.py
+++ b/nyx/panel/log.py
@@ -65,19 +65,18 @@ class LogPanel(nyx.panel.Panel, threading.Thread):
   """
 
   def __init__(self):
-    nyx.panel.Panel.__init__(self, 'log', 0)
+    nyx.panel.Panel.__init__(self, 'log')
     threading.Thread.__init__(self)
     self.setDaemon(True)
 
     logged_events = nyx.arguments.expand_events(CONFIG['startup.events'])
     self._event_log = nyx.log.LogGroup(CONFIG['cache.log_panel.size'], group_by_day = True)
+    self._event_log_paused = None
     self._event_types = nyx.log.listen_for_events(self._register_tor_event, logged_events)
     self._log_file = nyx.log.LogFileOutput(CONFIG['features.logFile'])
     self._filter = nyx.log.LogFilters(initial_filters = CONFIG['features.log.regex'])
     self._show_duplicates = CONFIG['features.log.showDuplicateEntries']
 
-    self.set_pause_attr('_event_log')
-
     self._scroller = nyx.curses.Scroller()
     self._halt = False  # terminates thread if true
     self._pause_condition = threading.Condition()
@@ -271,10 +270,16 @@ class LogPanel(nyx.panel.Panel, threading.Thread):
       ('c', 'clear event log', None),
     ]
 
+  def set_paused(self, is_pause):
+    if is_pause:
+      self._event_log_paused = self._event_log.clone()
+
+    nyx.panel.Panel.set_paused(self, is_pause)
+
   def draw(self, width, height):
     scroll = self._scroller.location(self._last_content_height, height)
 
-    event_log = list(self.get_attr('_event_log'))
+    event_log = list(self._event_log_paused if self.is_paused() else self._event_log)
     event_filter = self._filter.clone()
     event_types = list(self._event_types)
     last_content_height = self._last_content_height
diff --git a/nyx/popups.py b/nyx/popups.py
index 6190a09..89fa26e 100644
--- a/nyx/popups.py
+++ b/nyx/popups.py
@@ -24,7 +24,7 @@ UNRESOLVED_MSG = 'No consensus data available'
 ERROR_MSG = 'Unable to retrieve data'
 
 
-def popup_window(height = -1, width = -1, top = 0, left = 0, below_static = True):
+def popup_window(height = -1, width = -1, below_static = True):
   """
   Provides a popup dialog you can use in a 'with' block...
 
@@ -38,8 +38,6 @@ def popup_window(height = -1, width = -1, top = 0, left = 0, below_static = True
 
   :param int height: maximum height of the popup
   :param int width: maximum width of the popup
-  :param int top: top position, relative to the sticky content
-  :param int left: left position from the screen
   :param bool below_static: positions popup below static content if True
 
   :returns: tuple of the form (subwindow, width, height) when used in a with block
@@ -54,7 +52,7 @@ def popup_window(height = -1, width = -1, top = 0, left = 0, below_static = True
       else:
         sticky_height = 0
 
-      popup = nyx.panel.Panel('popup', top + sticky_height, left, height, width)
+      popup = nyx.panel.Panel('popup', top = sticky_height, height = height, width = width)
       popup.set_visible(True)
 
       # Redraws the popup to prepare a subwindow instance. If none is spawned then





More information about the tor-commits mailing list