commit 78355ab3700aa86eeae14e56b75368a082677362
Author: Damian Johnson <atagar(a)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