commit 9fec021715ebd054086cffb707c70968f47e039a
Author: Damian Johnson <atagar(a)torproject.org>
Date: Sat Jun 25 17:30:58 2016 -0700
Drop DrawAttributes attribute container
This made some sense when we needed to pass a bundle of attributes among
helpers, but it's now just clutter. Testability is simple without it.
---
nyx/panel/graph.py | 61 ++++++++++++++++++++++++-----------------------------
test/panel/graph.py | 22 ++-----------------
2 files changed, 29 insertions(+), 54 deletions(-)
diff --git a/nyx/panel/graph.py b/nyx/panel/graph.py
index e35e972..1043339 100644
--- a/nyx/panel/graph.py
+++ b/nyx/panel/graph.py
@@ -14,7 +14,6 @@ Downloaded (0.0 B/sec): Uploaded (0.0 B/sec):
25s 50 1m 1.6 2.0 25s 50 1m 1.6 2.0
"""
-import collections
import copy
import time
@@ -33,8 +32,6 @@ GraphStat = enum.Enum(('BANDWIDTH', 'bandwidth'), ('CONNECTIONS', 'connections')
Interval = enum.Enum(('EACH_SECOND', 'each second'), ('FIVE_SECONDS', '5 seconds'), ('THIRTY_SECONDS', '30 seconds'), ('MINUTELY', 'minutely'), ('FIFTEEN_MINUTE', '15 minute'), ('THIRTY_MINUTE', '30 minute'), ('HOURLY', 'hourly'), ('DAILY', 'daily'))
Bounds = enum.Enum(('GLOBAL_MAX', 'global_max'), ('LOCAL_MAX', 'local_max'), ('TIGHT', 'tight'))
-DrawAttributes = collections.namedtuple('DrawAttributes', ('stat', 'subgraph_height', 'subgraph_width', 'interval', 'bounds_type'))
-
INTERVAL_SECONDS = {
Interval.EACH_SECOND: 1,
Interval.FIVE_SECONDS: 5,
@@ -572,21 +569,18 @@ class GraphPanel(nyx.panel.Panel):
stat = self._stats_paused[self.displayed_stat]
accounting_stats = self._accounting_stats_paused
- attr = DrawAttributes(
- stat = type(stat)(stat), # clone the GraphCategory
- subgraph_height = self._graph_height + 2, # graph rows + header + x-axis label
- subgraph_width = min(subwindow.width / 2, CONFIG['features.graph.max_width']),
- interval = self.update_interval,
- bounds_type = self.bounds_type,
- )
+ stat = type(stat)(stat) # clone the GraphCategory
+ subgraph_height = self._graph_height + 2 # graph rows + header + x-axis label
+ subgraph_width = min(subwindow.width / 2, CONFIG['features.graph.max_width'])
+ interval, bounds_type = self.update_interval, self.bounds_type
- subwindow.addstr(0, 0, attr.stat.title(subwindow.width), HIGHLIGHT)
+ subwindow.addstr(0, 0, stat.title(subwindow.width), HIGHLIGHT)
- _draw_subgraph(subwindow, attr, attr.stat.primary, 0, PRIMARY_COLOR)
- _draw_subgraph(subwindow, attr, attr.stat.secondary, attr.subgraph_width, SECONDARY_COLOR)
+ _draw_subgraph(subwindow, stat.primary, 0, subgraph_width, subgraph_height, bounds_type, interval, PRIMARY_COLOR)
+ _draw_subgraph(subwindow, stat.secondary, subgraph_width, subgraph_width, subgraph_height, bounds_type, interval, SECONDARY_COLOR)
- if attr.stat.stat_type() == GraphStat.BANDWIDTH and accounting_stats:
- _draw_accounting_stats(subwindow, DEFAULT_CONTENT_HEIGHT + attr.subgraph_height - 2, accounting_stats)
+ if stat.stat_type() == GraphStat.BANDWIDTH and accounting_stats:
+ _draw_accounting_stats(subwindow, DEFAULT_CONTENT_HEIGHT + subgraph_height - 2, accounting_stats)
def _update_accounting(self, event):
if not CONFIG['features.graph.bw.accounting.show']:
@@ -614,37 +608,36 @@ class GraphPanel(nyx.panel.Panel):
self.redraw(True)
-def _draw_subgraph(subwindow, attr, data, x, color, fill_char = ' '):
- # Concering our subgraph colums, the y-axis label can be at most six
- # characters, with two spaces of padding on either side of the graph.
- # Starting with the smallest size, then possibly raise it after determing
- # the y_axis_labels.
+def _draw_subgraph(subwindow, data, x, width, height, bounds_type, interval, color, fill_char = ' '):
+ """
+ Renders subgraph including its title, labeled axis, and content.
+ """
- subgraph_columns = attr.subgraph_width - 8
- min_bound, max_bound = data.bounds(attr.bounds_type, attr.interval, subgraph_columns)
+ columns = width - 8 # y-axis labels can be at most six characters wide with a space on either side
+ min_bound, max_bound = data.bounds(bounds_type, interval, columns)
- x_axis_labels = _x_axis_labels(attr.interval, subgraph_columns)
- y_axis_labels = _y_axis_labels(attr.subgraph_height, data, min_bound, max_bound)
- subgraph_columns = max(subgraph_columns, attr.subgraph_width - max([len(label) for label in y_axis_labels.values()]) - 2)
+ x_axis_labels = _x_axis_labels(interval, columns)
+ y_axis_labels = _y_axis_labels(height, data, min_bound, max_bound)
+ columns = max(columns, width - max([len(label) for label in y_axis_labels.values()]) - 2)
axis_offset = max([len(label) for label in y_axis_labels.values()])
- subwindow.addstr(x, 1, data.header(attr.subgraph_width), color, BOLD)
+ subwindow.addstr(x, 1, data.header(width), color, BOLD)
for x_offset, label in x_axis_labels.items():
- subwindow.addstr(x + x_offset + axis_offset, attr.subgraph_height, label, color)
+ subwindow.addstr(x + x_offset + axis_offset, height, label, color)
for y, label in y_axis_labels.items():
subwindow.addstr(x, y, label, color)
- for col in range(subgraph_columns):
- column_count = int(data.values[attr.interval][col]) - min_bound
- column_height = int(min(attr.subgraph_height - 2, (attr.subgraph_height - 2) * column_count / (max(1, max_bound) - min_bound)))
+ for col in range(columns):
+ column_count = int(data.values[interval][col]) - min_bound
+ column_height = int(min(height - 2, (height - 2) * column_count / (max(1, max_bound) - min_bound)))
for row in range(column_height):
- subwindow.addstr(x + col + axis_offset + 1, attr.subgraph_height - 1 - row, fill_char, color, HIGHLIGHT)
+ subwindow.addstr(x + col + axis_offset + 1, height - 1 - row, fill_char, color, HIGHLIGHT)
-def _x_axis_labels(interval, subgraph_columns):
+def _x_axis_labels(interval, columns):
"""
Provides the labels for the x-axis. We include the units for only its first
value, then bump the precision for subsequent units. For example...
@@ -655,10 +648,10 @@ def _x_axis_labels(interval, subgraph_columns):
x_axis_labels = {}
interval_sec = INTERVAL_SECONDS[interval]
- interval_spacing = 10 if subgraph_columns >= WIDE_LABELING_GRAPH_COL else 5
+ interval_spacing = 10 if columns >= WIDE_LABELING_GRAPH_COL else 5
previous_units, decimal_precision = None, 0
- for i in range((subgraph_columns - 4) / interval_spacing):
+ for i in range((columns - 4) / interval_spacing):
x = (i + 1) * interval_spacing
time_label = str_tools.time_label(x * interval_sec, decimal_precision)
diff --git a/test/panel/graph.py b/test/panel/graph.py
index 5327cba..6df72c5 100644
--- a/test/panel/graph.py
+++ b/test/panel/graph.py
@@ -95,36 +95,18 @@ class TestGraph(unittest.TestCase):
@patch('nyx.panel.graph.tor_controller')
def test_draw_subgraph_blank(self, tor_controller_mock):
tor_controller_mock().get_info.return_value = None
-
- attr = nyx.panel.graph.DrawAttributes(
- stat = None,
- subgraph_height = 7,
- subgraph_width = 30,
- interval = nyx.panel.graph.Interval.EACH_SECOND,
- bounds_type = nyx.panel.graph.Bounds.LOCAL_MAX,
- )
-
data = nyx.panel.graph.BandwidthStats()
- rendered = test.render(nyx.panel.graph._draw_subgraph, attr, data.primary, 0, nyx.curses.Color.CYAN, '*')
+ rendered = test.render(nyx.panel.graph._draw_subgraph, data.primary, 0, 30, 7, nyx.panel.graph.Bounds.LOCAL_MAX, nyx.panel.graph.Interval.EACH_SECOND, nyx.curses.Color.CYAN, '*')
self.assertEqual(EXPECTED_BLANK_GRAPH, rendered.content)
@require_curses
@patch('nyx.panel.graph.tor_controller')
def test_draw_subgraph(self, tor_controller_mock):
tor_controller_mock().get_info.return_value = '543,543 421,421 551,551 710,710 200,200 175,175 188,188 250,250 377,377'
-
- attr = nyx.panel.graph.DrawAttributes(
- stat = None,
- subgraph_height = 7,
- subgraph_width = 30,
- interval = nyx.panel.graph.Interval.EACH_SECOND,
- bounds_type = nyx.panel.graph.Bounds.LOCAL_MAX,
- )
-
data = nyx.panel.graph.BandwidthStats()
- rendered = test.render(nyx.panel.graph._draw_subgraph, attr, data.primary, 0, nyx.curses.Color.CYAN, '*')
+ rendered = test.render(nyx.panel.graph._draw_subgraph, data.primary, 0, 30, 7, nyx.panel.graph.Bounds.LOCAL_MAX, nyx.panel.graph.Interval.EACH_SECOND, nyx.curses.Color.CYAN, '*')
self.assertEqual(EXPECTED_GRAPH, rendered.content)
@require_curses