commit dcf0852106423d413c262e7aa87abc8b5695346d Author: Damian Johnson atagar@torproject.org Date: Sat May 10 15:37:47 2014 -0700
Python interpretor when running the prompt
Support for providing the user with a python interpretor when they include the '--python' argument. This is what our old 'prompt' command once provided, and is handy when you'd like to get a quick and easy Controller to interact with. --- stem/interpretor/__init__.py | 37 +++++++++++++++++++++------------- stem/interpretor/arguments.py | 6 +++++- stem/interpretor/settings.cfg | 39 +++++++++++++++++++++++++++++++++--- test/unit/interpretor/arguments.py | 6 +++++- 4 files changed, 69 insertions(+), 19 deletions(-)
diff --git a/stem/interpretor/__init__.py b/stem/interpretor/__init__.py index 892b3b3..9ebcea7 100644 --- a/stem/interpretor/__init__.py +++ b/stem/interpretor/__init__.py @@ -8,6 +8,7 @@ features such as tab completion, history, and IRC-style functions (like /help).
__all__ = ['arguments', 'autocomplete', 'commands', 'help', 'msg']
+import code import os import sys
@@ -69,17 +70,25 @@ def main(): sys.exit(1)
with controller: - autocompleter = stem.interpretor.autocomplete.Autocompleter(controller) - readline.parse_and_bind('tab: complete') - readline.set_completer(autocompleter.complete) - readline.set_completer_delims('\n') - - interpretor = stem.interpretor.commands.ControlInterpretor(controller) - - while True: - try: - user_input = raw_input(PROMPT) - print interpretor.run_command(user_input) - except (KeyboardInterrupt, EOFError, stem.SocketClosed) as exc: - print # move cursor to the following line - break + if args.python_prompt: + console = code.InteractiveConsole({ + 'controller': controller, + 'stem': stem, + 'stem.control': stem.control, + }) + console.interact(msg('msg.python_banner', version = controller.get_info('version'))) + else: + autocompleter = stem.interpretor.autocomplete.Autocompleter(controller) + readline.parse_and_bind('tab: complete') + readline.set_completer(autocompleter.complete) + readline.set_completer_delims('\n') + + interpretor = stem.interpretor.commands.ControlInterpretor(controller) + + while True: + try: + user_input = raw_input(PROMPT) + print interpretor.run_command(user_input) + except (KeyboardInterrupt, EOFError, stem.SocketClosed) as exc: + print # move cursor to the following line + break diff --git a/stem/interpretor/arguments.py b/stem/interpretor/arguments.py index 733da27..6dc327b 100644 --- a/stem/interpretor/arguments.py +++ b/stem/interpretor/arguments.py @@ -17,14 +17,16 @@ DEFAULT_ARGS = { 'user_provided_port': False, 'control_socket': '/var/run/tor/control', 'user_provided_socket': False, + 'python_prompt': False, 'print_help': False, }
-OPT = 'i:s:h' +OPT = 'i:s:ph'
OPT_EXPANDED = [ 'interface=', 'socket=', + 'python', 'help', ]
@@ -68,6 +70,8 @@ def parse(argv): elif opt in ('-s', '--socket'): args['control_socket'] = arg args['user_provided_socket'] = True + elif opt in ('-p', '--python'): + args['python_prompt'] = True elif opt in ('-h', '--help'): args['print_help'] = True
diff --git a/stem/interpretor/settings.cfg b/stem/interpretor/settings.cfg index feec575..73fb067 100644 --- a/stem/interpretor/settings.cfg +++ b/stem/interpretor/settings.cfg @@ -11,17 +11,50 @@ msg.multiline_unimplemented_notice Multi-line control options like this are not yet implemented.
msg.help -|Usage prompt [OPTION] -|Interactive interpretor for Tor. +|Interactive interpretor for Tor. This can provide you with either direct +|access to Tor's control interface or a python prompt connected to Tor... +| +| % prompt -i 9051 +| >>> GETINFO version +| 0.2.5.1-alpha-dev (git-245ecfff36c0cecc) +| +| >>> /help GETINFO +| [ description of tor's GETINFO command ] +| +| >>> /quit +| +| % prompt -pi 9051 +| >>> controller.get_info('version') +| '0.2.5.1-alpha-dev (git-245ecfff36c0cecc)' +| +| >>> for port in controller.get_ports(stem.control.Listener.CONTROL): +| ... print 'you have a control port available on %s' % port +| ... +| you have a control port available on 9051 +| +| >>> quit() +| +|================================================================================ | | -i, --interface [ADDRESS:]PORT change control interface from {address}:{port} | -s, --socket SOCKET_PATH attach using unix domain socket if present, | SOCKET_PATH defaults to: {socket} +| -p, --python provides a python interpretor connected to +| Tor rather than attaching directly | -h, --help presents this help | |Example: |prompt -i 1643 attach to control port 1643 -|prompt -s ~/.tor/socket attach to a control socket in your home directory +|prompt -ps ~/.tor/socket attach to this control socket, and provide a python +| interpretor + +msg.python_banner +|Welcome to Stem's interpretor prompt. You presently have a connection to Tor +|available via your 'controller' variable. For example... +| +| >>> print controller.get_info('version') +| {version} +|
################# # OUTPUT OF /HELP # diff --git a/test/unit/interpretor/arguments.py b/test/unit/interpretor/arguments.py index ab835c4..1141877 100644 --- a/test/unit/interpretor/arguments.py +++ b/test/unit/interpretor/arguments.py @@ -22,6 +22,9 @@ class TestArgumentParsing(unittest.TestCase): args = parse(['--socket', '/tmp/my_socket']) self.assertEqual('/tmp/my_socket', args.control_socket)
+ args = parse(['--python']) + self.assertEqual(True, args.python_prompt) + args = parse(['--help']) self.assertEqual(True, args.print_help)
@@ -29,7 +32,8 @@ class TestArgumentParsing(unittest.TestCase): args = parse(['-i', '1643']) self.assertEqual(1643, args.control_port)
- args = parse(['-s', '~/.tor/socket']) + args = parse(['-ps', '~/.tor/socket']) + self.assertEqual(True, args.python_prompt) self.assertEqual('~/.tor/socket', args.control_socket)
def test_that_we_reject_unrecognized_arguments(self):