[tor-commits] [stem/master] Initial parts for an interpretor prompt

atagar at torproject.org atagar at torproject.org
Tue May 6 01:21:12 UTC 2014


commit 95c1711c7982dd38689c3ffcb1ede2b32a4c13d9
Author: Damian Johnson <atagar at 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 at 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 at 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()





More information about the tor-commits mailing list