commit 045a5ec8774074eb92066571dfc661c4098bd77a Author: Damian Johnson atagar@torproject.org Date: Sun May 27 14:35:15 2012 -0700
Adding Controller class
Making a class for the general controller. As a todo comment mentiond, moving the from_port/from_socket_file helper functions there and revising the tests to reflect that. --- run_tests.py | 2 + stem/control.py | 92 +++++++++++++++++--------------- test/integ/control/__init__.py | 2 +- test/integ/control/base_controller.py | 22 -------- test/integ/control/controller.py | 36 +++++++++++++ 5 files changed, 88 insertions(+), 66 deletions(-)
diff --git a/run_tests.py b/run_tests.py index 85a4f65..d123081 100755 --- a/run_tests.py +++ b/run_tests.py @@ -32,6 +32,7 @@ import test.integ.connection.authentication import test.integ.connection.connect import test.integ.connection.protocolinfo import test.integ.control.base_controller +import test.integ.control.controller import test.integ.socket.control_message import test.integ.socket.control_socket import test.integ.descriptor.reader @@ -118,6 +119,7 @@ INTEG_TESTS = ( test.integ.connection.authentication.TestAuthenticate, test.integ.connection.connect.TestConnect, test.integ.control.base_controller.TestBaseController, + test.integ.control.controller.TestController, )
def load_user_configuration(test_config): diff --git a/stem/control.py b/stem/control.py index 9b912e5..e2d3d90 100644 --- a/stem/control.py +++ b/stem/control.py @@ -8,6 +8,9 @@ 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.
+Controller - General controller class intended for direct use. + +- get_info - issues a GETINFO query + BaseController - Base controller class asynchronous message handling. |- msg - communicates with the tor process |- is_alive - reports if our connection to tor is open or closed @@ -37,54 +40,13 @@ class BaseController: """ Controller for the tor process. This is a minimal base class for other controllers, providing basic process communication and event listing. Don't - use this directly - subclasses provide higher level functionality. + use this directly - subclasses like the Controller provide higher level + functionality.
Do not continue to directly interacte with the ControlSocket we're constructed from - use our wrapper methods instead. """
- # 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 self._msg_lock = threading.RLock() @@ -424,3 +386,47 @@ class BaseController: self._event_notice.wait() self._event_notice.clear()
+class Controller(BaseController): + """ + Communicates with a control socket. This is built on top of the + BaseController and provides a more user friendly API for library users. + """ + + 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 Controller(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 Controller(control_socket) + + from_port = staticmethod(from_port) + from_socket_file = staticmethod(from_socket_file) + diff --git a/test/integ/control/__init__.py b/test/integ/control/__init__.py index 715082f..10c3cf5 100644 --- a/test/integ/control/__init__.py +++ b/test/integ/control/__init__.py @@ -2,5 +2,5 @@ Integration tests for stem.control. """
-__all__ = ["base_controller"] +__all__ = ["base_controller", "controller"]
diff --git a/test/integ/control/base_controller.py b/test/integ/control/base_controller.py index 09c68da..32239d2 100644 --- a/test/integ/control/base_controller.py +++ b/test/integ/control/base_controller.py @@ -35,28 +35,6 @@ class TestBaseController(unittest.TestCase): def setUp(self): test.runner.require_control(self)
- 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(): - with stem.control.BaseController.from_port(control_port = test.runner.CONTROL_PORT) as controller: - 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(): - with stem.control.BaseController.from_socket_file(socket_path = test.runner.CONTROL_SOCKET_PATH) as controller: - 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_connect_repeatedly(self): """ Connects and closes the socket repeatedly. This is a simple attempt to diff --git a/test/integ/control/controller.py b/test/integ/control/controller.py new file mode 100644 index 0000000..4bf8284 --- /dev/null +++ b/test/integ/control/controller.py @@ -0,0 +1,36 @@ +""" +Integration tests for the stem.control.Controller class. +""" + +import unittest + +import stem.control +import stem.socket +import test.runner + +class TestController(unittest.TestCase): + def setUp(self): + test.runner.require_control(self) + + 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(): + with stem.control.Controller.from_port(control_port = test.runner.CONTROL_PORT) as controller: + self.assertTrue(isinstance(controller, stem.control.Controller)) + else: + self.assertRaises(stem.socket.SocketError, stem.control.Controller.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(): + with stem.control.Controller.from_socket_file(socket_path = test.runner.CONTROL_SOCKET_PATH) as controller: + self.assertTrue(isinstance(controller, stem.control.Controller)) + else: + self.assertRaises(stem.socket.SocketError, stem.control.Controller.from_socket_file, test.runner.CONTROL_SOCKET_PATH) +
tor-commits@lists.torproject.org