[tor-commits] [nyx/master] Rewrite port count dialog

atagar at torproject.org atagar at torproject.org
Thu Jul 2 16:58:41 UTC 2015


commit 35206a3a09979f6321aa8e9ce97728b4b1ccf92c
Author: Damian Johnson <atagar at torproject.org>
Date:   Thu Jul 2 09:57:13 2015 -0700

    Rewrite port count dialog
    
    Revising the dialog that shows aggregated counts for entry or exit connections
    (locales if a guard, or port usage if an exit). This is a pretty small popup
    and code got even smaller with the cleanup, so moving it into popups.py.
---
 nyx/connections/__init__.py    |    1 -
 nyx/connections/conn_panel.py  |   19 +++++--
 nyx/connections/count_popup.py |  107 ----------------------------------------
 nyx/popups.py                  |   51 +++++++++++++++++++
 4 files changed, 67 insertions(+), 111 deletions(-)

diff --git a/nyx/connections/__init__.py b/nyx/connections/__init__.py
index 447adf6..c7e90a9 100644
--- a/nyx/connections/__init__.py
+++ b/nyx/connections/__init__.py
@@ -6,7 +6,6 @@ __all__ = [
   'circ_entry',
   'conn_entry',
   'conn_panel',
-  'count_popup',
   'descriptor_popup',
   'entries',
 ]
diff --git a/nyx/connections/conn_panel.py b/nyx/connections/conn_panel.py
index c555a38..0a27721 100644
--- a/nyx/connections/conn_panel.py
+++ b/nyx/connections/conn_panel.py
@@ -10,7 +10,7 @@ import threading
 import nyx.popups
 import nyx.util.tracker
 
-from nyx.connections import count_popup, descriptor_popup, entries, conn_entry, circ_entry
+from nyx.connections import descriptor_popup, entries, conn_entry, circ_entry
 from nyx.util import panel, tor_controller, tracker, ui_tools
 
 from stem.control import State
@@ -24,6 +24,8 @@ DETAILS_HEIGHT = 7
 
 Listing = enum.Enum(('IP_ADDRESS', 'IP Address'), 'HOSTNAME', 'FINGERPRINT', 'NICKNAME')
 
+EXIT_USAGE_WIDTH = 15
+
 
 def conf_handler(key, value):
   if key == 'features.connection.listing_type':
@@ -335,9 +337,20 @@ class ConnectionPanel(panel.Panel, threading.Thread):
         self.set_title_visible(True)
         self.redraw(True)
       elif key.match('c') and self.is_clients_allowed():
-        count_popup.showCountDialog(count_popup.CountType.CLIENT_LOCALE, self._client_locale_usage)
+        nyx.popups.show_count_dialog('Client Locales', self._client_locale_usage)
       elif key.match('e') and self.is_exits_allowed():
-        count_popup.showCountDialog(count_popup.CountType.EXIT_PORT, self._exit_port_usage)
+        counts = {}
+        key_width = max(map(len, self._exit_port_usage.keys()))
+
+        for k, v in self._exit_port_usage.items():
+          usage = connection.port_usage(k)
+
+          if usage:
+            k = k.ljust(key_width + 3) + usage.ljust(EXIT_USAGE_WIDTH)
+
+          counts[k] = v
+
+        nyx.popups.show_count_dialog('Exiting Port Usage', counts)
       else:
         return False
 
diff --git a/nyx/connections/count_popup.py b/nyx/connections/count_popup.py
deleted file mode 100644
index e61dc26..0000000
--- a/nyx/connections/count_popup.py
+++ /dev/null
@@ -1,107 +0,0 @@
-"""
-Provides a dialog with client locale or exiting port counts.
-"""
-
-import curses
-import operator
-
-import nyx.controller
-import nyx.popups
-
-from stem.util import connection, enum, log
-
-CountType = enum.Enum('CLIENT_LOCALE', 'EXIT_PORT')
-EXIT_USAGE_WIDTH = 15
-
-
-def showCountDialog(count_type, counts):
-  """
-  Provides a dialog with bar graphs and percentages for the given set of
-  counts. Pressing any key closes the dialog.
-
-  Arguments:
-    count_type - type of counts being presented
-    counts    - mapping of labels to counts
-  """
-
-  is_no_stats = not counts
-  no_stats_msg = "Usage stats aren't available yet, press any key..."
-
-  if is_no_stats:
-    height, width = 3, len(no_stats_msg) + 4
-  else:
-    height, width = 4 + max(1, len(counts)), 80
-
-  with nyx.popups.popup_window(height, width) as (popup, height, width):
-    if popup:
-      control = nyx.controller.get_controller()
-
-      popup.win.box()
-
-      # dialog title
-
-      if count_type == CountType.CLIENT_LOCALE:
-        title = 'Client Locales'
-      elif count_type == CountType.EXIT_PORT:
-        title = 'Exiting Port Usage'
-      else:
-        title = ''
-        log.warn('Unrecognized count type: %s' % count_type)
-
-      popup.addstr(0, 0, title, curses.A_STANDOUT)
-
-      if is_no_stats:
-        popup.addstr(1, 2, no_stats_msg, curses.A_BOLD, 'cyan')
-      else:
-        sorted_counts = sorted(counts.iteritems(), key=operator.itemgetter(1))
-        sorted_counts.reverse()
-
-        # constructs string formatting for the max key and value display width
-
-        key_width, val_width, value_total = 3, 1, 0
-
-        for k, v in sorted_counts:
-          key_width = max(key_width, len(k))
-          val_width = max(val_width, len(str(v)))
-          value_total += v
-
-        # extra space since we're adding usage informaion
-
-        if count_type == CountType.EXIT_PORT:
-          key_width += EXIT_USAGE_WIDTH
-
-        label_format = '%%-%is %%%ii (%%%%%%-2i)' % (key_width, val_width)
-
-        for i in range(height - 4):
-          k, v = sorted_counts[i]
-
-          # includes a port usage column
-
-          if count_type == CountType.EXIT_PORT:
-            usage = connection.port_usage(k)
-
-            if usage:
-              key_format = '%%-%is   %%s' % (key_width - EXIT_USAGE_WIDTH)
-              k = key_format % (k, usage[:EXIT_USAGE_WIDTH - 3])
-
-          label = label_format % (k, v, v * 100 / value_total)
-          popup.addstr(i + 1, 2, label, curses.A_BOLD, 'green')
-
-          # All labels have the same size since they're based on the max widths.
-          # If this changes then this'll need to be the max label width.
-
-          label_width = len(label)
-
-          # draws simple bar graph for percentages
-
-          fill_width = v * (width - 4 - label_width) / value_total
-
-          for j in range(fill_width):
-            popup.addstr(i + 1, 3 + label_width + j, ' ', curses.A_STANDOUT, 'red')
-
-        popup.addstr(height - 2, 2, 'Press any key...')
-
-      popup.win.refresh()
-
-      curses.cbreak()
-      control.key_input()
diff --git a/nyx/popups.py b/nyx/popups.py
index 38eade0..351467f 100644
--- a/nyx/popups.py
+++ b/nyx/popups.py
@@ -3,12 +3,15 @@ Functions for displaying popups in the interface.
 """
 
 import curses
+import operator
 
 import nyx.controller
 
 from nyx import __version__, __release_date__
 from nyx.util import panel, ui_tools
 
+NO_STATS_MSG = "Usage stats aren't available yet, press any key..."
+
 
 def popup_window(height = -1, width = -1, top = 0, left = 0, below_static = True):
   """
@@ -199,6 +202,54 @@ def show_about_popup():
       control.key_input()
 
 
+def show_count_dialog(title, counts):
+  """
+  Provides a dialog with bar graphs and percentages for the given set of
+  counts. Pressing any key closes the dialog.
+
+  :param str title: dialog title
+  :param dict counts: mapping of labels to their value
+  """
+
+  if not counts:
+    height, width = 3, len(NO_STATS_MSG) + 4
+  else:
+    height, width = 4 + max(1, len(counts)), 80
+
+  with nyx.popups.popup_window(height, width) as (popup, width, height):
+    if not popup:
+      return
+
+    if not counts:
+      popup.addstr(1, 2, NO_STATS_MSG, curses.A_BOLD, 'cyan')
+    else:
+      key_width, val_width, value_total = 3, 1, 0
+
+      for k, v in counts.items():
+        key_width = max(key_width, len(k))
+        val_width = max(val_width, len(str(v)))
+        value_total += v
+
+      sorted_counts = sorted(counts.iteritems(), key = operator.itemgetter(1), reverse = True)
+      graph_width = width - key_width - val_width - 11  # border, extra spaces, and percentage column
+
+      for y, (k, v) in enumerate(sorted_counts):
+        label = '%s %s (%-2i%%)' % (k.ljust(key_width), str(v).rjust(val_width), v * 100 / value_total)
+        x = popup.addstr(y + 1, 2, label, curses.A_BOLD, 'green')
+
+        for j in range(graph_width * v / value_total):
+          popup.addstr(y + 1, x + j + 1, ' ', curses.A_STANDOUT, 'red')
+
+      popup.addstr(height - 2, 2, 'Press any key...')
+
+    popup.win.box()
+    popup.addstr(0, 0, title, curses.A_STANDOUT)
+    popup.win.refresh()
+
+    curses.cbreak()
+    nyx.controller.get_controller().key_input()
+
+
 def show_sort_dialog(title, options, old_selection, option_colors):
   """
   Displays a sorting dialog of the form:



More information about the tor-commits mailing list