commit 95c1711c7982dd38689c3ffcb1ede2b32a4c13d9 Author: Damian Johnson atagar@torproject.org Date: Sun Apr 6 11:29:18 2014 -0700
Initial parts for an interpretor prompt
Argument handling, connection, and authentication to tor. This presently doesn't allow you to *do* anything. It's just a 'hello world' demo that prints tor's version. --- prompt | 23 +++------- prompt_old | 19 ++++++++ stem/interpretor/__init__.py | 39 ++++++++++++++++ stem/interpretor/arguments.py | 100 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 164 insertions(+), 17 deletions(-)
diff --git a/prompt b/prompt index c1ba961..fc115a3 100755 --- a/prompt +++ b/prompt @@ -1,19 +1,8 @@ -#!/bin/sh -# -# Provides a quick method of getting a controller that we can use to test stem -# with. This starts tor if it isn't already running and provides us with a -# controller instance. When done it gives us the option to stop the tor. -# -# atagar@morrigan:~/Desktop/stem$ ./prompt -# Welcome to stem's testing prompt. You currently have a controller available -# via the 'controller' variable. -# -# >>> controller.get_info("version") -# '0.2.1.30' -# >>> quit() -# -# Would you like to stop the tor instance we made? (y/n, default: n): y +#!/usr/bin/env python +# Copyright 2014, Damian Johnson and The Tor Project +# See LICENSE for licensing information
-python -i -c "import test.prompt; test.prompt.print_usage(); controller = test.prompt.controller()" -python -c "import test.prompt; test.prompt.stop(True)" +import stem.interpretor
+if __name__ == '__main__': + stem.interpretor.main() diff --git a/prompt_old b/prompt_old new file mode 100755 index 0000000..c1ba961 --- /dev/null +++ b/prompt_old @@ -0,0 +1,19 @@ +#!/bin/sh +# +# Provides a quick method of getting a controller that we can use to test stem +# with. This starts tor if it isn't already running and provides us with a +# controller instance. When done it gives us the option to stop the tor. +# +# atagar@morrigan:~/Desktop/stem$ ./prompt +# Welcome to stem's testing prompt. You currently have a controller available +# via the 'controller' variable. +# +# >>> controller.get_info("version") +# '0.2.1.30' +# >>> quit() +# +# Would you like to stop the tor instance we made? (y/n, default: n): y + +python -i -c "import test.prompt; test.prompt.print_usage(); controller = test.prompt.controller()" +python -c "import test.prompt; test.prompt.stop(True)" + diff --git a/stem/interpretor/__init__.py b/stem/interpretor/__init__.py new file mode 100644 index 0000000..ffe0012 --- /dev/null +++ b/stem/interpretor/__init__.py @@ -0,0 +1,39 @@ +# Copyright 2014, Damian Johnson and The Tor Project +# See LICENSE for licensing information + +""" +Interactive interpretor for interacting with Tor directly. This adds usability +features such as tab completion, history, and IRC-style functions (like /help). +""" + +__all__ = ['arguments'] + +import sys + +import stem.connection +import stem.interpretor.arguments + +def main(): + try: + args = stem.interpretor.arguments.parse(sys.argv[1:]) + except ValueError as exc: + print exc + sys.exit(1) + + if args.print_help: + print stem.interpretor.arguments.get_help() + sys.exit() + + control_port = None if args.user_provided_socket else (args.control_address, args.control_port) + control_socket = None if args.user_provided_port else args.control_socket + + controller = stem.connection.connect( + control_port = control_port, + control_socket = control_socket, + ) + + if controller is None: + sys.exit(1) + + with controller: + print controller.get_version() diff --git a/stem/interpretor/arguments.py b/stem/interpretor/arguments.py new file mode 100644 index 0000000..f7feac4 --- /dev/null +++ b/stem/interpretor/arguments.py @@ -0,0 +1,100 @@ +# Copyright 2014, Damian Johnson and The Tor Project +# See LICENSE for licensing information + +""" +Commandline argument parsing for arm. +""" + +import collections +import getopt + +DEFAULT_ARGS = { + 'control_address': '127.0.0.1', + 'control_port': 9051, + 'user_provided_port': False, + 'control_socket': '/var/run/tor/control', + 'user_provided_socket': False, + 'print_help': False, +} + +OPT = 'i:s:h' + +OPT_EXPANDED = [ + 'interface=', + 'socket=', + 'help', +] + +HELP_OUTPUT = """ +Usage prompt [OPTION] +Interactive interpretor for Tor. + + -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} + -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 +""" + +def parse(argv): + """ + Parses our arguments, providing a named tuple with their values. + + :param list argv: input arguments to be parsed + + :returns: a **named tuple** with our parsed arguments + + :raises: **ValueError** if we got an invalid argument + """ + + args = dict(DEFAULT_ARGS) + + try: + getopt_results = getopt.getopt(argv, OPT, OPT_EXPANDED)[0] + except getopt.GetoptError as exc: + raise ValueError(msg('usage.invalid_arguments', error = exc)) + + for opt, arg in getopt_results: + if opt in ('-i', '--interface'): + if ':' in arg: + address, port = arg.split(':', 1) + else: + address, port = None, arg + + if address is not None: + if not stem.util.connection.is_valid_ipv4_address(address): + raise ValueError(msg('usage.not_a_valid_address', address_input = address)) + + args['control_address'] = address + + if not stem.util.connection.is_valid_port(port): + raise ValueError(msg('usage.not_a_valid_port', port_input = port)) + + args['control_port'] = int(port) + args['user_provided_port'] = True + elif opt in ('-s', '--socket'): + args['control_socket'] = arg + args['user_provided_socket'] = True + elif opt in ('-h', '--help'): + args['print_help'] = True + + # translates our args dict into a named tuple + + Args = collections.namedtuple('Args', args.keys()) + return Args(**args) + +def get_help(): + """ + Provides our --help usage information. + + :returns: **str** with our usage information + """ + + return HELP_OUTPUT.format( + address = DEFAULT_ARGS['control_address'], + port = DEFAULT_ARGS['control_port'], + socket = DEFAULT_ARGS['control_socket'], + ).strip()
tor-commits@lists.torproject.org