commit 78355ab3700aa86eeae14e56b75368a082677362 Author: Damian Johnson atagar@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
tor-commits@lists.torproject.org