[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[tor-commits] [stem/master] Moving exceptions to stem's toplevel module



commit 82747342cac4a7204b42928fe3a3f32fadea62c6
Author: Ravi Chandra Padmala <neenaoffline@xxxxxxxxx>
Date:   Tue Nov 6 19:08:03 2012 +0530

    Moving exceptions to stem's toplevel module
    
    Fixing #6357
---
 stem/__init__.py                        |   63 +++++++++++++++
 stem/connection.py                      |   40 +++++-----
 stem/control.py                         |  130 +++++++++++++++---------------
 stem/response/__init__.py               |   16 ++--
 stem/response/authchallenge.py          |   14 ++--
 stem/response/getconf.py                |    4 +-
 stem/response/getinfo.py                |   12 ++--
 stem/response/mapaddress.py             |   12 ++--
 stem/response/protocolinfo.py           |   14 ++--
 stem/socket.py                          |  121 +++++++---------------------
 test/integ/connection/authentication.py |    2 +-
 test/integ/control/base_controller.py   |    4 +-
 test/integ/control/controller.py        |   46 ++++++------
 test/integ/socket/control_message.py    |   14 ++--
 test/integ/socket/control_socket.py     |   10 +-
 test/unit/connection/authentication.py  |   10 +-
 test/unit/response/authchallenge.py     |    2 +-
 test/unit/response/control_message.py   |    8 +-
 test/unit/response/getconf.py           |    6 +-
 test/unit/response/getinfo.py           |    8 +-
 test/unit/response/mapaddress.py        |    6 +-
 test/unit/response/protocolinfo.py      |    2 +-
 test/unit/response/singleline.py        |    2 +-
 test/util.py                            |    4 +-
 24 files changed, 277 insertions(+), 273 deletions(-)

diff --git a/stem/__init__.py b/stem/__init__.py
index c05fcda..4146dff 100644
--- a/stem/__init__.py
+++ b/stem/__init__.py
@@ -1,5 +1,18 @@
 """
 Library for working with the tor process.
+
+**Module Overview:**
+
+::
+
+  ControllerError - Base exception raised when using the controller.
+    |- ProtocolError - Malformed socket data.
+    |- OperationFailed - Tor was unable to successfully complete the operation.
+    |  |- UnsatisfiableRequest - Tor was unable to satisfy a valid request.
+    |  +- InvalidRequest - Invalid request.
+    |     +- InvalidArguments - Invalid request parameters.
+    +- SocketError - Communication with the socket failed.
+       +- SocketClosed - Socket has been shut down.
 """
 
 __version__ = '0.0.1'
@@ -21,3 +34,53 @@ __all__ = [
   "version",
 ]
 
+class ControllerError(Exception):
+  "Base error for controller communication issues."
+
+class ProtocolError(ControllerError):
+  "Malformed content from the control socket."
+
+class OperationFailed(ControllerError):
+  """
+  Base exception class for failed operations that return an error code
+  
+  :var str code: error code returned by Tor
+  :var str message: error message returned by Tor or a human readable error
+    message
+  """
+  
+  def __init__(self, code = None, message = None):
+    super(ControllerError, self).__init__(message)
+    self.code = code
+    self.message = message
+
+class UnsatisfiableRequest(OperationFailed):
+  """
+  Exception raised if Tor was unable to process our request.
+  """
+
+class InvalidRequest(OperationFailed):
+  """
+  Exception raised when the request was invalid or malformed.
+  """
+
+class InvalidArguments(InvalidRequest):
+  """
+  Exception class for requests which had invalid arguments.
+  
+  :var str code: error code returned by Tor
+  :var str message: error message returned by Tor or a human readable error
+    message
+  :var list arguments: a list of arguments which were invalid
+  """
+  
+  def __init__(self, code = None, message = None, arguments = None):
+    super(InvalidArguments, self).__init__(code, message)
+    self.arguments = arguments
+
+class SocketError(ControllerError):
+  "Error arose while communicating with the control socket."
+
+class SocketClosed(SocketError):
+  "Control socket was closed before completing the message."
+
diff --git a/stem/connection.py b/stem/connection.py
index 20f0d84..e4971fa 100644
--- a/stem/connection.py
+++ b/stem/connection.py
@@ -20,7 +20,7 @@ fine-grained control over the authentication process. For instance...
   
   try:
     control_socket = stem.socket.ControlPort(control_port = 9051)
-  except stem.socket.SocketError, exc:
+  except stem.SocketError, exc:
     print "Unable to connect to port 9051 (%s)" % exc
     sys.exit(1)
   
@@ -131,7 +131,7 @@ def connect_port(control_addr = "127.0.0.1", control_port = 9051, password = Non
   
   try:
     control_port = stem.socket.ControlPort(control_addr, control_port)
-  except stem.socket.SocketError, exc:
+  except stem.SocketError, exc:
     print exc
     return None
   
@@ -153,7 +153,7 @@ def connect_socket_file(socket_path = "/var/run/tor/control", password = None, c
   
   try:
     control_socket = stem.socket.ControlSocketFile(socket_path)
-  except stem.socket.SocketError, exc:
+  except stem.SocketError, exc:
     print exc
     return None
   
@@ -303,9 +303,9 @@ def authenticate(controller, password = None, chroot_path = None, protocolinfo_r
   if not protocolinfo_response:
     try:
       protocolinfo_response = get_protocolinfo(controller)
-    except stem.socket.ProtocolError:
+    except stem.ProtocolError:
       raise IncorrectSocketType("unable to use the control socket")
-    except stem.socket.SocketError, exc:
+    except stem.SocketError, exc:
       raise AuthenticationFailure("socket connection failed (%s)" % exc)
   
   auth_methods = list(protocolinfo_response.auth_methods)
@@ -384,7 +384,7 @@ def authenticate(controller, password = None, chroot_path = None, protocolinfo_r
       
       log.debug("The %s method raised a CookieAuthRejected when cookie auth should be available. Stem may need to be corrected to recognize this response: %s" % (auth_func, exc))
       auth_exceptions.append(IncorrectCookieValue(str(exc), exc.cookie_path, exc.is_safecookie))
-    except stem.socket.ControllerError, exc:
+    except stem.ControllerError, exc:
       auth_exceptions.append(AuthenticationFailure(str(exc)))
   
   # All authentication attempts failed. Raise the exception that takes priority
@@ -418,7 +418,7 @@ def authenticate_none(controller, suppress_ctl_errors = True):
   
   :param controller: tor controller or socket to be authenticated
   :param bool suppress_ctl_errors: reports raised
-    :class:`~stem.socket.ControllerError` as authentication rejection if
+    :class:`~stem.ControllerError` as authentication rejection if
     **True**, otherwise they're re-raised
   
   :raises: :class:`stem.connection.OpenAuthRejected` if the empty authentication credentials aren't accepted
@@ -433,7 +433,7 @@ def authenticate_none(controller, suppress_ctl_errors = True):
       except: pass
       
       raise OpenAuthRejected(str(auth_response), auth_response)
-  except stem.socket.ControllerError, exc:
+  except stem.ControllerError, exc:
     try: controller.connect()
     except: pass
     
@@ -464,7 +464,7 @@ def authenticate_password(controller, password, suppress_ctl_errors = True):
   :param controller: tor controller or socket to be authenticated
   :param str password: passphrase to present to the socket
   :param bool suppress_ctl_errors: reports raised
-    :class:`~stem.socket.ControllerError` as authentication rejection if
+    :class:`~stem.ControllerError` as authentication rejection if
     **True**, otherwise they're re-raised
   
   :raises:
@@ -496,7 +496,7 @@ def authenticate_password(controller, password, suppress_ctl_errors = True):
         raise IncorrectPassword(str(auth_response), auth_response)
       else:
         raise PasswordAuthRejected(str(auth_response), auth_response)
-  except stem.socket.ControllerError, exc:
+  except stem.ControllerError, exc:
     try: controller.connect()
     except: pass
     
@@ -534,7 +534,7 @@ def authenticate_cookie(controller, cookie_path, suppress_ctl_errors = True):
   :param controller: tor controller or socket to be authenticated
   :param str cookie_path: path of the authentication cookie to send to tor
   :param bool suppress_ctl_errors: reports raised
-    :class:`~stem.socket.ControllerError` as authentication rejection if
+    :class:`~stem.ControllerError` as authentication rejection if
     **True**, otherwise they're re-raised
   
   :raises:
@@ -568,7 +568,7 @@ def authenticate_cookie(controller, cookie_path, suppress_ctl_errors = True):
         raise IncorrectCookieValue(str(auth_response), cookie_path, False, auth_response)
       else:
         raise CookieAuthRejected(str(auth_response), cookie_path, False, auth_response)
-  except stem.socket.ControllerError, exc:
+  except stem.ControllerError, exc:
     try: controller.connect()
     except: pass
     
@@ -613,7 +613,7 @@ def authenticate_safecookie(controller, cookie_path, suppress_ctl_errors = True)
   :param controller: tor controller or socket to be authenticated
   :param str cookie_path: path of the authentication cookie to send to tor
   :param bool suppress_ctl_errors: reports raised
-    :class:`~stem.socket.ControllerError` as authentication rejection if
+    :class:`~stem.ControllerError` as authentication rejection if
     **True**, otherwise they're re-raised
   
   :raises:
@@ -657,7 +657,7 @@ def authenticate_safecookie(controller, cookie_path, suppress_ctl_errors = True)
         raise CookieAuthRejected(authchallenge_response_str, cookie_path, True)
       else:
         raise AuthChallengeFailed(authchallenge_response, cookie_path)
-  except stem.socket.ControllerError, exc:
+  except stem.ControllerError, exc:
     try: controller.connect()
     except: pass
     
@@ -666,7 +666,7 @@ def authenticate_safecookie(controller, cookie_path, suppress_ctl_errors = True)
   
   try:
     stem.response.convert("AUTHCHALLENGE", authchallenge_response)
-  except stem.socket.ProtocolError, exc:
+  except stem.ProtocolError, exc:
     if not suppress_ctl_errors: raise exc
     else: raise AuthChallengeFailed("Unable to parse AUTHCHALLENGE response: %s" % exc, cookie_path)
   
@@ -680,7 +680,7 @@ def authenticate_safecookie(controller, cookie_path, suppress_ctl_errors = True)
     client_hash = stem.util.connection.hmac_sha256(CLIENT_HASH_CONSTANT,
         cookie_data + client_nonce + authchallenge_response.server_nonce)
     auth_response = _msg(controller, "AUTHENTICATE %s" % (binascii.b2a_hex(client_hash)))
-  except stem.socket.ControllerError, exc:
+  except stem.ControllerError, exc:
     try: controller.connect()
     except: pass
     
@@ -721,9 +721,9 @@ def get_protocolinfo(controller):
   :returns: :class:`~stem.response.protocolinfo.ProtocolInfoResponse` provided by tor
   
   :raises:
-    * :class:`stem.socket.ProtocolError` if the PROTOCOLINFO response is
+    * :class:`stem.ProtocolError` if the PROTOCOLINFO response is
       malformed
-    * :class:`stem.socket.SocketError` if problems arise in establishing or
+    * :class:`stem.SocketError` if problems arise in establishing or
       using the socket
   """
   
@@ -740,8 +740,8 @@ def get_protocolinfo(controller):
     
     try:
       protocolinfo_response = _msg(controller, "PROTOCOLINFO 1")
-    except stem.socket.SocketClosed, exc:
-      raise stem.socket.SocketError(exc)
+    except stem.SocketClosed, exc:
+      raise stem.SocketError(exc)
   
   stem.response.convert("PROTOCOLINFO", protocolinfo_response)
   
diff --git a/stem/control.py b/stem/control.py
index 02afa33..a2d408b 100644
--- a/stem/control.py
+++ b/stem/control.py
@@ -162,11 +162,11 @@ class BaseController(object):
     :returns: :class:`~stem.response.ControlMessage` with the response
     
     :raises:
-      * :class:`stem.socket.ProtocolError` the content from the socket is
+      * :class:`stem.ProtocolError` the content from the socket is
         malformed
-      * :class:`stem.socket.SocketError` if a problem arises in using the
+      * :class:`stem.SocketError` if a problem arises in using the
         socket
-      * :class:`stem.socket.SocketClosed` if the socket is shut down
+      * :class:`stem.SocketClosed` if the socket is shut down
     """
     
     with self._msg_lock:
@@ -191,11 +191,11 @@ class BaseController(object):
         try:
           response = self._reply_queue.get_nowait()
           
-          if isinstance(response, stem.socket.SocketClosed):
+          if isinstance(response, stem.SocketClosed):
             pass # this is fine
-          elif isinstance(response, stem.socket.ProtocolError):
+          elif isinstance(response, stem.ProtocolError):
             log.info("Tor provided a malformed message (%s)" % response)
-          elif isinstance(response, stem.socket.ControllerError):
+          elif isinstance(response, stem.ControllerError):
             log.info("Socket experienced a problem (%s)" % response)
           elif isinstance(response, stem.response.ControlMessage):
             log.notice("BUG: the msg() function failed to deliver a response: %s" % response)
@@ -212,11 +212,11 @@ class BaseController(object):
         # If the message we received back had an exception then re-raise it to the
         # caller. Otherwise return the response.
         
-        if isinstance(response, stem.socket.ControllerError):
+        if isinstance(response, stem.ControllerError):
           raise response
         else:
           return response
-      except stem.socket.SocketClosed, exc:
+      except stem.SocketClosed, exc:
         # If the recv() thread caused the SocketClosed then we could still be
         # in the process of closing. Calling close() here so that we can
         # provide an assurance to the caller that when we raise a SocketClosed
@@ -240,7 +240,7 @@ class BaseController(object):
     Reconnects our control socket. This is a pass-through for our socket's
     :func:`~stem.socket.ControlSocket.connect` method.
     
-    :raises: :class:`stem.socket.SocketError` if unable to make a socket
+    :raises: :class:`stem.SocketError` if unable to make a socket
     """
     
     self._socket.connect()
@@ -432,7 +432,7 @@ class BaseController(object):
         else:
           # response to a msg() call
           self._reply_queue.put(control_message)
-      except stem.socket.ControllerError, exc:
+      except stem.ControllerError, exc:
         # Assume that all exceptions belong to the reader. This isn't always
         # true, but the msg() call can do a better job of sorting it out.
         #
@@ -473,7 +473,7 @@ class Controller(BaseController):
     
     :returns: :class:`~stem.control.Controller` attached to the given port
     
-    :raises: :class:`stem.socket.SocketError` if we're unable to establish a connection
+    :raises: :class:`stem.SocketError` if we're unable to establish a connection
     """
     
     if not stem.util.connection.is_valid_ip_address(control_addr):
@@ -492,7 +492,7 @@ class Controller(BaseController):
     
     :returns: :class:`~stem.control.Controller` attached to the given socket file
     
-    :raises: :class:`stem.socket.SocketError` if we're unable to establish a connection
+    :raises: :class:`stem.SocketError` if we're unable to establish a connection
     """
     
     control_socket = stem.socket.ControlSocketFile(socket_path)
@@ -573,9 +573,9 @@ class Controller(BaseController):
       * default if one was provided and our call failed
     
     :raises:
-      * :class:`stem.socket.ControllerError` if the call fails and we weren't
+      * :class:`stem.ControllerError` if the call fails and we weren't
         provided a default response
-      * :class:`stem.socket.InvalidArguments` if the 'param' requested was
+      * :class:`stem.InvalidArguments` if the 'param' requested was
         invalid
     """
     
@@ -599,7 +599,7 @@ class Controller(BaseController):
         params.remove(param)
       elif param.startswith('ip-to-country/') and self.is_geoip_unavailable():
         # the geoip database aleady looks to be unavailable - abort the request
-        raise stem.socket.ProtocolError("Tor geoip database is unavailable")
+        raise stem.ProtocolError("Tor geoip database is unavailable")
     
     # if everything was cached then short circuit making the query
     if not params:
@@ -631,7 +631,7 @@ class Controller(BaseController):
         return reply
       else:
         return reply.values()[0]
-    except stem.socket.ControllerError, exc:
+    except stem.ControllerError, exc:
       # bump geoip failure count if...
       # * we're caching results
       # * this was soley a geoip lookup
@@ -656,7 +656,7 @@ class Controller(BaseController):
       connected to
     
     :raises:
-      * :class:`stem.socket.ControllerError` if unable to query the version
+      * :class:`stem.ControllerError` if unable to query the version
       * **ValueError** if unable to parse the version
     """
     
@@ -679,7 +679,7 @@ class Controller(BaseController):
     :returns: :class:`~stem.descriptor.server_descriptor.RelayDescriptor` for the given relay
     
     :raises:
-      * :class:`stem.socket.ControllerError` if unable to query the descriptor
+      * :class:`stem.ControllerError` if unable to query the descriptor
       * **ValueError** if **relay** doesn't conform with the pattern for being
         a fingerprint or nickname
     """
@@ -703,7 +703,7 @@ class Controller(BaseController):
       :class:`~stem.descriptor.server_descriptor.RelayDescriptor` for relays in
       the tor network
     
-    :raises: :class:`stem.socket.ControllerError` if unable to query tor
+    :raises: :class:`stem.ControllerError` if unable to query tor
     """
     
     # TODO: We should iterate over the descriptors as they're read from the
@@ -726,7 +726,7 @@ class Controller(BaseController):
       for the given relay
     
     :raises:
-      * :class:`stem.socket.ControllerError` if unable to query the descriptor
+      * :class:`stem.ControllerError` if unable to query the descriptor
       * **ValueError** if **relay** doesn't conform with the patter for being a
         fingerprint or nickname
     """
@@ -750,7 +750,7 @@ class Controller(BaseController):
       :class:`~stem.descriptor.router_status_entry.RouterStatusEntryV2` for
       relays in the tor network
     
-    :raises: :class:`stem.socket.ControllerError` if unable to query tor
+    :raises: :class:`stem.ControllerError` if unable to query tor
     """
     
     # TODO: We should iterate over the descriptors as they're read from the
@@ -783,9 +783,9 @@ class Controller(BaseController):
     :returns: :class:`~stem.response.protocolinfo.ProtocolInfoResponse` provided by tor
     
     :raises:
-      * :class:`stem.socket.ProtocolError` if the PROTOCOLINFO response is
+      * :class:`stem.ProtocolError` if the PROTOCOLINFO response is
         malformed
-      * :class:`stem.socket.SocketError` if problems arise in establishing or
+      * :class:`stem.SocketError` if problems arise in establishing or
         using the socket
     """
     
@@ -814,9 +814,9 @@ class Controller(BaseController):
       * default if one was provided and our call failed
     
     :raises:
-      * :class:`stem.socket.ControllerError` if the call fails and we weren't
+      * :class:`stem.ControllerError` if the call fails and we weren't
         provided a default response
-      * :class:`stem.socket.InvalidArguments` if the configuration option
+      * :class:`stem.InvalidArguments` if the configuration option
         requested was invalid
     """
     
@@ -874,8 +874,8 @@ class Controller(BaseController):
       * default if one was provided and our call failed
     
     :raises:
-      * :class:`stem.socket.ControllerError` if the call fails and we weren't provided a default response
-      * :class:`stem.socket.InvalidArguments` if the configuration option requested was invalid
+      * :class:`stem.ControllerError` if the call fails and we weren't provided a default response
+      * :class:`stem.InvalidArguments` if the configuration option requested was invalid
     """
     
     start_time = time.time()
@@ -941,7 +941,7 @@ class Controller(BaseController):
         return reply
       else:
         return dict([(entry[0], entry[1][0]) for entry in reply.items()])
-    except stem.socket.ControllerError, exc:
+    except stem.ControllerError, exc:
       log.debug("GETCONF %s (failed: %s)" % (" ".join(lookup_params), exc))
       
       if default != UNDEFINED: return default
@@ -960,10 +960,10 @@ class Controller(BaseController):
     :param str,list value: value to set the parameter to
     
     :raises:
-      * :class:`stem.socket.ControllerError` if the call fails
-      * :class:`stem.socket.InvalidArguments` if configuration options
+      * :class:`stem.ControllerError` if the call fails
+      * :class:`stem.InvalidArguments` if configuration options
         requested was invalid
-      * :class:`stem.socket.InvalidRequest` if the configuration setting is
+      * :class:`stem.InvalidRequest` if the configuration setting is
         impossible or if there's a syntax error in the configuration values
     """
     
@@ -976,9 +976,9 @@ class Controller(BaseController):
     :param str params: configuration option to be reset
     
     :raises:
-      * :class:`stem.socket.ControllerError` if the call fails
-      * :class:`stem.socket.InvalidArguments` if configuration options requested was invalid
-      * :class:`stem.socket.InvalidRequest` if the configuration setting is
+      * :class:`stem.ControllerError` if the call fails
+      * :class:`stem.InvalidArguments` if configuration options requested was invalid
+      * :class:`stem.InvalidRequest` if the configuration setting is
         impossible or if there's a syntax error in the configuration values
     """
     
@@ -1011,10 +1011,10 @@ class Controller(BaseController):
       defaults if **True**
     
     :raises:
-      * :class:`stem.socket.ControllerError` if the call fails
-      * :class:`stem.socket.InvalidArguments` if configuration options
+      * :class:`stem.ControllerError` if the call fails
+      * :class:`stem.InvalidArguments` if configuration options
         requested was invalid
-      * :class:`stem.socket.InvalidRequest` if the configuration setting is
+      * :class:`stem.InvalidRequest` if the configuration setting is
         impossible or if there's a syntax error in the configuration values
     """
     
@@ -1058,12 +1058,12 @@ class Controller(BaseController):
       if response.code == "552":
         if response.message.startswith("Unrecognized option: Unknown option '"):
           key = response.message[37:response.message.find("\'", 37)]
-          raise stem.socket.InvalidArguments(response.code, response.message, [key])
-        raise stem.socket.InvalidRequest(response.code, response.message)
+          raise stem.InvalidArguments(response.code, response.message, [key])
+        raise stem.InvalidRequest(response.code, response.message)
       elif response.code in ("513", "553"):
-        raise stem.socket.InvalidRequest(response.code, response.message)
+        raise stem.InvalidRequest(response.code, response.message)
       else:
-        raise stem.socket.ProtocolError("Returned unexpected status code: %s" % response.code)
+        raise stem.ProtocolError("Returned unexpected status code: %s" % response.code)
   
   def load_conf(self, configtext):
     """
@@ -1072,7 +1072,7 @@ class Controller(BaseController):
     
     :param str configtext: the configuration text
     
-    :raises: :class:`stem.socket.ControllerError` if the call fails
+    :raises: :class:`stem.ControllerError` if the call fails
     """
     
     response = self.msg("LOADCONF\n%s" % configtext)
@@ -1080,18 +1080,18 @@ class Controller(BaseController):
     
     if response.code in ("552", "553"):
       if response.code == "552" and response.message.startswith("Invalid config file: Failed to parse/validate config: Unknown option"):
-        raise stem.socket.InvalidArguments(response.code, response.message, [response.message[70:response.message.find('.', 70) - 1]])
-      raise stem.socket.InvalidRequest(response.code, response.message)
+        raise stem.InvalidArguments(response.code, response.message, [response.message[70:response.message.find('.', 70) - 1]])
+      raise stem.InvalidRequest(response.code, response.message)
     elif not response.is_ok():
-      raise stem.socket.ProtocolError("+LOADCONF Received unexpected response\n%s" % str(response))
+      raise stem.ProtocolError("+LOADCONF Received unexpected response\n%s" % str(response))
   
   def save_conf(self):
     """
     Saves the current configuration options into the active torrc file.
     
     :raises:
-      * :class:`stem.socket.ControllerError` if the call fails
-      * :class:`stem.socket.OperationFailed` if the client is unable to save
+      * :class:`stem.ControllerError` if the call fails
+      * :class:`stem.OperationFailed` if the client is unable to save
         the configuration file
     """
     
@@ -1101,9 +1101,9 @@ class Controller(BaseController):
     if response.is_ok():
       return True
     elif response.code == "551":
-      raise stem.socket.OperationFailed(response.code, response.message)
+      raise stem.OperationFailed(response.code, response.message)
     else:
-      raise stem.socket.ProtocolError("SAVECONF returned unexpected response code")
+      raise stem.ProtocolError("SAVECONF returned unexpected response code")
   
   def is_feature_enabled(self, feature):
     """
@@ -1148,8 +1148,8 @@ class Controller(BaseController):
     :param str,list features: a single feature or a list of features to be enabled
     
     :raises:
-      * :class:`stem.socket.ControllerError` if the call fails
-      * :class:`stem.socket.InvalidArguments` if features passed were invalid
+      * :class:`stem.ControllerError` if the call fails
+      * :class:`stem.InvalidArguments` if features passed were invalid
     """
     
     if type(features) == str: features = [features]
@@ -1161,9 +1161,9 @@ class Controller(BaseController):
         invalid_feature = []
         if response.message.startswith("Unrecognized feature \""):
           invalid_feature = [response.message[22:response.message.find("\"", 22)]]
-        raise stem.socket.InvalidArguments(response.code, response.message, invalid_feature)
+        raise stem.InvalidArguments(response.code, response.message, invalid_feature)
       
-      raise stem.socket.ProtocolError("USEFEATURE provided an invalid response code: %s" % response.code)
+      raise stem.ProtocolError("USEFEATURE provided an invalid response code: %s" % response.code)
     
     self.enabled_features += [entry.upper() for entry in features]
   
@@ -1184,7 +1184,7 @@ class Controller(BaseController):
         share any circuits with old ones (this also clears our DNS cache)
       * **CLEARDNSCACHE** - clears cached DNS results
     
-    :raises: :class:`stem.socket.InvalidArguments` if signal provided wasn't recognized
+    :raises: :class:`stem.InvalidArguments` if signal provided wasn't recognized
     """
     
     response = self.msg("SIGNAL %s" % signal)
@@ -1192,9 +1192,9 @@ class Controller(BaseController):
     
     if not response.is_ok():
       if response.code == "552":
-        raise stem.socket.InvalidArguments(response.code, response.message, [signal])
+        raise stem.InvalidArguments(response.code, response.message, [signal])
       
-      raise stem.socket.ProtocolError("SIGNAL response contained unrecognized status code: %s" % response.code)
+      raise stem.ProtocolError("SIGNAL response contained unrecognized status code: %s" % response.code)
   
   def repurpose_circuit(self, circuit_id, purpose):
     """
@@ -1205,7 +1205,7 @@ class Controller(BaseController):
     :param int circuit_id: id of the circuit whose purpose is to be changed
     :param str purpose: purpose (either "general" or "controller")
     
-    :raises: :class:`stem.socket.InvalidArguments` if the circuit doesn't exist or if the purpose was invalid
+    :raises: :class:`stem.InvalidArguments` if the circuit doesn't exist or if the purpose was invalid
     """
     
     response = self.msg("SETCIRCUITPURPOSE %s purpose=%s" % (str(circuit_id), purpose))
@@ -1213,9 +1213,9 @@ class Controller(BaseController):
     
     if not response.is_ok():
       if response.code == "552":
-        raise stem.socket.InvalidRequest(response.code, response.message)
+        raise stem.InvalidRequest(response.code, response.message)
       else:
-        raise stem.socket.ProtocolError("SETCIRCUITPURPOSE returned unexpected response code: %s" % response.code)
+        raise stem.ProtocolError("SETCIRCUITPURPOSE returned unexpected response code: %s" % response.code)
   
   def new_circuit(self, path = None, purpose = "general"):
     """
@@ -1244,7 +1244,7 @@ class Controller(BaseController):
     
     :returns: int of the circuit id of the created or extended circuit
     
-    :raises: :class:`stem.socket.InvalidRequest` if one of the parameters were invalid
+    :raises: :class:`stem.InvalidRequest` if one of the parameters were invalid
     """
     
     args = [str(circuit)]
@@ -1260,11 +1260,11 @@ class Controller(BaseController):
         extended, new_circuit = response.message.split(" ")
         assert extended == "EXTENDED"
       except:
-        raise stem.socket.ProtocolError("EXTENDCIRCUIT response invalid:\n%s", str(response))
+        raise stem.ProtocolError("EXTENDCIRCUIT response invalid:\n%s", str(response))
     elif response.code == '552':
-      raise stem.socket.InvalidRequest(response.code, response.message)
+      raise stem.InvalidRequest(response.code, response.message)
     else:
-      raise stem.socket.ProtocolError("EXTENDCIRCUIT returned unexpected response code: %s" % response.code)
+      raise stem.ProtocolError("EXTENDCIRCUIT returned unexpected response code: %s" % response.code)
     
     return int(new_circuit)
   
@@ -1281,8 +1281,8 @@ class Controller(BaseController):
     :param dict mapping: mapping of original addresses to replacement addresses
     
     :raises:
-      * :class:`stem.socket.InvalidRequest` if the addresses are malformed
-      * :class:`stem.socket.OperationFailed` if Tor couldn't fulfill the request
+      * :class:`stem.InvalidRequest` if the addresses are malformed
+      * :class:`stem.OperationFailed` if Tor couldn't fulfill the request
     
     :returns: **dict** with 'original -> replacement' address mappings
     """
diff --git a/stem/response/__init__.py b/stem/response/__init__.py
index fb6c63f..050ba02 100644
--- a/stem/response/__init__.py
+++ b/stem/response/__init__.py
@@ -66,20 +66,20 @@ def convert(response_type, message, **kwargs):
     * AUTHCHALLENGE
     * SINGLELINE
   
-  * **\*** can raise a :class:`stem.socket.InvalidArguments` exception
-  * **^** can raise a :class:`stem.socket.InvalidRequest` exception
-  * **&** can raise a :class:`stem.socket.OperationFailed` exception
+  * **\*** can raise a :class:`stem.InvalidArguments` exception
+  * **^** can raise a :class:`stem.InvalidRequest` exception
+  * **&** can raise a :class:`stem.OperationFailed` exception
   
   :param str response_type: type of tor response to convert to
   :param stem.response.ControlMessage message: message to be converted
   :param kwargs: optional keyword arguments to be passed to the parser method
   
   :raises:
-    * :class:`stem.socket.ProtocolError` the message isn't a proper response of
+    * :class:`stem.ProtocolError` the message isn't a proper response of
       that type
-    * :class:`stem.socket.InvalidArguments` the arguments given as input are
+    * :class:`stem.InvalidArguments` the arguments given as input are
       invalid
-    * :class:`stem.socket.InvalidRequest` the arguments given as input are
+    * :class:`stem.InvalidRequest` the arguments given as input are
       invalid
     * **TypeError** if argument isn't a :class:`~stem.response.ControlMessage`
       or response_type isn't supported
@@ -471,9 +471,9 @@ class SingleLineResponse(ControlMessage):
     content = self.content()
     
     if len(content) > 1:
-      raise stem.socket.ProtocolError("Received multi-line response")
+      raise stem.ProtocolError("Received multi-line response")
     elif len(content) == 0:
-      raise stem.socket.ProtocolError("Received empty response")
+      raise stem.ProtocolError("Received empty response")
     else:
       self.code, _, self.message = content[0]
 
diff --git a/stem/response/authchallenge.py b/stem/response/authchallenge.py
index fa60339..6cc22f9 100644
--- a/stem/response/authchallenge.py
+++ b/stem/response/authchallenge.py
@@ -20,33 +20,33 @@ class AuthChallengeResponse(stem.response.ControlMessage):
     self.server_nonce = None
     
     if not self.is_ok():
-      raise stem.socket.ProtocolError("AUTHCHALLENGE response didn't have an OK status:\n%s" % self)
+      raise stem.ProtocolError("AUTHCHALLENGE response didn't have an OK status:\n%s" % self)
     elif len(self) > 1:
-      raise stem.socket.ProtocolError("Received multiline AUTHCHALLENGE response:\n%s" % self)
+      raise stem.ProtocolError("Received multiline AUTHCHALLENGE response:\n%s" % self)
     
     line = self[0]
     
     # sanity check that we're a AUTHCHALLENGE response
     if not line.pop() == "AUTHCHALLENGE":
-      raise stem.socket.ProtocolError("Message is not an AUTHCHALLENGE response (%s)" % self)
+      raise stem.ProtocolError("Message is not an AUTHCHALLENGE response (%s)" % self)
     
     if line.is_next_mapping("SERVERHASH"):
       value = line.pop_mapping()[1]
       
       if not stem.util.tor_tools.is_hex_digits(value, 64):
-        raise stem.socket.ProtocolError("SERVERHASH has an invalid value: %s" % value)
+        raise stem.ProtocolError("SERVERHASH has an invalid value: %s" % value)
       
       self.server_hash = binascii.a2b_hex(value)
     else:
-      raise stem.socket.ProtocolError("Missing SERVERHASH mapping: %s" % line)
+      raise stem.ProtocolError("Missing SERVERHASH mapping: %s" % line)
     
     if line.is_next_mapping("SERVERNONCE"):
       value = line.pop_mapping()[1]
       
       if not stem.util.tor_tools.is_hex_digits(value, 64):
-        raise stem.socket.ProtocolError("SERVERNONCE has an invalid value: %s" % value)
+        raise stem.ProtocolError("SERVERNONCE has an invalid value: %s" % value)
       
       self.server_nonce = binascii.a2b_hex(value)
     else:
-      raise stem.socket.ProtocolError("Missing SERVERNONCE mapping: %s" % line)
+      raise stem.ProtocolError("Missing SERVERNONCE mapping: %s" % line)
 
diff --git a/stem/response/getconf.py b/stem/response/getconf.py
index 6d396b8..889a587 100644
--- a/stem/response/getconf.py
+++ b/stem/response/getconf.py
@@ -31,10 +31,10 @@ class GetConfResponse(stem.response.ControlMessage):
           unrecognized_keywords.append(line[32:-1])
       
       if unrecognized_keywords:
-        raise stem.socket.InvalidArguments("552", "GETCONF request contained unrecognized keywords: %s" \
+        raise stem.InvalidArguments("552", "GETCONF request contained unrecognized keywords: %s" \
             % ', '.join(unrecognized_keywords), unrecognized_keywords)
       else:
-        raise stem.socket.ProtocolError("GETCONF response contained a non-OK status code:\n%s" % self)
+        raise stem.ProtocolError("GETCONF response contained a non-OK status code:\n%s" % self)
     
     while remaining_lines:
       line = remaining_lines.pop(0)
diff --git a/stem/response/getinfo.py b/stem/response/getinfo.py
index ddedc34..fb967d7 100644
--- a/stem/response/getinfo.py
+++ b/stem/response/getinfo.py
@@ -31,23 +31,23 @@ class GetInfoResponse(stem.response.ControlMessage):
           unrecognized_keywords.append(line[18:-1])
       
       if unrecognized_keywords:
-        raise stem.socket.InvalidArguments("552", "GETINFO request contained unrecognized keywords: %s\n" \
+        raise stem.InvalidArguments("552", "GETINFO request contained unrecognized keywords: %s\n" \
             % ', '.join(unrecognized_keywords), unrecognized_keywords)
       else:
-        raise stem.socket.ProtocolError("GETINFO response didn't have an OK status:\n%s" % self)
+        raise stem.ProtocolError("GETINFO response didn't have an OK status:\n%s" % self)
     
     while remaining_lines:
       try:
         key, value = remaining_lines.pop(0).split("=", 1)
       except ValueError:
-        raise stem.socket.ProtocolError("GETINFO replies should only contain parameter=value mappings:\n%s" % self)
+        raise stem.ProtocolError("GETINFO replies should only contain parameter=value mappings:\n%s" % self)
       
       # if the value is a multiline value then it *must* be of the form
       # '<key>=\n<value>'
       
       if "\n" in value:
         if not value.startswith("\n"):
-          raise stem.socket.ProtocolError("GETINFO response contained a multi-line value that didn't start with a newline:\n%s" % self)
+          raise stem.ProtocolError("GETINFO response contained a multi-line value that didn't start with a newline:\n%s" % self)
         
         value = value[1:]
       
@@ -60,7 +60,7 @@ class GetInfoResponse(stem.response.ControlMessage):
     :param set params: parameters to assert that we contain
     
     :raises:
-      * :class:`stem.socket.ProtocolError` if parameters don't match this response
+      * :class:`stem.ProtocolError` if parameters don't match this response
     """
     
     reply_params = set(self.entries.keys())
@@ -69,5 +69,5 @@ class GetInfoResponse(stem.response.ControlMessage):
       requested_label = ", ".join(params)
       reply_label = ", ".join(reply_params)
       
-      raise stem.socket.ProtocolError("GETINFO reply doesn't match the parameters that we requested. Queried '%s' but got '%s'." % (requested_label, reply_label))
+      raise stem.ProtocolError("GETINFO reply doesn't match the parameters that we requested. Queried '%s' but got '%s'." % (requested_label, reply_label))
 
diff --git a/stem/response/mapaddress.py b/stem/response/mapaddress.py
index d4e33de..b2be32e 100644
--- a/stem/response/mapaddress.py
+++ b/stem/response/mapaddress.py
@@ -9,8 +9,8 @@ class MapAddressResponse(stem.response.ControlMessage):
   :var dict entries: mapping between the original and replacement addresses
   
   :raises:
-    * :class:`stem.socket.OperationFailed` if Tor was unable to satisfy the request
-    * :class:`stem.socket.InvalidRequest` if the addresses provided were invalid
+    * :class:`stem.OperationFailed` if Tor was unable to satisfy the request
+    * :class:`stem.InvalidRequest` if the addresses provided were invalid
   """
   
   def _parse_message(self):
@@ -21,11 +21,11 @@ class MapAddressResponse(stem.response.ControlMessage):
     if not self.is_ok():
       for code, _, message in self.content():
         if code == "512":
-          raise stem.socket.InvalidRequest(code, message)
+          raise stem.InvalidRequest(code, message)
         elif code == "451":
-          raise stem.socket.OperationFailed(code, message)
+          raise stem.OperationFailed(code, message)
         else:
-          raise stem.socket.ProtocolError("MAPADDRESS returned unexpected response code: %s", code)
+          raise stem.ProtocolError("MAPADDRESS returned unexpected response code: %s", code)
     
     self.entries = {}
     
@@ -35,5 +35,5 @@ class MapAddressResponse(stem.response.ControlMessage):
           key, value = message.split("=", 1)
           self.entries[key] = value
         except ValueError:
-          raise stem.socket.ProtocolError(None, "MAPADDRESS returned '%s', which isn't a mapping" % message)
+          raise stem.ProtocolError(None, "MAPADDRESS returned '%s', which isn't a mapping" % message)
 
diff --git a/stem/response/protocolinfo.py b/stem/response/protocolinfo.py
index 258c5b6..d696a4d 100644
--- a/stem/response/protocolinfo.py
+++ b/stem/response/protocolinfo.py
@@ -36,11 +36,11 @@ class ProtocolInfoResponse(stem.response.ControlMessage):
     remaining_lines = list(self)
     
     if not self.is_ok() or not remaining_lines.pop() == "OK":
-      raise stem.socket.ProtocolError("PROTOCOLINFO response didn't have an OK status:\n%s" % self)
+      raise stem.ProtocolError("PROTOCOLINFO response didn't have an OK status:\n%s" % self)
     
     # sanity check that we're a PROTOCOLINFO response
     if not remaining_lines[0].startswith("PROTOCOLINFO"):
-      raise stem.socket.ProtocolError("Message is not a PROTOCOLINFO response:\n%s" % self)
+      raise stem.ProtocolError("Message is not a PROTOCOLINFO response:\n%s" % self)
     
     while remaining_lines:
       line = remaining_lines.pop(0)
@@ -52,12 +52,12 @@ class ProtocolInfoResponse(stem.response.ControlMessage):
         #   PIVERSION = 1*DIGIT
         
         if line.is_empty():
-          raise stem.socket.ProtocolError("PROTOCOLINFO response's initial line is missing the protocol version: %s" % line)
+          raise stem.ProtocolError("PROTOCOLINFO response's initial line is missing the protocol version: %s" % line)
         
         try:
           self.protocol_version = int(line.pop())
         except ValueError:
-          raise stem.socket.ProtocolError("PROTOCOLINFO response version is non-numeric: %s" % line)
+          raise stem.ProtocolError("PROTOCOLINFO response version is non-numeric: %s" % line)
         
         # The piversion really should be "1" but, according to the spec, tor
         # does not necessarily need to provide the PROTOCOLINFO version that we
@@ -75,7 +75,7 @@ class ProtocolInfoResponse(stem.response.ControlMessage):
         
         # parse AuthMethod mapping
         if not line.is_next_mapping("METHODS"):
-          raise stem.socket.ProtocolError("PROTOCOLINFO response's AUTH line is missing its mandatory 'METHODS' mapping: %s" % line)
+          raise stem.ProtocolError("PROTOCOLINFO response's AUTH line is missing its mandatory 'METHODS' mapping: %s" % line)
         
         for method in line.pop_mapping()[1].split(","):
           if method == "NULL":
@@ -105,12 +105,12 @@ class ProtocolInfoResponse(stem.response.ControlMessage):
         #   TorVersion = QuotedString
         
         if not line.is_next_mapping("Tor", True):
-          raise stem.socket.ProtocolError("PROTOCOLINFO response's VERSION line is missing its mandatory tor version mapping: %s" % line)
+          raise stem.ProtocolError("PROTOCOLINFO response's VERSION line is missing its mandatory tor version mapping: %s" % line)
         
         try:
           self.tor_version = stem.version.Version(line.pop_mapping(True)[1])
         except ValueError, exc:
-          raise stem.socket.ProtocolError(exc)
+          raise stem.ProtocolError(exc)
       else:
         log.debug("Unrecognized PROTOCOLINFO line type '%s', ignoring it: %s" % (line_type, line))
     
diff --git a/stem/socket.py b/stem/socket.py
index 2b13466..6528f97 100644
--- a/stem/socket.py
+++ b/stem/socket.py
@@ -25,15 +25,6 @@ as instances of the :class:`~stem.response.ControlMessage` class.
   send_message - Writes a message to a control socket.
   recv_message - Reads a ControlMessage from a control socket.
   send_formatting - Performs the formatting expected from sent messages.
-  
-  ControllerError - Base exception raised when using the controller.
-    |- ProtocolError - Malformed socket data.
-    |- OperationFailed - Tor was unable to successfully complete the operation.
-    |  |- UnsatisfiableRequest - Tor was unable to satisfy a valid request.
-    |  +- InvalidRequest - Invalid request.
-    |     +- InvalidArguments - Invalid request parameters.
-    +- SocketError - Communication with the socket failed.
-       +- SocketClosed - Socket has been shut down.
 """
 
 from __future__ import with_statement
@@ -77,15 +68,15 @@ class ControlSocket(object):
     :param bool raw: leaves the message formatting untouched, passing it to the socket as-is
     
     :raises:
-      * :class:`stem.socket.SocketError` if a problem arises in using the socket
-      * :class:`stem.socket.SocketClosed` if the socket is known to be shut down
+      * :class:`stem.SocketError` if a problem arises in using the socket
+      * :class:`stem.SocketClosed` if the socket is known to be shut down
     """
     
     with self._send_lock:
       try:
-        if not self.is_alive(): raise SocketClosed()
+        if not self.is_alive(): raise stem.SocketClosed()
         send_message(self._socket_file, message, raw)
-      except SocketClosed, exc:
+      except stem.SocketClosed, exc:
         # if send_message raises a SocketClosed then we should properly shut
         # everything down
         if self.is_alive(): self.close()
@@ -99,8 +90,8 @@ class ControlSocket(object):
     :returns: :class:`~stem.response.ControlMessage` for the message received
     
     :raises:
-      * :class:`stem.socket.ProtocolError` the content from the socket is malformed
-      * :class:`stem.socket.SocketClosed` if the socket closes before we receive a complete message
+      * :class:`stem.ProtocolError` the content from the socket is malformed
+      * :class:`stem.SocketClosed` if the socket closes before we receive a complete message
     """
     
     with self._recv_lock:
@@ -110,9 +101,9 @@ class ControlSocket(object):
         
         socket_file = self._socket_file
         
-        if not socket_file: raise SocketClosed()
+        if not socket_file: raise stem.SocketClosed()
         return recv_message(socket_file)
-      except SocketClosed, exc:
+      except stem.SocketClosed, exc:
         # If recv_message raises a SocketClosed then we should properly shut
         # everything down. However, there's a couple cases where this will
         # cause deadlock...
@@ -159,7 +150,7 @@ class ControlSocket(object):
     Connects to a new socket, closing our previous one if we're already
     attached.
     
-    :raises: :class:`stem.socket.SocketError` if unable to make a socket
+    :raises: :class:`stem.SocketError` if unable to make a socket
     """
     
     with self._send_lock:
@@ -181,7 +172,7 @@ class ControlSocket(object):
         
         try:
           self._connect()
-        except SocketError:
+        except stem.SocketError:
           self._connect() # single retry
   
   def close(self):
@@ -261,7 +252,7 @@ class ControlSocket(object):
     :returns: **socket.socket** for our configuration
     
     :raises:
-      * :class:`stem.socket.SocketError` if unable to make a socket
+      * :class:`stem.SocketError` if unable to make a socket
       * **NotImplementedError** if not implemented by a subclass
     """
     
@@ -281,7 +272,7 @@ class ControlPort(ControlSocket):
     :param int control_port: port number of the controller
     :param bool connect: connects to the socket if True, leaves it unconnected otherwise
     
-    :raises: :class:`stem.socket.SocketError` if connect is **True** and we're
+    :raises: :class:`stem.SocketError` if connect is **True** and we're
       unable to establish a connection
     """
     
@@ -315,7 +306,7 @@ class ControlPort(ControlSocket):
       control_socket.connect((self._control_addr, self._control_port))
       return control_socket
     except socket.error, exc:
-      raise SocketError(exc)
+      raise stem.SocketError(exc)
 
 class ControlSocketFile(ControlSocket):
   """
@@ -330,7 +321,7 @@ class ControlSocketFile(ControlSocket):
     :param str socket_path: path where the control socket is located
     :param bool connect: connects to the socket if True, leaves it unconnected otherwise
     
-    :raises: :class:`stem.socket.SocketError` if connect is **True** and we're
+    :raises: :class:`stem.SocketError` if connect is **True** and we're
       unable to establish a connection
     """
     
@@ -354,7 +345,7 @@ class ControlSocketFile(ControlSocket):
       control_socket.connect(self._socket_path)
       return control_socket
     except socket.error, exc:
-      raise SocketError(exc)
+      raise stem.SocketError(exc)
 
 def send_message(control_file, message, raw = False):
   """
@@ -384,8 +375,8 @@ def send_message(control_file, message, raw = False):
     socket as-is
   
   :raises:
-    * :class:`stem.socket.SocketError` if a problem arises in using the socket
-    * :class:`stem.socket.SocketClosed` if the socket is known to be shut down
+    * :class:`stem.SocketError` if a problem arises in using the socket
+    * :class:`stem.SocketClosed` if the socket is known to be shut down
   """
   
   if not raw: message = send_formatting(message)
@@ -404,15 +395,15 @@ def send_message(control_file, message, raw = False):
     # Just accounting for known disconnection responses.
     
     if str(exc) == "[Errno 32] Broken pipe":
-      raise SocketClosed(exc)
+      raise stem.SocketClosed(exc)
     else:
-      raise SocketError(exc)
+      raise stem.SocketError(exc)
   except AttributeError:
     # if the control_file has been closed then flush will receive:
     # AttributeError: 'NoneType' object has no attribute 'sendall'
     
     log.info("Failed to send message: file has been closed")
-    raise SocketClosed("file has been closed")
+    raise stem.SocketClosed("file has been closed")
 
 def recv_message(control_file):
   """
@@ -425,8 +416,8 @@ def recv_message(control_file):
   :returns: :class:`~stem.response.ControlMessage` read from the socket
   
   :raises:
-    * :class:`stem.socket.ProtocolError` the content from the socket is malformed
-    * :class:`stem.socket.SocketClosed` if the socket closes before we receive
+    * :class:`stem.ProtocolError` the content from the socket is malformed
+    * :class:`stem.SocketClosed` if the socket closes before we receive
       a complete message
   """
   
@@ -441,14 +432,14 @@ def recv_message(control_file):
       
       prefix = logging_prefix % "SocketClosed"
       log.info(prefix + "socket file has been closed")
-      raise SocketClosed("socket file has been closed")
+      raise stem.SocketClosed("socket file has been closed")
     except socket.error, exc:
       # when disconnected we get...
       # socket.error: [Errno 107] Transport endpoint is not connected
       
       prefix = logging_prefix % "SocketClosed"
       log.info(prefix + "received exception \"%s\"" % exc)
-      raise SocketClosed(exc)
+      raise stem.SocketClosed(exc)
     
     raw_content += line
     
@@ -461,19 +452,19 @@ def recv_message(control_file):
       
       prefix = logging_prefix % "SocketClosed"
       log.info(prefix + "empty socket content")
-      raise SocketClosed("Received empty socket content.")
+      raise stem.SocketClosed("Received empty socket content.")
     elif len(line) < 4:
       prefix = logging_prefix % "ProtocolError"
       log.info(prefix + "line too short, \"%s\"" % log.escape(line))
-      raise ProtocolError("Badly formatted reply line: too short")
+      raise stem.ProtocolError("Badly formatted reply line: too short")
     elif not re.match(r'^[a-zA-Z0-9]{3}[-+ ]', line):
       prefix = logging_prefix % "ProtocolError"
       log.info(prefix + "malformed status code/divider, \"%s\"" % log.escape(line))
-      raise ProtocolError("Badly formatted reply line: beginning is malformed")
+      raise stem.ProtocolError("Badly formatted reply line: beginning is malformed")
     elif not line.endswith("\r\n"):
       prefix = logging_prefix % "ProtocolError"
       log.info(prefix + "no CRLF linebreak, \"%s\"" % log.escape(line))
-      raise ProtocolError("All lines should end with CRLF")
+      raise stem.ProtocolError("All lines should end with CRLF")
     
     line = line[:-2] # strips off the CRLF
     status_code, divider, content = line[:3], line[3], line[4:]
@@ -498,14 +489,14 @@ def recv_message(control_file):
         except socket.error, exc:
           prefix = logging_prefix % "SocketClosed"
           log.info(prefix + "received an exception while mid-way through a data reply (exception: \"%s\", read content: \"%s\")" % (exc, log.escape(raw_content)))
-          raise SocketClosed(exc)
+          raise stem.SocketClosed(exc)
         
         raw_content += line
         
         if not line.endswith("\r\n"):
           prefix = logging_prefix % "ProtocolError"
           log.info(prefix + "CRLF linebreaks missing from a data reply, \"%s\"" % log.escape(raw_content))
-          raise ProtocolError("All lines should end with CRLF")
+          raise stem.ProtocolError("All lines should end with CRLF")
         elif line == ".\r\n":
           break # data block termination
         
@@ -527,7 +518,7 @@ def recv_message(control_file):
       # be safe...
       prefix = logging_prefix % "ProtocolError"
       log.warn(prefix + "\"%s\" isn't a recognized divider type" % line)
-      raise ProtocolError("Unrecognized divider type '%s': %s" % (divider, line))
+      raise stem.ProtocolError("Unrecognized divider type '%s': %s" % (divider, line))
 
 def send_formatting(message):
   """
@@ -557,53 +548,3 @@ def send_formatting(message):
   else:
     return message + "\r\n"
 
-class ControllerError(Exception):
-  "Base error for controller communication issues."
-
-class ProtocolError(ControllerError):
-  "Malformed content from the control socket."
-
-class OperationFailed(ControllerError):
-  """
-  Base exception class for failed operations that return an error code
-  
-  :var str code: error code returned by Tor
-  :var str message: error message returned by Tor or a human readable error
-    message
-  """
-  
-  def __init__(self, code = None, message = None):
-    super(ControllerError, self).__init__(message)
-    self.code = code
-    self.message = message
-
-class UnsatisfiableRequest(OperationFailed):
-  """
-  Exception raised if Tor was unable to process our request.
-  """
-
-class InvalidRequest(OperationFailed):
-  """
-  Exception raised when the request was invalid or malformed.
-  """
-
-class InvalidArguments(InvalidRequest):
-  """
-  Exception class for requests which had invalid arguments.
-  
-  :var str code: error code returned by Tor
-  :var str message: error message returned by Tor or a human readable error
-    message
-  :var list arguments: a list of arguments which were invalid
-  """
-  
-  def __init__(self, code = None, message = None, arguments = None):
-    super(InvalidArguments, self).__init__(code, message)
-    self.arguments = arguments
-
-class SocketError(ControllerError):
-  "Error arose while communicating with the control socket."
-
-class SocketClosed(SocketError):
-  "Control socket was closed before completing the message."
-
diff --git a/test/integ/connection/authentication.py b/test/integ/connection/authentication.py
index 8c5c06d..f811917 100644
--- a/test/integ/connection/authentication.py
+++ b/test/integ/connection/authentication.py
@@ -137,7 +137,7 @@ class TestAuthenticate(unittest.TestCase):
     
     try:
       control_socket = stem.socket.ControlPort(control_port = test.runner.CONTROL_PORT)
-    except stem.socket.SocketError:
+    except stem.SocketError:
       # assert that we didn't have a socket to connect to
       self.assertFalse(test.runner.Torrc.PORT in tor_options)
       return
diff --git a/test/integ/control/base_controller.py b/test/integ/control/base_controller.py
index 22cd7a8..eebb788 100644
--- a/test/integ/control/base_controller.py
+++ b/test/integ/control/base_controller.py
@@ -108,7 +108,7 @@ class TestBaseController(unittest.TestCase):
             controller.msg("GETINFO version")
             controller.msg("GETINFO blarg")
             controller.msg("blarg")
-          except stem.socket.ControllerError:
+          except stem.ControllerError:
             pass
       
       message_threads = []
@@ -213,7 +213,7 @@ class TestBaseController(unittest.TestCase):
       
       # cause the socket to shut down without calling close()
       controller.msg("Blarg!")
-      self.assertRaises(stem.socket.SocketClosed, controller.msg, "blarg")
+      self.assertRaises(stem.SocketClosed, controller.msg, "blarg")
       self.assertEquals(controller, state_observer.controller)
       self.assertEquals(stem.control.State.CLOSED, state_observer.state)
       self.assertTrue(state_observer.timestamp < time.time())
diff --git a/test/integ/control/controller.py b/test/integ/control/controller.py
index 2f7d15c..c1bdda8 100644
--- a/test/integ/control/controller.py
+++ b/test/integ/control/controller.py
@@ -32,7 +32,7 @@ class TestController(unittest.TestCase):
       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)
+      self.assertRaises(stem.SocketError, stem.control.Controller.from_port, "127.0.0.1", test.runner.CONTROL_PORT)
   
   def test_from_socket_file(self):
     """
@@ -45,7 +45,7 @@ class TestController(unittest.TestCase):
       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)
+      self.assertRaises(stem.SocketError, stem.control.Controller.from_socket_file, test.runner.CONTROL_SOCKET_PATH)
   
   def test_getinfo(self):
     """
@@ -75,12 +75,12 @@ class TestController(unittest.TestCase):
       
       # non-existant option
       
-      self.assertRaises(stem.socket.ControllerError, controller.get_info, "blarg")
+      self.assertRaises(stem.ControllerError, controller.get_info, "blarg")
       self.assertEqual("ho hum", controller.get_info("blarg", "ho hum"))
       
       # empty input
       
-      self.assertRaises(stem.socket.ControllerError, controller.get_info, "")
+      self.assertRaises(stem.ControllerError, controller.get_info, "")
       self.assertEqual("ho hum", controller.get_info("", "ho hum"))
       
       self.assertEqual({}, controller.get_info([]))
@@ -175,12 +175,12 @@ class TestController(unittest.TestCase):
       self.assertEqual(set(request_params), set(reply_params))
       
       # non-existant option(s)
-      self.assertRaises(stem.socket.InvalidArguments, controller.get_conf, "blarg")
+      self.assertRaises(stem.InvalidArguments, controller.get_conf, "blarg")
       self.assertEqual("la-di-dah", controller.get_conf("blarg", "la-di-dah"))
-      self.assertRaises(stem.socket.InvalidArguments, controller.get_conf_map, "blarg")
+      self.assertRaises(stem.InvalidArguments, controller.get_conf_map, "blarg")
       self.assertEqual("la-di-dah", controller.get_conf_map("blarg", "la-di-dah"))
       
-      self.assertRaises(stem.socket.InvalidRequest, controller.get_conf_map, ["blarg", "huadf"], multiple = True)
+      self.assertRaises(stem.InvalidRequest, controller.get_conf_map, ["blarg", "huadf"], multiple = True)
       self.assertEqual("la-di-dah", controller.get_conf_map(["erfusdj", "afiafj"], "la-di-dah", multiple = True))
       
       # multivalue configuration keys
@@ -227,7 +227,7 @@ class TestController(unittest.TestCase):
         try:
           controller.set_conf("invalidkeyboo", "abcde")
           self.fail()
-        except stem.socket.InvalidArguments, exc:
+        except stem.InvalidArguments, exc:
           self.assertEqual(["invalidkeyboo"], exc.arguments)
         
         # resets configuration parameters
@@ -251,7 +251,7 @@ class TestController(unittest.TestCase):
             "bombay": "vadapav",
           })
           self.fail()
-        except stem.socket.InvalidArguments, exc:
+        except stem.InvalidArguments, exc:
           self.assertEqual(["bombay"], exc.arguments)
         
         # context-sensitive keys (the only retched things for which order matters)
@@ -289,11 +289,11 @@ class TestController(unittest.TestCase):
       
       try:
         # invalid requests
-        self.assertRaises(stem.socket.InvalidRequest, controller.load_conf, "ContactInfo confloaded")
+        self.assertRaises(stem.InvalidRequest, controller.load_conf, "ContactInfo confloaded")
         try:
           controller.load_conf("Blahblah blah")
           self.fail()
-        except stem.socket.InvalidArguments, exc:
+        except stem.InvalidArguments, exc:
           self.assertEqual(["Blahblah"], exc.arguments)
         
         # valid config
@@ -345,10 +345,10 @@ class TestController(unittest.TestCase):
       
       self.assertTrue(re.match("\$[0-9a-fA-F]{40}[~=].*", controller.get_info('orconn-status').split()[0]))
       self.assertTrue("VERBOSE_NAMES" in controller.enabled_features)
-      self.assertRaises(stem.socket.InvalidArguments, controller.enable_feature, ["NOT", "A", "FEATURE"])
+      self.assertRaises(stem.InvalidArguments, controller.enable_feature, ["NOT", "A", "FEATURE"])
       try:
         controller.enable_feature(["NOT", "A", "FEATURE"])
-      except stem.socket.InvalidArguments, exc:
+      except stem.InvalidArguments, exc:
         self.assertEqual(["NOT"], exc.arguments)
       else: self.fail()
   
@@ -364,7 +364,7 @@ class TestController(unittest.TestCase):
       controller.signal("CLEARDNSCACHE")
       
       # invalid signals
-      self.assertRaises(stem.socket.InvalidArguments, controller.signal, "FOOBAR")
+      self.assertRaises(stem.InvalidArguments, controller.signal, "FOOBAR")
   
   def test_extendcircuit(self):
     if test.runner.require_control(self): return
@@ -377,9 +377,9 @@ class TestController(unittest.TestCase):
       circ_id = controller.new_circuit()
       self.assertTrue(filter(lambda x: int(x.split()[0]) == circ_id, controller.get_info('circuit-status').splitlines()))
       
-      self.assertRaises(stem.socket.InvalidRequest, controller.extend_circuit, "foo")
-      self.assertRaises(stem.socket.InvalidRequest, controller.extend_circuit, 0, "thisroutershouldntexistbecausestemexists!@##$%#")
-      self.assertRaises(stem.socket.InvalidRequest, controller.extend_circuit, 0, "thisroutershouldntexistbecausestemexists!@##$%#", "foo")
+      self.assertRaises(stem.InvalidRequest, controller.extend_circuit, "foo")
+      self.assertRaises(stem.InvalidRequest, controller.extend_circuit, 0, "thisroutershouldntexistbecausestemexists!@##$%#")
+      self.assertRaises(stem.InvalidRequest, controller.extend_circuit, 0, "thisroutershouldntexistbecausestemexists!@##$%#", "foo")
   
   def test_repurpose_circuit(self):
     """
@@ -403,8 +403,8 @@ class TestController(unittest.TestCase):
       circ = filter(re.compile("^%i " % circ_id).match, circuit_output.splitlines())[0]
       self.assertTrue("PURPOSE=GENERAL" in circ)
       
-      self.assertRaises(stem.socket.InvalidRequest, controller.repurpose_circuit, 'f934h9f3h4', "fooo")
-      self.assertRaises(stem.socket.InvalidRequest, controller.repurpose_circuit, '4', "fooo")
+      self.assertRaises(stem.InvalidRequest, controller.repurpose_circuit, 'f934h9f3h4', "fooo")
+      self.assertRaises(stem.InvalidRequest, controller.repurpose_circuit, '4', "fooo")
   
   def test_mapaddress(self):
     if test.runner.require_control(self): return
@@ -448,8 +448,8 @@ class TestController(unittest.TestCase):
       self.assertRaises(ValueError, controller.get_server_descriptor, "z" * 30)
       
       # try with a relay that doesn't exist
-      self.assertRaises(stem.socket.ControllerError, controller.get_server_descriptor, "blargg")
-      self.assertRaises(stem.socket.ControllerError, controller.get_server_descriptor, "5" * 40)
+      self.assertRaises(stem.ControllerError, controller.get_server_descriptor, "blargg")
+      self.assertRaises(stem.ControllerError, controller.get_server_descriptor, "5" * 40)
       
       first_descriptor = None
       with stem.descriptor.reader.DescriptorReader([descriptor_path]) as reader:
@@ -505,8 +505,8 @@ class TestController(unittest.TestCase):
       self.assertRaises(ValueError, controller.get_network_status, "z" * 30)
       
       # try with a relay that doesn't exist
-      self.assertRaises(stem.socket.ControllerError, controller.get_network_status, "blargg")
-      self.assertRaises(stem.socket.ControllerError, controller.get_network_status, "5" * 40)
+      self.assertRaises(stem.ControllerError, controller.get_network_status, "blargg")
+      self.assertRaises(stem.ControllerError, controller.get_network_status, "5" * 40)
       
       # our cached consensus is v3 but the control port can only be queried for
       # v2 or v1 network status information
diff --git a/test/integ/socket/control_message.py b/test/integ/socket/control_message.py
index cb2fe52..af6af16 100644
--- a/test/integ/socket/control_message.py
+++ b/test/integ/socket/control_message.py
@@ -36,23 +36,23 @@ class TestControlMessage(unittest.TestCase):
     # checked in more depth by the ControlSocket integ tests.
     
     self.assertTrue(control_socket.is_alive())
-    self.assertRaises(stem.socket.SocketClosed, control_socket.recv)
+    self.assertRaises(stem.SocketClosed, control_socket.recv)
     self.assertFalse(control_socket.is_alive())
     
     # Additional socket usage should fail, and pulling more responses will fail
     # with more closed exceptions.
     
-    self.assertRaises(stem.socket.SocketError, control_socket.send, "GETINFO version")
-    self.assertRaises(stem.socket.SocketClosed, control_socket.recv)
-    self.assertRaises(stem.socket.SocketClosed, control_socket.recv)
-    self.assertRaises(stem.socket.SocketClosed, control_socket.recv)
+    self.assertRaises(stem.SocketError, control_socket.send, "GETINFO version")
+    self.assertRaises(stem.SocketClosed, control_socket.recv)
+    self.assertRaises(stem.SocketClosed, control_socket.recv)
+    self.assertRaises(stem.SocketClosed, control_socket.recv)
     
     # The socket connection is already broken so calling close shouldn't have
     # an impact.
     
     control_socket.close()
-    self.assertRaises(stem.socket.SocketClosed, control_socket.send, "GETINFO version")
-    self.assertRaises(stem.socket.SocketClosed, control_socket.recv)
+    self.assertRaises(stem.SocketClosed, control_socket.send, "GETINFO version")
+    self.assertRaises(stem.SocketClosed, control_socket.recv)
   
   def test_invalid_command(self):
     """
diff --git a/test/integ/socket/control_socket.py b/test/integ/socket/control_socket.py
index ad253d1..a775b20 100644
--- a/test/integ/socket/control_socket.py
+++ b/test/integ/socket/control_socket.py
@@ -49,7 +49,7 @@ class TestControlSocket(unittest.TestCase):
       control_socket.close()
       self.assertFalse(control_socket.is_alive())
       
-      self.assertRaises(stem.socket.SocketClosed, control_socket.send, "blarg")
+      self.assertRaises(stem.SocketClosed, control_socket.send, "blarg")
   
   def test_send_disconnected(self):
     """
@@ -75,7 +75,7 @@ class TestControlSocket(unittest.TestCase):
         control_socket.send("blarg")
         self.assertTrue(control_socket.is_alive())
       else:
-        self.assertRaises(stem.socket.SocketClosed, control_socket.send, "blarg")
+        self.assertRaises(stem.SocketClosed, control_socket.send, "blarg")
         self.assertFalse(control_socket.is_alive())
   
   def test_recv_closed(self):
@@ -90,7 +90,7 @@ class TestControlSocket(unittest.TestCase):
       control_socket.close()
       self.assertFalse(control_socket.is_alive())
       
-      self.assertRaises(stem.socket.SocketClosed, control_socket.recv)
+      self.assertRaises(stem.SocketClosed, control_socket.recv)
   
   def test_recv_disconnected(self):
     """
@@ -109,7 +109,7 @@ class TestControlSocket(unittest.TestCase):
       # however.
       
       self.assertTrue(control_socket.is_alive())
-      self.assertRaises(stem.socket.SocketClosed, control_socket.recv)
+      self.assertRaises(stem.SocketClosed, control_socket.recv)
       self.assertFalse(control_socket.is_alive())
   
   def test_connect_repeatedly(self):
@@ -125,6 +125,6 @@ class TestControlSocket(unittest.TestCase):
         stem.connection.get_protocolinfo(control_socket)
         
         control_socket.close()
-        self.assertRaises(stem.socket.SocketClosed, control_socket.send, "PROTOCOLINFO 1")
+        self.assertRaises(stem.SocketClosed, control_socket.send, "PROTOCOLINFO 1")
         control_socket.connect()
 
diff --git a/test/unit/connection/authentication.py b/test/unit/connection/authentication.py
index 2efcab8..a99651a 100644
--- a/test/unit/connection/authentication.py
+++ b/test/unit/connection/authentication.py
@@ -40,11 +40,11 @@ class TestAuthenticate(unittest.TestCase):
     stem.connection.authenticate(None)
     
     # tests where get_protocolinfo raises an exception
-    raised_exc = stem.socket.ProtocolError(None)
+    raised_exc = stem.ProtocolError(None)
     mocking.mock(stem.connection.get_protocolinfo, mocking.raise_exception(raised_exc))
     self.assertRaises(stem.connection.IncorrectSocketType, stem.connection.authenticate, None)
     
-    raised_exc = stem.socket.SocketError(None)
+    raised_exc = stem.SocketError(None)
     mocking.mock(stem.connection.get_protocolinfo, mocking.raise_exception(raised_exc))
     self.assertRaises(stem.connection.AuthenticationFailure, stem.connection.authenticate, None)
   
@@ -82,9 +82,9 @@ class TestAuthenticate(unittest.TestCase):
     # 'suppress_ctl_errors' is False, so including those
     
     control_exc = (
-      stem.socket.ProtocolError(None),
-      stem.socket.SocketError(None),
-      stem.socket.SocketClosed(None))
+      stem.ProtocolError(None),
+      stem.SocketError(None),
+      stem.SocketClosed(None))
     
     all_auth_none_exc += control_exc
     all_auth_password_exc += control_exc
diff --git a/test/unit/response/authchallenge.py b/test/unit/response/authchallenge.py
index f85856b..5560b03 100644
--- a/test/unit/response/authchallenge.py
+++ b/test/unit/response/authchallenge.py
@@ -50,5 +50,5 @@ class TestAuthChallengeResponse(unittest.TestCase):
       
       remaining_comp = auth_challenge_comp[:i] + auth_challenge_comp[i + 1:]
       control_message = mocking.get_message(' '.join(remaining_comp))
-      self.assertRaises(stem.socket.ProtocolError, stem.response.convert, "AUTHCHALLENGE", control_message)
+      self.assertRaises(stem.ProtocolError, stem.response.convert, "AUTHCHALLENGE", control_message)
 
diff --git a/test/unit/response/control_message.py b/test/unit/response/control_message.py
index b86fc41..68a5c42 100644
--- a/test/unit/response/control_message.py
+++ b/test/unit/response/control_message.py
@@ -111,7 +111,7 @@ class TestControlMessage(unittest.TestCase):
       # replace the CRLF for the line
       infonames_lines[i] = infonames_lines[i].rstrip("\r\n") + "\n"
       test_socket_file = StringIO.StringIO("".join(infonames_lines))
-      self.assertRaises(stem.socket.ProtocolError, stem.socket.recv_message, test_socket_file)
+      self.assertRaises(stem.ProtocolError, stem.socket.recv_message, test_socket_file)
       
       # puts the CRLF back
       infonames_lines[i] = infonames_lines[i].rstrip("\n") + "\r\n"
@@ -136,8 +136,8 @@ class TestControlMessage(unittest.TestCase):
         # - this is part of the message prefix
         # - this is disrupting the line ending
         
-        self.assertRaises(stem.socket.ProtocolError, stem.socket.recv_message, StringIO.StringIO(removal_test_input))
-        self.assertRaises(stem.socket.ProtocolError, stem.socket.recv_message, StringIO.StringIO(replacement_test_input))
+        self.assertRaises(stem.ProtocolError, stem.socket.recv_message, StringIO.StringIO(removal_test_input))
+        self.assertRaises(stem.ProtocolError, stem.socket.recv_message, StringIO.StringIO(replacement_test_input))
       else:
         # otherwise the data will be malformed, but this goes undetected
         self._assert_message_parses(removal_test_input)
@@ -151,7 +151,7 @@ class TestControlMessage(unittest.TestCase):
     
     control_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
     control_socket_file = control_socket.makefile()
-    self.assertRaises(stem.socket.SocketClosed, stem.socket.recv_message, control_socket_file)
+    self.assertRaises(stem.SocketClosed, stem.socket.recv_message, control_socket_file)
   
   def _assert_message_parses(self, controller_reply):
     """
diff --git a/test/unit/response/getconf.py b/test/unit/response/getconf.py
index 58e80d6..70d1239 100644
--- a/test/unit/response/getconf.py
+++ b/test/unit/response/getconf.py
@@ -96,11 +96,11 @@ class TestGetConfResponse(unittest.TestCase):
     """
     
     control_message = mocking.get_message(UNRECOGNIZED_KEY_RESPONSE)
-    self.assertRaises(stem.socket.InvalidArguments, stem.response.convert, "GETCONF", control_message)
+    self.assertRaises(stem.InvalidArguments, stem.response.convert, "GETCONF", control_message)
     
     try:
       stem.response.convert("GETCONF", control_message)
-    except stem.socket.InvalidArguments, exc:
+    except stem.InvalidArguments, exc:
       self.assertEqual(exc.arguments, ["brickroad", "submarine"])
   
   def test_invalid_content(self):
@@ -111,5 +111,5 @@ class TestGetConfResponse(unittest.TestCase):
     """
     
     control_message = mocking.get_message(INVALID_RESPONSE)
-    self.assertRaises(stem.socket.ProtocolError, stem.response.convert, "GETCONF", control_message)
+    self.assertRaises(stem.ProtocolError, stem.response.convert, "GETCONF", control_message)
 
diff --git a/test/unit/response/getinfo.py b/test/unit/response/getinfo.py
index 6d21faf..2a51693 100644
--- a/test/unit/response/getinfo.py
+++ b/test/unit/response/getinfo.py
@@ -111,7 +111,7 @@ class TestGetInfoResponse(unittest.TestCase):
     """
     
     control_message = mocking.get_message(NON_KEY_VALUE_ENTRY)
-    self.assertRaises(stem.socket.ProtocolError, stem.response.convert, "GETINFO", control_message)
+    self.assertRaises(stem.ProtocolError, stem.response.convert, "GETINFO", control_message)
   
   def test_unrecognized_key_response(self):
     """
@@ -119,11 +119,11 @@ class TestGetInfoResponse(unittest.TestCase):
     """
     
     control_message = mocking.get_message(UNRECOGNIZED_KEY_ENTRY)
-    self.assertRaises(stem.socket.InvalidArguments, stem.response.convert, "GETINFO", control_message)
+    self.assertRaises(stem.InvalidArguments, stem.response.convert, "GETINFO", control_message)
     
     try:
       stem.response.convert("GETINFO", control_message)
-    except stem.socket.InvalidArguments, exc:
+    except stem.InvalidArguments, exc:
       self.assertEqual(exc.arguments, ["blackhole"])
   
   def test_invalid_multiline_content(self):
@@ -134,5 +134,5 @@ class TestGetInfoResponse(unittest.TestCase):
     """
     
     control_message = mocking.get_message(MISSING_MULTILINE_NEWLINE)
-    self.assertRaises(stem.socket.ProtocolError, stem.response.convert, "GETINFO", control_message)
+    self.assertRaises(stem.ProtocolError, stem.response.convert, "GETINFO", control_message)
 
diff --git a/test/unit/response/mapaddress.py b/test/unit/response/mapaddress.py
index 3c2a372..2f9949b 100644
--- a/test/unit/response/mapaddress.py
+++ b/test/unit/response/mapaddress.py
@@ -61,7 +61,7 @@ class TestMapAddressResponse(unittest.TestCase):
     """
     
     control_message = mocking.get_message(UNRECOGNIZED_KEYS_RESPONSE)
-    self.assertRaises(stem.socket.InvalidRequest, stem.response.convert, "MAPADDRESS", control_message)
+    self.assertRaises(stem.InvalidRequest, stem.response.convert, "MAPADDRESS", control_message)
     expected = { "23": "324" }
     
     control_message = mocking.get_message(PARTIAL_FAILURE_RESPONSE)
@@ -76,8 +76,8 @@ class TestMapAddressResponse(unittest.TestCase):
     """
     
     control_message = mocking.get_message(INVALID_EMPTY_RESPONSE)
-    self.assertRaises(stem.socket.ProtocolError, stem.response.convert, "MAPADDRESS", control_message)
+    self.assertRaises(stem.ProtocolError, stem.response.convert, "MAPADDRESS", control_message)
     
     control_message = mocking.get_message(INVALID_RESPONSE)
-    self.assertRaises(stem.socket.ProtocolError, stem.response.convert, "MAPADDRESS", control_message)
+    self.assertRaises(stem.ProtocolError, stem.response.convert, "MAPADDRESS", control_message)
 
diff --git a/test/unit/response/protocolinfo.py b/test/unit/response/protocolinfo.py
index 09d4414..7d16075 100644
--- a/test/unit/response/protocolinfo.py
+++ b/test/unit/response/protocolinfo.py
@@ -72,7 +72,7 @@ class TestProtocolInfoResponse(unittest.TestCase):
     
     # attempt to convert a different message type
     bw_event_control_message = mocking.get_message("650 BW 32326 2856")
-    self.assertRaises(stem.socket.ProtocolError, stem.response.convert, "PROTOCOLINFO", bw_event_control_message)
+    self.assertRaises(stem.ProtocolError, stem.response.convert, "PROTOCOLINFO", bw_event_control_message)
   
   def test_no_auth(self):
     """
diff --git a/test/unit/response/singleline.py b/test/unit/response/singleline.py
index aa9c915..0a4e13f 100644
--- a/test/unit/response/singleline.py
+++ b/test/unit/response/singleline.py
@@ -31,5 +31,5 @@ class TestSingleLineResponse(unittest.TestCase):
   
   def test_multi_line_response(self):
     message = mocking.get_message(MULTILINE_RESPONSE)
-    self.assertRaises(stem.socket.ProtocolError, stem.response.convert, "SINGLELINE", message)
+    self.assertRaises(stem.ProtocolError, stem.response.convert, "SINGLELINE", message)
 
diff --git a/test/util.py b/test/util.py
index ddc96f0..90a5551 100644
--- a/test/util.py
+++ b/test/util.py
@@ -1,7 +1,7 @@
 import struct
 import socket
 
-from stem.socket import ProtocolError
+from stem import ProtocolError
 import test.runner
 
 error_msgs = {
@@ -48,7 +48,7 @@ def negotiate_socks(sock, host, port):
   :param str host: host to connect to
   :param int port: port to connect to
   
-  :raises: :class:`stem.socket.ProtocolError` if the socks server doesn't grant our request
+  :raises: :class:`stem.ProtocolError` if the socks server doesn't grant our request
   
   :returns: a list with the IP address and the port that the proxy connected to
   """

_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits