commit 9a70131cf2bf0b25f89faa89c62fb70d5e891ee1 Author: Ravi Chandra Padmala neenaoffline@gmail.com Date: Tue Jul 3 01:34:46 2012 +0530
Implement use_feature wrapper method --- stem/control.py | 38 ++++++++++++++++++++++++++++++++++++++ stem/version.py | 1 + test/integ/control/controller.py | 19 +++++++++++++++++++ 3 files changed, 58 insertions(+), 0 deletions(-)
diff --git a/stem/control.py b/stem/control.py index dd5f812..f2eb47a 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 + |- 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 +- protocolinfo - convenience method to get the protocol info @@ -962,6 +963,43 @@ class Controller(BaseController): raise stem.socket.OperationFailed(response.code, response.message) else: raise stem.socket.ProtocolError("SAVECONF returned unexpected response code") + + def enable_feature(self, features): + """ + Enables features that are disabled by default to maintain backward + compatibility. Once enabled, a feature cannot be disabled and a new + control connection must be opened to get a connection with the feature + 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. + + :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 + """ + + if type(features) == str: features = [features] + response = self.msg("USEFEATURE %s" % " ".join(features)) + stem.response.convert("SINGLELINE", response) + + if not response.is_ok(): + if response.code == "552": + invalid_feature = [] + if response.message.startswith("Unrecognized feature ""): + 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")
def _case_insensitive_lookup(entries, key, default = UNDEFINED): """ diff --git a/stem/version.py b/stem/version.py index 08f5ca2..e17d63b 100644 --- a/stem/version.py +++ b/stem/version.py @@ -249,5 +249,6 @@ 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")), )
diff --git a/test/integ/control/controller.py b/test/integ/control/controller.py index 54f2626..88ef642 100644 --- a/test/integ/control/controller.py +++ b/test/integ/control/controller.py @@ -316,4 +316,23 @@ class TestController(unittest.TestCase): finally: controller.load_conf(oldconf) controller.save_conf() + + def test_enable_feature(self): + """ + Test Controller.enable_feature with valid and invalid inputs. + """ + + if test.runner.require_control(self): return + + runner = test.runner.get_runner() + + with runner.get_tor_controller() as controller: + if test.runner.require_version(self, stem.version.Requirement.FEATURE_VERBOSENAMES): + controller.enable_feature("VERBOSE_NAMES") + self.assertRaises(stem.socket.InvalidArguments, controller.enable_feature, ["NOT", "A", "FEATURE"]) + try: + controller.enable_feature(["NOT", "A", "FEATURE"]) + except stem.socket.InvalidArguments, exc: + self.assertEqual(["NOT"], exc.arguments) + else: self.fail()