[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