[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [stem/master] Only doing raw controller requests via the prompt
commit 32b9f75825d0c67639ded301f76d8c599031a616
Author: Damian Johnson <atagar@xxxxxxxxxxxxxx>
Date: Sun May 11 22:21:09 2014 -0700
Only doing raw controller requests via the prompt
I was using our Controller's high level methods (get_info(), get_conf(),
add_event_listeners()) for a couple reasons. First they provide caching and
second because they yeild more succinct output. But on refection those are both
terrible reasons. Caching is worthless with such a low call volume, and it's
actually *better* if we print raw Tor responses. This is supposed to provide
raw controller accesss, right? :)
If users want the behavior of the high level methods then they can now call
those easy enough.
---
stem/control.py | 2 +
stem/interpretor/commands.py | 88 +++++--------------------------------
stem/interpretor/settings.cfg | 7 +--
test/mocking.py | 3 +-
test/unit/interpretor/commands.py | 50 +++++++--------------
5 files changed, 32 insertions(+), 118 deletions(-)
diff --git a/stem/control.py b/stem/control.py
index 02c9fa5..27cce01 100644
--- a/stem/control.py
+++ b/stem/control.py
@@ -1915,6 +1915,7 @@ class Controller(BaseController):
"""
# first checking that tor supports these event types
+
with self._event_listeners_lock:
if self.is_authenticated():
for event_type in events:
@@ -1929,6 +1930,7 @@ class Controller(BaseController):
failed_events = self._attach_listeners()[1]
# restricted the failures to just things we requested
+
failed_events = set(failed_events).intersection(set(events))
if failed_events:
diff --git a/stem/interpretor/commands.py b/stem/interpretor/commands.py
index 4b90fce..b66c87b 100644
--- a/stem/interpretor/commands.py
+++ b/stem/interpretor/commands.py
@@ -3,7 +3,6 @@ Handles making requests and formatting the responses.
"""
import code
-import re
import stem
import stem.control
@@ -103,12 +102,16 @@ class ControlInterpretor(code.InteractiveConsole):
self.is_multiline_context = False
- def register_event(self, event):
- """
- Adds the event to our buffer so it'll be in '/events' output.
- """
+ # Intercept events our controller hears about at a pretty low level since
+ # the user will likely be requesting them by direct 'SETEVENTS' calls.
+
+ handle_event_real = self._controller._handle_event
+
+ def handle_event_wrapper(event_message):
+ handle_event_real(event_message)
+ self._received_events.append(event_message)
- self._received_events.append(event)
+ self._controller._handle_event = handle_event_wrapper
def do_help(self, arg):
"""
@@ -270,76 +273,7 @@ class ControlInterpretor(code.InteractiveConsole):
else:
cmd = cmd.upper() # makes commands uppercase to match the spec
- if cmd == 'GETINFO':
- try:
- response = self._controller.get_info(arg.split())
- output = format('\n'.join(response.values()), *STANDARD_OUTPUT)
- except stem.ControllerError as exc:
- output = format(str(exc), *ERROR_OUTPUT)
- elif cmd == 'GETCONF':
- try:
- response = self._controller.get_conf_map(arg.split())
-
- for arg in response:
- output += format(arg, *BOLD_OUTPUT) + format(' => ' + ', '.join(response[arg]), *STANDARD_OUTPUT) + '\n'
- except stem.ControllerError as exc:
- output = format(str(exc), *ERROR_OUTPUT)
- elif cmd in ('SETCONF', 'RESETCONF'):
- # arguments can either be '<param>', '<param>=<value>', or
- # '<param>="<value>"' entries
-
- param_list = []
-
- while arg:
- # TODO: I'm a little dubious of this for LineList values (like the
- # ExitPolicy) since they're parsed as a single value. However, tor
- # seems to be happy to get a single comma separated string (though it
- # echos back faithfully rather than being parsed) so leaving this
- # alone for now.
-
- quoted_match = re.match(r'^(\S+)=\"([^"]+)\"', arg)
- nonquoted_match = re.match(r'^(\S+)=(\S+)', arg)
-
- if quoted_match:
- # we're dealing with a '<param>="<value>"' entry
- param, value = quoted_match.groups()
-
- param_list.append((param, value))
- arg = arg[len(param) + len(value) + 3:].strip()
- elif nonquoted_match:
- # we're dealing with a '<param>=<value>' entry
- param, value = nonquoted_match.groups()
-
- param_list.append((param, value))
- arg = arg[len(param) + len(value) + 1:].strip()
- else:
- # starts with just a param
- param = arg.split()[0]
- param_list.append((param, None))
- arg = arg[len(param):].strip()
-
- try:
- is_reset = cmd == 'RESETCONF'
- self._controller.set_options(param_list, is_reset)
- except stem.ControllerError as exc:
- output = format(str(exc), *ERROR_OUTPUT)
- elif cmd == 'SETEVENTS':
- try:
- # first discontinue listening to prior events
-
- self._controller.remove_event_listener(self.register_event)
-
- # attach listeners for the given group of events
-
- if arg:
- events = arg.split()
- self._controller.add_event_listener(self.register_event, *events)
- output = format(msg('msg.listening_to_events', events = ', '.join(events)), *STANDARD_OUTPUT)
- else:
- output = format('Disabled event listening', *STANDARD_OUTPUT)
- except stem.ControllerError as exc:
- output = format(str(exc), *ERROR_OUTPUT)
- elif cmd.replace('+', '') in ('LOADCONF', 'POSTDESCRIPTOR'):
+ if cmd.replace('+', '') in ('LOADCONF', 'POSTDESCRIPTOR'):
# provides a notice that multi-line controller input isn't yet implemented
output = format(msg('msg.multiline_unimplemented_notice'), *ERROR_OUTPUT)
elif cmd == 'QUIT':
@@ -353,7 +287,7 @@ class ControlInterpretor(code.InteractiveConsole):
return
else:
try:
- output = format(str(self._controller.msg(command)), *STANDARD_OUTPUT)
+ output = format(self._controller.msg(command).raw_content().strip(), *STANDARD_OUTPUT)
except stem.ControllerError as exc:
if isinstance(exc, stem.SocketClosed):
raise exc
diff --git a/stem/interpretor/settings.cfg b/stem/interpretor/settings.cfg
index b8d39dc..028188f 100644
--- a/stem/interpretor/settings.cfg
+++ b/stem/interpretor/settings.cfg
@@ -34,7 +34,8 @@ msg.startup_banner
|You can also issue requests directly to Tor...
|
| >>> GETINFO version
-| 0.2.5.1-alpha-dev (git-245ecfff36c0cecc)
+| 250-version=0.2.5.1-alpha-dev (git-245ecfff36c0cecc)
+| 250 OK
|
|For more information run '/help'.
|
@@ -49,10 +50,6 @@ msg.starting_tor
|--------------------------------------------------------------------------------
|
-msg.listening_to_events
-|Listening for {events} events. You can print events we've received with
-|'/events', and also interact with them via the 'events' variable.
-
#################
# OUTPUT OF /HELP #
#################
diff --git a/test/mocking.py b/test/mocking.py
index bfd68f6..f139548 100644
--- a/test/mocking.py
+++ b/test/mocking.py
@@ -38,6 +38,7 @@ Helper functions for creating mock objects.
import base64
import hashlib
import itertools
+import re
import stem.descriptor.extrainfo_descriptor
import stem.descriptor.microdescriptor
@@ -227,7 +228,7 @@ def get_message(content, reformat = True):
if not content.endswith('\n'):
content += '\n'
- content = content.replace('\n', '\r\n')
+ content = re.sub('([\r]?)\n', '\r\n', content)
return stem.response.ControlMessage.from_str(content)
diff --git a/test/unit/interpretor/commands.py b/test/unit/interpretor/commands.py
index 1d03779..dfdbddb 100644
--- a/test/unit/interpretor/commands.py
+++ b/test/unit/interpretor/commands.py
@@ -1,4 +1,3 @@
-import collections
import datetime
import unittest
@@ -130,7 +129,7 @@ class TestInterpretorCommands(unittest.TestCase):
for content in event_contents:
event = mocking.get_message(content)
stem.response.convert('EVENT', event)
- interpretor.register_event(event)
+ interpretor._received_events.append(event)
self.assertEqual(EXPECTED_EVENTS_RESPONSE, interpretor.run_command('/events'))
@@ -166,53 +165,34 @@ class TestInterpretorCommands(unittest.TestCase):
self.assertEqual(expected, interpretor.run_command('/unrecognized'))
def test_getinfo(self):
- controller, getinfo = Mock(), collections.OrderedDict()
- controller.get_info.return_value = getinfo
+ response = '250-version=0.2.5.1-alpha-dev (git-245ecfff36c0cecc)\r\n250 OK'
- interpretor = ControlInterpretor(controller)
+ controller = Mock()
+ controller.msg.return_value = mocking.get_message(response)
- getinfo['version'] = '0.2.5.1-alpha-dev (git-245ecfff36c0cecc)'
- self.assertEqual('\x1b[34m0.2.5.1-alpha-dev (git-245ecfff36c0cecc)\x1b[0m\n', interpretor.run_command('GETINFO version'))
- controller.get_info.assert_called_with(['version'])
+ interpretor = ControlInterpretor(controller)
- getinfo['process/user'] = 'atagar'
- self.assertEqual('\x1b[34m0.2.5.1-alpha-dev (git-245ecfff36c0cecc)\natagar\x1b[0m\n', interpretor.run_command('getinfo version process/user'))
- controller.get_info.assert_called_with(['version', 'process/user'])
+ self.assertEqual('\x1b[34m%s\x1b[0m\n' % response, interpretor.run_command('GETINFO version'))
+ controller.msg.assert_called_with('GETINFO version')
- controller.get_info.side_effect = stem.ControllerError('kaboom!')
+ controller.msg.side_effect = stem.ControllerError('kaboom!')
self.assertEqual('\x1b[1;31mkaboom!\x1b[0m\n', interpretor.run_command('getinfo process/user'))
def test_getconf(self):
- controller, getconf = Mock(), collections.OrderedDict()
- controller.get_conf_map.return_value = getconf
-
- interpretor = ControlInterpretor(controller)
-
- getconf['log'] = ['notice stdout']
- getconf['address'] = ['']
+ response = '250-Log=notice stdout\r\n250 Address'
- self.assertEqual(EXPECTED_GETCONF_RESPONSE, interpretor.run_command('GETCONF log address'))
- controller.get_conf_map.assert_called_with(['log', 'address'])
-
- def test_setconf(self):
controller = Mock()
+ controller.msg.return_value = mocking.get_message(response)
+
interpretor = ControlInterpretor(controller)
- self.assertEqual('\n', interpretor.run_command('SETCONF ControlPort=9051'))
- controller.set_options.assert_called_with([('ControlPort', '9051')], False)
+ self.assertEqual('\x1b[34m%s\x1b[0m\n' % response, interpretor.run_command('GETCONF log address'))
+ controller.msg.assert_called_with('GETCONF log address')
def test_setevents(self):
controller = Mock()
- interpretor = ControlInterpretor(controller)
+ controller.msg.return_value = mocking.get_message('250 OK')
- self.assertEqual("\x1b[34mListening for BW events. You can print events we've received with\n'/events', and also interact with them via the 'events' variable.\x1b[0m\n", interpretor.run_command('SETEVENTS BW'))
- controller.add_event_listener.assert_called_with(interpretor.register_event, 'BW')
-
- def test_raw_commands(self):
- controller = Mock()
- controller.msg.return_value = 'response'
interpretor = ControlInterpretor(controller)
- interpretor.do_python('disable')
- self.assertEqual('\x1b[34mresponse\x1b[0m\n', interpretor.run_command('NEW_COMMAND spiffyness'))
- controller.msg.assert_called_with('NEW_COMMAND spiffyness')
+ self.assertEqual('\x1b[34m250 OK\x1b[0m\n', interpretor.run_command('SETEVENTS BW'))
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits