[tor-commits] [stem/master] Add Controller.is_feature_enabled

atagar at torproject.org atagar at torproject.org
Sun Aug 26 20:36:53 UTC 2012


commit 17d536657c43984665138ee131e77a6a291176d5
Author: Ravi Chandra Padmala <neenaoffline at gmail.com>
Date:   Wed Aug 22 23:45:49 2012 +0530

    Add Controller.is_feature_enabled
    
    Also made some minor modifications based on CR in #6417
---
 stem/control.py                  |   41 +++++++++++++++++++++++++++----------
 stem/version.py                  |    3 +-
 test/integ/control/controller.py |    8 +++++-
 3 files changed, 38 insertions(+), 14 deletions(-)

diff --git a/stem/control.py b/stem/control.py
index f2eb47a..8d59682 100644
--- a/stem/control.py
+++ b/stem/control.py
@@ -24,6 +24,7 @@ interacting at a higher level.
     |- set_options - sets or resets the values of multiple configuration options
     |- load_conf - loads configuration information as if it was in the torrc
     |- save_conf - saves configuration information to the torrc
+    |- is_feature_enabled - returns true if a given control connection feature is enabled
     |- enable_feature - enables control protocol features that have been disabled by default
     |- get_version - convenience method to get tor version
     |- authenticate - convenience method to authenticate the controller
@@ -489,6 +490,7 @@ class Controller(BaseController):
     
     # number of sequental 'GETINFO ip-to-country/*' lookups that have failed
     self._geoip_failure_count = 0
+    self.enabled_features = []
   
   def connect(self):
     super(Controller, self).connect()
@@ -964,6 +966,28 @@ class Controller(BaseController):
     else:
       raise stem.socket.ProtocolError("SAVECONF returned unexpected response code")
   
+  def is_feature_enabled(self, feature):
+    """
+    Checks if a control connection feature is enabled. These features can be
+    enabled using :func:`stem.control.Controller.enable_feature`.
+    
+    :param str feature: feature to be checked
+    
+    :returns: True if feature is enabled, False otherwise
+    """
+    
+    defaulted_version = None
+    
+    if feature == "EXTENDED_EVENTS":
+      defaulted_version = stem.version.Requirement.EXTENDED_EVENTS_DEFAULTED
+    elif feature == "VERBOSE_NAMES":
+      defaulted_version = stem.version.Requirement.VERBOSE_NAMES_DEFAULTED
+    
+    if defaulted_version and self.get_version().meets_requirements(defaulted_version):
+      return True
+    else:
+      return feature in self.enabled_features
+  
   def enable_feature(self, features):
     """
     Enables features that are disabled by default to maintain backward
@@ -972,21 +996,14 @@ class Controller(BaseController):
     disabled. Feature names are case-insensitive.
     
     The following features are currently accepted:
-      * EXTENDED_EVENTS - Requests the extended event syntax. Has the same
-          effect as calling SETEVENTS with EXTENDED. Introduced in
-          0.1.2.3-alpha, always-on since Tor 0.2.2.1-alpha
-      * VERBOSE_NAMES - Replaces ServerID with LongName in events and GETINFO
-          results. LongName provides a Fingerprint for all routers, an indication
-          of Named status, and a Nickname if one is known. LongName is strictly
-          more informative than ServerID, which only provides either a Fingerprint
-          or a Nickname. Introduced in 0.1.2.2-alpha, always-on since Tor
-          0.2.2.1-alpha.
+      * EXTENDED_EVENTS - Requests the extended event syntax
+      * VERBOSE_NAMES - Replaces ServerID with LongName in events and GETINFO results
     
     :param str,list features: a single feature or a list of features to be enabled
     
     :raises:
-      :class:`stem.socket.ControllerError` if the call fails
-      :class:`stem.socket.InvalidArguments` if features passed were invalid
+      * :class:`stem.socket.ControllerError` if the call fails
+      * :class:`stem.socket.InvalidArguments` if features passed were invalid
     """
     
     if type(features) == str: features = [features]
@@ -1000,6 +1017,8 @@ class Controller(BaseController):
           invalid_feature = [response.message[22:response.message.find("\"", 22)]]
         raise stem.socket.InvalidArguments(response.code, response.message, invalid_feature)
       raise stem.socket.ProtocolError("USEFEATURE returned invalid response code")
+    
+    self.enabled_features = list(set(self.enabled_features).union(features))
 
 def _case_insensitive_lookup(entries, key, default = UNDEFINED):
   """
diff --git a/stem/version.py b/stem/version.py
index e17d63b..90cc997 100644
--- a/stem/version.py
+++ b/stem/version.py
@@ -249,6 +249,7 @@ Requirement = stem.util.enum.Enum(
   ("LOADCONF", Version("0.2.1.1")),
   ("TORRC_CONTROL_SOCKET", Version("0.2.0.30")),
   ("TORRC_DISABLE_DEBUGGER_ATTACHMENT", Version("0.2.3.9")),
-  ("FEATURE_VERBOSENAMES", Version("0.1.2.2-alpha")),
+  ("VERBOSE_NAMES_DEFAULTED", Version("0.2.2.1-alpha")),
+  ("EXTENDED_EVENTS_DEFAULTED", Version("0.2.2.1-alpha")),
 )
 
diff --git a/test/integ/control/controller.py b/test/integ/control/controller.py
index 88ef642..ea91c8c 100644
--- a/test/integ/control/controller.py
+++ b/test/integ/control/controller.py
@@ -4,9 +4,10 @@ Integration tests for the stem.control.Controller class.
 
 from __future__ import with_statement
 
+import re
+import shutil
 import unittest
 import tempfile
-import shutil
 
 import stem.control
 import stem.socket
@@ -327,8 +328,11 @@ class TestController(unittest.TestCase):
     runner = test.runner.get_runner()
     
     with runner.get_tor_controller() as controller:
-      if test.runner.require_version(self, stem.version.Requirement.FEATURE_VERBOSENAMES):
+      if not test.runner.require_version(self, stem.version.Version("0.1.2.2-alpha")):
         controller.enable_feature("VERBOSE_NAMES")
+      self.assertTrue(re.match("\$[0-9a-fA-F]{40}[~=].*", controller.get_info('orconn-status').split()[0]))
+      self.assertTrue(controller.is_feature_enabled("VERBOSE_NAMES"))
+      self.assertTrue("VERBOSE_NAMES" in controller.enabled_features)
       self.assertRaises(stem.socket.InvalidArguments, controller.enable_feature, ["NOT", "A", "FEATURE"])
       try:
         controller.enable_feature(["NOT", "A", "FEATURE"])





More information about the tor-commits mailing list