[tor-commits] [stem/master] Add Controller.reset_conf and fix Controller.set_conf

atagar at torproject.org atagar at torproject.org
Sun Jul 8 20:14:44 UTC 2012


commit ea57e936e08400d63a423c669311643afd4dd84d
Author: Ravi Chandra Padmala <neenaoffline at gmail.com>
Date:   Tue Jun 26 10:04:52 2012 +0530

    Add Controller.reset_conf and fix Controller.set_conf
---
 stem/control.py                  |   96 +++++++++++++++++++++++++++++---------
 test/integ/control/controller.py |   65 ++++++++++++++++++++++----
 2 files changed, 128 insertions(+), 33 deletions(-)

diff --git a/stem/control.py b/stem/control.py
index 0e0d611..dfa79c7 100644
--- a/stem/control.py
+++ b/stem/control.py
@@ -14,6 +14,10 @@ interacting at a higher level.
   
   Controller - General controller class intended for direct use.
     |- get_info - issues a GETINFO query
+    |- get_conf - issues a GETCONF query for a single parameter
+    |- get_conf_mapping - issues a GETCONF query for multiple parameters
+    |- set_conf - issues a SETCONF query
+    |- reset_conf - issues a RESETCONF query
     |- get_version - convenience method to get tor version
     |- authenticate - convenience method to authenticate the controller
     +- protocolinfo - convenience method to get the protocol info
@@ -560,7 +564,7 @@ class Controller(BaseController):
       Response depends upon how we were called as follows...
       
       * str with the response if multiple was False
-      * list with the response strings multiple was True
+      * list with the response strings if multiple was True
       * default if one was provided and our call failed
     
     :raises:
@@ -662,13 +666,40 @@ class Controller(BaseController):
       if default != UNDEFINED: return default
       else: raise exc
   
-  def set_conf(self, *args):
+  def _set_conf(self, params, command="SETCONF"):
+    controlitems = [command]
+    
+    for key, value in params:
+      if type(value) in (list, tuple):
+        controlitems.extend(["%s=\"%s\"" % (key, val.strip()) for val in value])
+      elif value:
+        controlitems.append("%s=\"%s\"" % (key, value.strip()))
+      else:
+        controlitems.append(key)
+    
+    response = self.msg(" ".join(controlitems))
+    stem.response.convert("SINGLELINE", response)
+    
+    if response.is_ok():
+      return True
+    elif response.code == "552":
+      if response.message.startswith("Unrecognized option: Unknown option '"):
+        key = response.message[37:response.message.find("\'", 37)]
+        raise stem.socket.InvalidArguments(response.code, response.message, [key])
+      raise stem.socket.InvalidRequest(response.code, response.message)
+    elif response.code in ("513", "553"):
+      raise stem.socket.InvalidRequest(response.code, response.message)
+    else:
+      raise stem.socket.ProtocolError("%s returned unexpected status code" % command)
+  
+  def set_conf(self, *params):
     """
     Changes the configuration of one or more configuration variables using the
     control socket.
     
-    :param dict options: a dictionary containing a mapping of configuration keys (string)
-      to the corresponding values (string or list of strings)
+    :param list,dict params: a list containing tuples of configuration keys (string)
+      and their corresponding values (string or list of strings) or a dict
+      containing config-key: config-value pairs.
     
     Or
     
@@ -684,31 +715,50 @@ class Controller(BaseController):
         impossible or if there's a syntax error in the configuration values
     """
     
-    if len(args) == 2:
-      args = {args[0]: args[1]}
-    elif len(args) == 1:
-      args = args[0]
+    if len(params) == 2:
+      arg = [params]
+    elif len(params) == 1:
+      if type(params[0]) == dict:
+        arg = params[0].items()
+      else:
+        arg = params[0]
     else:
       raise TypeError("set_conf expected 1 or 2 arguments, got %d", len(args))
     
-    options = []
-    for key, value in args.iteritems():
-      options.append(key + "=\"" + value + "\"")
+    self._set_conf(arg, "SETCONF")
+  
+  def reset_conf(self, params):
+    """
+    Resets the configuration of one or more configuration variables using the
+    control socket.
+    
+    :param str,list,dict params:
+      This could be...
       
-    response = self.msg("SETCONF %s" % " ".join(options))
-    stem.response.convert("SINGLELINE", response)
+      * a single configuration key (str)
+      * a list of configuration keys to be reset and/or tuples of configuration
+        keys (string) and their corresponding values (string or list of strings)
+      * a dict containing configuration key/value pairs.
     
-    if response.is_ok():
-      return True
-    elif response.code == "552":
-      if response.message.startswith("Unrecognized option: Unknown option '"):
-        key = response.message[37:response.message.find("\'", 37)]
-        raise stem.socket.InvalidArguments(response.code, response.message, [key])
-      raise stem.socket.InvalidRequest(response.code, response.message)
-    elif response.code in ("513", "553"):
-      raise stem.socket.InvalidRequest(response.code, response.message)
+    :param list params: a list of configuration keys to be reset
+    
+    :returns: True on successfully resetting the values
+    
+    :raises:
+      :class:`stem.socket.ControllerError` if the call fails
+      :class:`stem.socket.InvalidArguments` if configuration options requested was invalid
+      :class:`stem.socket.InvalidRequest` if the configuration setting is
+        impossible or if there's a syntax error in the configuration values
+    """
+    
+    if type(params) == str:
+      arg = [(params, None)]
+    elif type(params) == dict:
+      arg = params.items()
     else:
-      raise stem.socket.ProtocolError("SETCONF returned unexpected status code")
+      arg = map(lambda item: (item, None) if type(item) == str else item, params)
+    
+    self._set_conf(arg, "RESETCONF")
 
 def _case_insensitive_lookup(entries, key):
   """
diff --git a/test/integ/control/controller.py b/test/integ/control/controller.py
index 4a517dd..a407904 100644
--- a/test/integ/control/controller.py
+++ b/test/integ/control/controller.py
@@ -193,18 +193,17 @@ class TestController(unittest.TestCase):
       self.assertEqual({}, controller.get_conf_map([], "la-di-dah"))
       
       # context-sensitive keys
-      
-      keys = {
-          "HiddenServiceDir": "/tmp/stemtestdir",
-          "HiddenServicePort": "17234 127.0.0.1:17235"
-          }
+      keys = [
+          ("HiddenServiceDir", "/tmp/stemtestdir"),
+          ("HiddenServicePort", "17234 127.0.0.1:17235")
+          ]
       controller.set_conf(keys)
       self.assertEqual("/tmp/stemtestdir", controller.get_conf("HiddenServiceDir"))
-      self.assertEqual("17234 127.0.0.1:17235", controller.get_conf("HiddenServiceDir"))
+      self.assertEqual("17234 127.0.0.1:17235", controller.get_conf("HiddenServicePort"))
   
   def test_setconf(self):
     """
-    Exercises SETCONF with valid and invalid requests.
+    Exercises Controller.set_conf with valid and invalid requests.
     """
     
     runner = test.runner.get_runner()
@@ -233,11 +232,57 @@ class TestController(unittest.TestCase):
       except stem.socket.InvalidArguments, exc:
         self.assertEqual(["bombay"], exc.arguments)
       
+      settings = [
+          ("HiddenServiceDir", "/tmp/stemtestdir"),
+          ("HiddenServicePort", "17234 127.0.0.1:17235")
+          ]
+      controller.set_conf(settings)
+      self.assertEqual("17234 127.0.0.1:17235", controller.get_conf("hiddenserviceport"))
+      self.assertEqual("/tmp/stemtestdir", controller.get_conf("hiddenservicedir"))
+  
+  def test_resetconf(self):
+    """
+    Exercises Controller.reset_conf with valid and invalid requests.
+    """
+    
+    runner = test.runner.get_runner()
+    
+    with runner.get_tor_controller() as controller:
+      # Single valid key
+      controller.set_conf("contactinfo", "stem at testing")
+      self.assertEqual("stem at testing", controller.get_conf("contactinfo"))
+      controller.reset_conf("contactinfo")
+      self.assertEqual(None, controller.get_conf("contactinfo"))
+      
+      # Invalid key
+      try:
+        controller.reset_conf(("invalidkeyboo", "abcde"))
+      except stem.socket.InvalidArguments, exc:
+        self.assertEqual(["invalidkeyboo"], exc.arguments)
+      
+      # Multiple keys, list & dict
       settings = {
-          "HiddenServiceDir": "/tmp/stemtestdir",
-          "HiddenServicePort": "17234 127.0.0.1:17235"
+          "connlimit": "314",
+          "contactinfo": "stem at testing"
           }
-      controller.set_conf(settings)
+      controller.reset_conf(settings)
+      self.assertEqual("314", controller.get_conf("ConnLimit"))
+      self.assertEqual("stem at testing", controller.get_conf("contactinfo"))
+      
+      settings = [
+          ("connlimit", "786"),
+          ("contactinfo", "stem testing")
+          ]
+      controller.reset_conf(settings)
+      self.assertEqual("786", controller.get_conf("ConnLimit"))
+      self.assertEqual("stem testing", controller.get_conf("contactinfo"))
+      
+      # context-sensitive keys
+      settings = [
+          ("HiddenServiceDir", "/tmp/stemtestdir"),
+          ("HiddenServicePort", "17234 127.0.0.1:17235")
+          ]
+      controller.reset_conf(settings)
       self.assertEqual("17234 127.0.0.1:17235", controller.get_conf("hiddenserviceport"))
       self.assertEqual("/tmp/stemtestdir", controller.get_conf("hiddenservicedir"))
 





More information about the tor-commits mailing list