commit 82747342cac4a7204b42928fe3a3f32fadea62c6 Author: Ravi Chandra Padmala neenaoffline@gmail.com 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@lists.torproject.org