[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [arm/master] Using @property for GraphPanel attributes
commit e773d64a6046ee3f2256b9ba26a078efd52eb4cd
Author: Damian Johnson <atagar@xxxxxxxxxxxxxx>
Date: Sun Nov 16 12:25:47 2014 -0800
Using @property for GraphPanel attributes
Neat, learned something new. Nice decorator replaement for the getter/setter
pattern.
---
arm/graph_panel.py | 170 ++++++++++++++++++++++-----------------------------
arm/menu/actions.py | 8 +--
arm/util/panel.py | 2 +-
3 files changed, 79 insertions(+), 101 deletions(-)
diff --git a/arm/graph_panel.py b/arm/graph_panel.py
index 3dfefbe..b6f8c97 100644
--- a/arm/graph_panel.py
+++ b/arm/graph_panel.py
@@ -355,7 +355,7 @@ class GraphPanel(panel.Panel):
def __init__(self, stdscr):
panel.Panel.__init__(self, stdscr, 'graph', 0)
- self._current_display = None if CONFIG['features.graph.type'] == 'none' else CONFIG['features.graph.type']
+ self._displayed_stat = None if CONFIG['features.graph.type'] == 'none' else CONFIG['features.graph.type']
self._update_interval = CONFIG['features.graph.interval']
self._bounds = CONFIG['features.graph.bound']
@@ -386,13 +386,49 @@ class GraphPanel(panel.Panel):
else:
log.notice(msg('panel.graphing.prepopulation_all_successful'))
- self._update_interval = Interval.FIFTEEN_MINUTE
+ self.update_interval = Interval.FIFTEEN_MINUTE
except ValueError as exc:
log.info(msg('panel.graphing.prepopulation_failure', error = exc))
controller.add_event_listener(self.bandwidth_event, EventType.BW)
controller.add_status_listener(self.reset_listener)
+ @property
+ def displayed_stat(self):
+ return self._displayed_stat
+
+ @displayed_stat.setter
+ def displayed_stat(self, value):
+ if value is not None and value not in self._stats.keys():
+ raise ValueError("%s isn't a graphed statistic" % value)
+
+ self._displayed_stat = value
+
+ def stat_options(self):
+ return self._stats.keys()
+
+ @property
+ def update_interval(self):
+ return self._update_interval
+
+ @update_interval.setter
+ def update_interval(self, value):
+ if value not in Interval:
+ raise ValueError("%s isn't a valid graphing update interval" % value)
+
+ self._update_interval = value
+
+ @property
+ def bounds_type(self):
+ return self._bounds
+
+ @bounds_type.setter
+ def bounds_type(self, value):
+ if value not in Bounds:
+ raise ValueError("%s isn't a valid type of bounds" % value)
+
+ self._bounds = value
+
def bandwidth_event(self, event):
for stat in self._stats.values():
stat.bandwidth_event(event)
@@ -408,8 +444,8 @@ class GraphPanel(panel.Panel):
arm.controller.get_controller().redraw()
- update_rate = INTERVAL_SECONDS[self._update_interval]
- param = self.get_attr('_stats')[self._current_display]
+ update_rate = INTERVAL_SECONDS[self.update_interval]
+ param = self.get_attr('_stats')[self.displayed_stat]
if param.primary.tick % update_rate == 0:
self.redraw(True)
@@ -417,52 +453,17 @@ class GraphPanel(panel.Panel):
def reset_listener(self, controller, event_type, _):
self.redraw(True)
- def get_update_interval(self):
- """
- Provides the rate that we update the graph at.
- """
-
- return self._update_interval
-
- def set_update_interval(self, update_interval):
- """
- Sets the rate that we update the graph at.
-
- Arguments:
- update_interval - update time enum
- """
-
- self._update_interval = update_interval
-
- def get_bounds_type(self):
- """
- Provides the type of graph bounds used.
- """
-
- return self._bounds
-
- def set_bounds_type(self, bounds_type):
- """
- Sets the type of graph boundaries we use.
-
- Arguments:
- bounds_type - graph bounds enum
- """
-
- self._bounds = bounds_type
-
def get_height(self):
"""
- Provides the height requested by the currently displayed GraphCategory
- (zero if hidden).
+ Provides the height of the content.
"""
- if self._current_display:
- height = DEFAULT_CONTENT_HEIGHT + self._graph_height
- else:
- height = 0
+ if not self.displayed_stat:
+ return 0
+
+ height = DEFAULT_CONTENT_HEIGHT + self._graph_height
- if self._current_display == GraphStat.BANDWIDTH and self._accounting_stats:
+ if self.displayed_stat == GraphStat.BANDWIDTH and self._accounting_stats:
height += 3
return height
@@ -518,7 +519,7 @@ class GraphPanel(panel.Panel):
self.resize_graph()
elif key.match('b'):
# uses the next boundary type
- self._bounds = Bounds.next(self._bounds)
+ self.bounds_type = Bounds.next(self.bounds_type)
self.redraw(True)
elif key.match('s'):
# provides a menu to pick the graphed stats
@@ -534,8 +535,8 @@ class GraphPanel(panel.Panel):
words = label.split()
options.append(' '.join(word[0].upper() + word[1:] for word in words))
- if self._current_display:
- initial_selection = available_stats.index(self._current_display) + 1
+ if self.displayed_stat:
+ initial_selection = available_stats.index(self.displayed_stat) + 1
else:
initial_selection = 0
@@ -544,16 +545,16 @@ class GraphPanel(panel.Panel):
# applies new setting
if selection == 0:
- self.set_stats(None)
+ self.displayed_stat = None
elif selection != -1:
- self.set_stats(available_stats[selection - 1])
+ self.displayed_stat = available_stats[selection - 1]
elif key.match('i'):
# provides menu to pick graph panel update interval
- selection = arm.popups.show_menu('Update Interval:', list(Interval), list(Interval).index(self._update_interval))
+ selection = arm.popups.show_menu('Update Interval:', list(Interval), list(Interval).index(self.update_interval))
if selection != -1:
- self._update_interval = list(Interval)[selection]
+ self.update_interval = list(Interval)[selection]
else:
return False
@@ -562,55 +563,55 @@ class GraphPanel(panel.Panel):
def get_help(self):
return [
('r', 'resize graph', None),
- ('s', 'graphed stats', self._current_display if self._current_display else 'none'),
- ('b', 'graph bounds', self._bounds.lower()),
- ('i', 'graph update interval', self._update_interval),
+ ('s', 'graphed stats', self.displayed_stat if self.displayed_stat else 'none'),
+ ('b', 'graph bounds', self.bounds_type.lower()),
+ ('i', 'graph update interval', self.update_interval),
]
def draw(self, width, height):
- if not self._current_display:
+ if not self.displayed_stat:
return
- param = self.get_attr('_stats')[self._current_display]
+ param = self.get_attr('_stats')[self.displayed_stat]
graph_column = min((width - 10) / 2, CONFIG['features.graph.max_width'])
if self.is_title_visible():
- title = CONFIG['attr.graph.title'].get(self._current_display, '')
+ title = CONFIG['attr.graph.title'].get(self.displayed_stat, '')
title_stats = str_tools.join(param.title_stats, ', ', width - len(title) - 4)
title = '%s (%s):' % (title, title_stats) if title_stats else '%s:' % title
self.addstr(0, 0, title, curses.A_STANDOUT)
# top labels
- primary_header = CONFIG['attr.graph.header.primary'].get(self._current_display, '')
+ primary_header = CONFIG['attr.graph.header.primary'].get(self.displayed_stat, '')
primary_header_stats = str_tools.join(param.primary_header_stats, '', (width / 2) - len(primary_header) - 4)
left = '%s (%s):' % (primary_header, primary_header_stats) if primary_header_stats else '%s:' % primary_header
self.addstr(1, 0, left, curses.A_BOLD, PRIMARY_COLOR)
- secondary_header = CONFIG['attr.graph.header.secondary'].get(self._current_display, '')
+ secondary_header = CONFIG['attr.graph.header.secondary'].get(self.displayed_stat, '')
secondary_header_stats = str_tools.join(param.secondary_header_stats, '', (width / 2) - len(secondary_header) - 4)
right = '%s (%s):' % (secondary_header, secondary_header_stats) if secondary_header_stats else '%s:' % secondary_header
self.addstr(1, graph_column + 5, right, curses.A_BOLD, SECONDARY_COLOR)
# determines max/min value on the graph
- if self._bounds == Bounds.GLOBAL_MAX:
- primary_max_bound = param.primary.max_value[self._update_interval]
- secondary_max_bound = param.secondary.max_value[self._update_interval]
+ if self.bounds_type == Bounds.GLOBAL_MAX:
+ primary_max_bound = param.primary.max_value[self.update_interval]
+ secondary_max_bound = param.secondary.max_value[self.update_interval]
else:
# both Bounds.LOCAL_MAX and Bounds.TIGHT use local maxima
if graph_column < 2:
# nothing being displayed
primary_max_bound, secondary_max_bound = 0, 0
else:
- primary_max_bound = max(param.primary.values[self._update_interval][:graph_column])
- secondary_max_bound = max(param.secondary.values[self._update_interval][:graph_column])
+ primary_max_bound = max(param.primary.values[self.update_interval][:graph_column])
+ secondary_max_bound = max(param.secondary.values[self.update_interval][:graph_column])
primary_min_bound = secondary_min_bound = 0
- if self._bounds == Bounds.TIGHT:
- primary_min_bound = min(param.primary.values[self._update_interval][:graph_column])
- secondary_min_bound = min(param.secondary.values[self._update_interval][:graph_column])
+ if self.bounds_type == Bounds.TIGHT:
+ primary_min_bound = min(param.primary.values[self.update_interval][:graph_column])
+ secondary_min_bound = min(param.secondary.values[self.update_interval][:graph_column])
# if the max = min (ie, all values are the same) then use zero lower
# bound so a graph is still displayed
@@ -657,13 +658,13 @@ class GraphPanel(panel.Panel):
# creates bar graph (both primary and secondary)
for col in range(graph_column):
- column_count = int(param.primary.values[self._update_interval][col]) - primary_min_bound
+ column_count = int(param.primary.values[self.update_interval][col]) - primary_min_bound
column_height = int(min(self._graph_height, self._graph_height * column_count / (max(1, primary_max_bound) - primary_min_bound)))
for row in range(column_height):
self.addstr(self._graph_height + 1 - row, col + 5, ' ', curses.A_STANDOUT, PRIMARY_COLOR)
- column_count = int(param.secondary.values[self._update_interval][col]) - secondary_min_bound
+ column_count = int(param.secondary.values[self.update_interval][col]) - secondary_min_bound
column_height = int(min(self._graph_height, self._graph_height * column_count / (max(1, secondary_max_bound) - secondary_min_bound)))
for row in range(column_height):
@@ -671,7 +672,7 @@ class GraphPanel(panel.Panel):
# bottom labeling of x-axis
- interval_sec = INTERVAL_SECONDS[self._update_interval]
+ interval_sec = INTERVAL_SECONDS[self.update_interval]
interval_spacing = 10 if graph_column >= WIDE_LABELING_GRAPH_COL else 5
units_label, decimal_precision = None, 0
@@ -697,7 +698,7 @@ class GraphPanel(panel.Panel):
labeling_line = DEFAULT_CONTENT_HEIGHT + self._graph_height - 2
- if self._current_display == GraphStat.BANDWIDTH and width <= COLLAPSE_WIDTH:
+ if self.displayed_stat == GraphStat.BANDWIDTH and width <= COLLAPSE_WIDTH:
# clears line
self.addstr(labeling_line, 0, ' ' * width)
@@ -714,7 +715,7 @@ class GraphPanel(panel.Panel):
accounting_stats = self.get_attr('_accounting_stats')
- if self._current_display == GraphStat.BANDWIDTH and accounting_stats:
+ if self.displayed_stat == GraphStat.BANDWIDTH and accounting_stats:
if tor_controller().is_alive():
hibernate_color = CONFIG['attr.hibernate_color'].get(accounting_stats.status, 'red')
@@ -731,29 +732,6 @@ class GraphPanel(panel.Panel):
self.addstr(labeling_line + 2, 0, 'Accounting:', curses.A_BOLD)
self.addstr(labeling_line + 2, 12, 'Connection Closed...')
- def get_stats(self):
- """
- Provides the currently selected stats label.
- """
-
- return self._current_display
-
- def set_stats(self, label):
- """
- Sets the currently displayed stats instance, hiding panel if None.
- """
-
- if label != self._current_display:
- if not label:
- self._current_display = None
- elif label in self._stats.keys():
- self._current_display = label
- else:
- raise ValueError('Unrecognized stats label: %s' % label)
-
- def get_all_stats(self):
- return self._stats
-
def copy_attr(self, attr):
if attr == '_stats':
return dict([(key, type(self._stats[key])(self._stats[key])) for key in self._stats])
diff --git a/arm/menu/actions.py b/arm/menu/actions.py
index 5608d6b..8b1e4f2 100644
--- a/arm/menu/actions.py
+++ b/arm/menu/actions.py
@@ -149,8 +149,8 @@ def make_graph_menu(graph_panel):
# stats options
- stat_group = arm.menu.item.SelectionGroup(graph_panel.set_stats, graph_panel.get_stats())
- available_stats = graph_panel.get_all_stats().keys()
+ stat_group = arm.menu.item.SelectionGroup(functools.partial(setattr, graph_panel, 'displayed_stat'), graph_panel.displayed_stat)
+ available_stats = graph_panel.stat_options()
available_stats.sort()
for stat_key in ["None"] + available_stats:
@@ -165,7 +165,7 @@ def make_graph_menu(graph_panel):
# interval submenu
interval_menu = arm.menu.item.Submenu("Interval")
- interval_group = arm.menu.item.SelectionGroup(graph_panel.set_update_interval, graph_panel.get_update_interval())
+ interval_group = arm.menu.item.SelectionGroup(functools.partial(setattr, graph_panel, 'update_interval'), graph_panel.update_interval)
for interval in arm.graph_panel.Interval:
interval_menu.add(arm.menu.item.SelectionMenuItem(interval, interval_group, interval))
@@ -175,7 +175,7 @@ def make_graph_menu(graph_panel):
# bounds submenu
bounds_menu = arm.menu.item.Submenu("Bounds")
- bounds_group = arm.menu.item.SelectionGroup(graph_panel.set_bounds_type, graph_panel.get_bounds_type())
+ bounds_group = arm.menu.item.SelectionGroup(functools.partial(setattr, graph_panel, 'bounds_type'), graph_panel.bounds_type)
for bounds_type in arm.graph_panel.Bounds:
bounds_menu.add(arm.menu.item.SelectionMenuItem(bounds_type, bounds_group, bounds_type))
diff --git a/arm/util/panel.py b/arm/util/panel.py
index fb6ae0e..9320270 100644
--- a/arm/util/panel.py
+++ b/arm/util/panel.py
@@ -53,7 +53,7 @@ for color_label in ui_tools.COLOR_LIST:
HALT_ACTIVITY = False
-class Panel():
+class Panel(object):
"""
Wrapper for curses subwindows. This hides most of the ugliness in common
curses operations including:
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits