[tor-commits] [compass/master] Rebuilt the Option class to be a little more usable from the web front-end

karsten at torproject.org karsten at torproject.org
Mon Jan 7 07:09:40 UTC 2013


commit e1b2e15dc56f6c3d0d6d032a893159e88e9a2d4f
Author: Chris Wacek <cwacek at cs.georgetown.edu>
Date:   Wed Dec 12 23:12:06 2012 -0500

    Rebuilt the Option class to be a little more usable from the web front-end
---
 app.py     |   71 +++++++++++++++++++++++++++++------------------------------
 compass.py |   58 ++++++++++++++++++++++++++++++++++++++-----------
 util.py    |   59 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 139 insertions(+), 49 deletions(-)

diff --git a/app.py b/app.py
index 3a66a79..67f4608 100644
--- a/app.py
+++ b/app.py
@@ -1,46 +1,45 @@
 import os
 import re
 import compass
-from flask import Flask, request, redirect, render_template, url_for
+from util import Result,Boolean,NullFn,Int,Container
+from flask import Flask, request, jsonify, render_template
 
 app = Flask(__name__)
 
 class Opt(object):
-    def __init__(self):
-        self.by_as = False
-        self.family = None
-        self.by_country = False
-        self.ases = None
-        self.country = None
-        self.top = -1
-        self.short = None 
-        self.links = None 
-        self.guards_only = None
-        self.inactive = False 
-        self.almost_fast_exits_only = None 
-        self.exits_only = False
-        self.download = None 
-        self.fast_exits_only = False
-        self.fast_exits_only_any_network = False
-        self.all_relays = False
+    request_types = {
+      'by_as':Boolean,
+      'by_country':Boolean,
+      'inactive':Boolean,
+      'exits_only':Boolean,
+      'guards_only': Boolean,
+      'links':Boolean,
+      'sort':NullFn,
+      'sort_reverse':Boolean,
+      'top':Int,
+      'family':NullFn,
+      'ases':NullFn,
+      'country':Container,
+      'exit_filter':NullFn
+    }
 
-class Result():
-    def __init__(self):
-        self.index = None
-        self.cw = None
-        self.adv_bw = None
-        self.p_guard = None
-        self.p_exit = None
-        self.p_middle = None
-        self.nick = None
-        self.fp = None
-        self.link = None
-        self.exit = None
-        self.guard = None
-        self.cc = None
-        self.as_no = None
-        self.as_name = None
-        self.as_info = None
+    @staticmethod
+    def convert(key,val):
+      return Opt.request_types[key](val)
+
+    def __str__(self):
+      return repr(self)
+
+    def __repr__(self):
+      return str(self.__dict__)
+
+    def __init__(self,request):
+
+      for key in Opt.request_types:
+        if key in request:
+          setattr(self,key,Opt.convert(key,request[key]))
+        else:
+          setattr(self,key,Opt.convert(key,None))
 
 def parse(output_string, grouping=False, sort_key=None):
     results = []
diff --git a/compass.py b/compass.py
index a62eb98..520a017 100755
--- a/compass.py
+++ b/compass.py
@@ -18,6 +18,7 @@ ALMOST_FAST_EXIT_PORTS = [80, 443]
 import json
 import operator
 import sys
+import util
 import os
 from optparse import OptionParser, OptionGroup
 import urllib
@@ -221,15 +222,16 @@ class RelayStats(object):
             filters.append(ExitFilter())
         if options.guards_only:
             filters.append(GuardFilter())
-        if options.fast_exits_only:
+        if options.exit_filter == 'all_relays':
+            pass
+        elif options.exit_filter == 'fast_exits_only':
             filters.append(SameNetworkFilter(FastExitFilter()))
-        if options.almost_fast_exits_only:
-	    filters.append(
-                FastExitFilter(ALMOST_FAST_EXIT_BANDWIDTH_RATE, ALMOST_FAST_EXIT_ADVERTISED_BANDWIDTH,
-                               ALMOST_FAST_EXIT_PORTS))
-            filters.append(
-                InverseFilter(SameNetworkFilter(FastExitFilter())))
-        if options.fast_exits_only_any_network:
+        elif options.exit_filter == 'almost_fast_exits_only':
+            filters.append(FastExitFilter(ALMOST_FAST_EXIT_BANDWIDTH_RATE,
+                                          ALMOST_FAST_EXIT_ADVERTISED_BANDWIDTH,
+                                          ALMOST_FAST_EXIT_PORTS))
+            filters.append(InverseFilter(SameNetworkFilter(FastExitFilter())))
+        elif options.exit_filter == 'fast_exits_only_any_network':
             filters.append(FastExitFilter())
         return filters
 
@@ -364,6 +366,9 @@ def create_option_parser():
                      help="select family by fingerprint or nickname (for named relays)")
     group.add_option("-g", "--guards-only", action="store_true",
                      help="select only relays suitable for guard position")
+    group.add_option("--exit-filter",type="choice", dest="exit_filter",
+                     choices=["fast_exits_only","almost_fast_exits_only",
+                              "all_relays","fast_exits_only_any_network"])
     group.add_option("--fast-exits-only", action="store_true",
                      help="select only fast exits (%d+ Mbit/s, %d+ KB/s, %s, %d- per /24)" %
                           (FAST_EXIT_BANDWIDTH_RATE / (125 * 1024),
@@ -404,6 +409,32 @@ def download_details_file():
     url.close()
     details_file.close()
 
+def fix_exit_filter_options(options):
+  """
+  Translate the old-style exit filter options into
+  the new format (as received on the front end).
+  """
+  if options.exit_filter != "all_relays":
+    # We just accept this option's value
+    return options
+
+  fast_exit_options = 0
+  if options.fast_exits_only:
+    options.exit_filter = "fast_exits_only"
+    fast_exit_options += 1
+  if options.almost_fast_exits_only:
+    options.exit_filter = "almost_fast_exits_only"
+    fast_exit_options += 1
+  if options.fast_exits_only_any_network:
+    options.exit_filter = "fast_exits_only_any_network"
+    fast_exit_options += 1
+
+  if fast_exit_options > 1:
+    raise Exception
+
+  return options
+
+
 if '__main__' == __name__:
     parser = create_option_parser()
     (options, args) = parser.parse_args()
@@ -411,12 +442,12 @@ if '__main__' == __name__:
         parser.error("Did not understand positional argument(s), use options instead.")
     if options.family and not re.match(r'^[A-F0-9]{40}$', options.family) and not re.match(r'^[A-Za-z0-9]{1,19}$', options.family):
         parser.error("Not a valid fingerprint or nickname: %s" % options.family)
-    fast_exit_options = 0
-    if options.fast_exits_only: fast_exit_options += 1
-    if options.almost_fast_exits_only: fast_exit_options += 1
-    if options.fast_exits_only_any_network: fast_exit_options += 1
-    if fast_exit_options > 1:
+
+    try:
+      fix_exit_filter_options(options)
+    except:
         parser.error("Can only filter by one fast-exit option.")
+
     if options.download:
         download_details_file()
         print "Downloaded details.json.  Re-run without --download option."
@@ -430,6 +461,7 @@ if '__main__' == __name__:
                     by_country=options.by_country,
                     by_as_number=options.by_as,
                     links=options.links)
+
     output_string = stats.print_groups(sorted_groups, options.top,
                        by_country=options.by_country,
                        by_as_number=options.by_as,
diff --git a/util.py b/util.py
new file mode 100644
index 0000000..d5d041e
--- /dev/null
+++ b/util.py
@@ -0,0 +1,59 @@
+import json
+
+def Container(val):
+  return json.loads(val)
+
+def NullFn(val):
+  return val
+
+def Int(val):
+  try:
+    return int(val)
+  except:
+    return None
+
+def Boolean(val):
+  if val == True:
+    return True
+
+  if val in ("false", "False", "FALSE", "F"):
+    return False
+  if val in ("true", "True", "TRUE", "T"):
+    return True
+
+  return False
+
+class Result():
+    WEIGHT_FIELDS = {
+    'consensus_weight_fraction': 'cw', 
+    'advertised_bandwidth_fraction': 'adv_bw',
+    'guard_probability': 'p_guard',
+    'middle_probability': 'p_middle',
+    'exit_probability': 'p_exit',
+    }
+
+    def __init__(self):
+        self.index = None
+        self.cw = None
+        self.adv_bw = None
+        self.p_guard = None
+        self.p_exit = None
+        self.p_middle = None
+        self.nick = None
+        self.fp = None
+        self.link = None
+        self.exit = None
+        self.guard = None
+        self.cc = None
+        self.as_no = None
+        self.as_name = None
+        self.as_info = None
+
+    def __getitem__(self,prop):
+      getattr(self,prop)
+
+    def __setitem__(self,prop,val):
+      setattr(self,prop,val)
+
+    def jsonify(self):
+      return self.__dict__





More information about the tor-commits mailing list