commit 398cbfb93a4982961e1ce27fc05d82265408e78a Author: Damian Johnson atagar@torproject.org Date: Mon Feb 6 08:16:59 2012 -0800
Helper constructors for BaseController instances
A controller is a wrapper around a ControlSocket instance so adding convenience methods to construct both the socket and controller at the same time. These will belong to the Controller class later. --- stem/control.py | 47 +++++++++++++++++++++++++++++++++ test/integ/control/base_controller.py | 23 ++++++++++++++++ 2 files changed, 70 insertions(+), 0 deletions(-)
diff --git a/stem/control.py b/stem/control.py index d1f30ee..c485cb9 100644 --- a/stem/control.py +++ b/stem/control.py @@ -4,6 +4,11 @@ Classes for interacting with the tor control socket. Controllers are a wrapper around a ControlSocket, retaining its low-level connection methods (send, recv, is_alive, etc) in addition to providing methods for interacting at a higher level. + +from_port - Provides a Controller based on a port connection. +from_socket_file - Provides a Controller based on a socket file connection. + +BaseController - ControlSocket subclass providing asynchronous message handling. """
import stem.socket @@ -18,6 +23,48 @@ class BaseController(stem.socket.ControlSocket): socket - ControlSocket from which this was constructed """
+ # TODO: Convenience methods for the BaseController are pointless since + # callers generally won't want to make instances of this directly. Move + # these to the Controller class once we have one. + + def from_port(control_addr = "127.0.0.1", control_port = 9051): + """ + Constructs a ControlPort based Controller. + + Arguments: + control_addr (str) - ip address of the controller + control_port (int) - port number of the controller + + Returns: + stem.control.Controller attached to the given port + + Raises: + stem.socket.SocketError if we're unable to establish a connection + """ + + control_port = stem.socket.ControlPort(control_addr, control_port) + return BaseController(control_port) + + def from_socket_file(socket_path = "/var/run/tor/control"): + """ + Constructs a ControlSocketFile based Controller. + + Arguments: + socket_path (str) - path where the control socket is located + + Returns: + stem.control.Controller attached to the given socket file + + Raises: + stem.socket.SocketError if we're unable to establish a connection + """ + + control_socket = stem.socket.ControlSocketFile(socket_path) + return BaseController(control_socket) + + from_port = staticmethod(from_port) + from_socket_file = staticmethod(from_socket_file) + def __init__(self, control_socket): self.socket = control_socket
diff --git a/test/integ/control/base_controller.py b/test/integ/control/base_controller.py index 467c057..e30964c 100644 --- a/test/integ/control/base_controller.py +++ b/test/integ/control/base_controller.py @@ -5,6 +5,7 @@ Integration tests for the stem.control.BaseController class. import unittest
import stem.control +import stem.socket import test.runner import test.mocking as mocking import test.integ.socket.control_socket @@ -16,6 +17,28 @@ class TestBaseController(unittest.TestCase): def tearDown(self): mocking.revert_mocking()
+ def test_from_port(self): + """ + Basic sanity check for the from_port constructor. + """ + + if test.runner.Torrc.PORT in test.runner.get_runner().get_options(): + controller = stem.control.BaseController.from_port(control_port = test.runner.CONTROL_PORT) + self.assertTrue(isinstance(controller, stem.control.BaseController)) + else: + self.assertRaises(stem.socket.SocketError, stem.control.BaseController.from_port, "127.0.0.1", test.runner.CONTROL_PORT) + + def test_from_socket_file(self): + """ + Basic sanity check for the from_socket_file constructor. + """ + + if test.runner.Torrc.SOCKET in test.runner.get_runner().get_options(): + controller = stem.control.BaseController.from_socket_file(test.runner.CONTROL_SOCKET_PATH) + self.assertTrue(isinstance(controller, stem.control.BaseController)) + else: + self.assertRaises(stem.socket.SocketError, stem.control.BaseController.from_socket_file, test.runner.CONTROL_SOCKET_PATH) + def test_socket_passthrough(self): """ The BaseController is a passthrough for the socket it is built from, so