commit 1eed64be89d0cf0382234786c020ab4760a4e8e4 Author: Damian Johnson atagar@torproject.org Date: Mon Jan 7 00:00:20 2013 -0800
Conforming to E701 (multiple statements on one line)
Well, that took a while. --- run_tests.py | 18 +++- stem/connection.py | 118 ++++++++++++++------- stem/control.py | 124 +++++++++++++++------- stem/descriptor/__init__.py | 25 +++-- stem/descriptor/extrainfo_descriptor.py | 52 ++++++--- stem/descriptor/networkstatus.py | 52 +++++++--- stem/descriptor/reader.py | 49 ++++++--- stem/descriptor/router_status_entry.py | 68 +++++++++--- stem/descriptor/server_descriptor.py | 69 ++++++++---- stem/exit_policy.py | 23 +++-- stem/process.py | 36 +++++-- stem/response/__init__.py | 13 ++- stem/response/events.py | 4 +- stem/response/getconf.py | 3 +- stem/socket.py | 53 +++++++--- stem/util/conf.py | 55 +++++++--- stem/util/connection.py | 10 ++- stem/util/enum.py | 3 +- stem/util/log.py | 33 ++++-- stem/util/proc.py | 47 ++++++--- stem/util/str_tools.py | 15 ++- stem/util/system.py | 72 +++++++++---- stem/util/term.py | 7 +- stem/util/tor_tools.py | 4 +- stem/version.py | 32 ++++-- test/check_whitespace.py | 6 +- test/integ/connection/authentication.py | 45 +++++--- test/integ/connection/connect.py | 6 +- test/integ/control/base_controller.py | 24 +++-- test/integ/control/controller.py | 145 +++++++++++++++++-------- test/integ/descriptor/extrainfo_descriptor.py | 4 +- test/integ/descriptor/networkstatus.py | 8 +- test/integ/descriptor/reader.py | 45 ++++++-- test/integ/descriptor/server_descriptor.py | 4 +- test/integ/process.py | 22 +++-- test/integ/response/protocolinfo.py | 12 ++- test/integ/socket/control_message.py | 15 ++- test/integ/socket/control_socket.py | 18 ++- test/integ/version.py | 6 +- test/mocking.py | 47 ++++++--- test/output.py | 30 ++++-- test/prompt.py | 8 +- test/runner.py | 26 ++++-- test/unit/descriptor/router_status_entry.py | 3 +- test/unit/exit_policy/policy.py | 3 +- test/unit/util/system.py | 6 +- 46 files changed, 1029 insertions(+), 439 deletions(-)
diff --git a/run_tests.py b/run_tests.py index c17898b..f9b18fc 100755 --- a/run_tests.py +++ b/run_tests.py @@ -208,7 +208,9 @@ def load_user_configuration(test_config): sys.exit(1) else: target_config = test_config.get("target.config", {}).get(target) - if target_config: arg_overrides[target_config] = "true" + + if target_config: + arg_overrides[target_config] = "true" elif opt in ("-l", "--test"): arg_overrides["argument.test"] = arg elif opt in ("-l", "--log"): @@ -304,7 +306,8 @@ if __name__ == '__main__': our_level = stem.util.log.logging_level(CONFIG["argument.log"]) info_level = stem.util.log.logging_level(stem.util.log.INFO)
- if our_level <= info_level: test.output.print_config(test_config) + if our_level <= info_level: + test.output.print_config(test_config)
error_tracker = test.output.ErrorTracker() output_filters = ( @@ -388,7 +391,9 @@ if __name__ == '__main__': skip_targets.append(target)
for target in integ_run_targets: - if target in skip_targets: continue + if target in skip_targets: + continue + error_tracker.set_category(target)
try: @@ -486,8 +491,11 @@ if __name__ == '__main__': print
runtime = time.time() - start_time - if runtime < 1: runtime_label = "(%0.1f seconds)" % runtime - else: runtime_label = "(%i seconds)" % runtime + + if runtime < 1: + runtime_label = "(%0.1f seconds)" % runtime + else: + runtime_label = "(%i seconds)" % runtime
if testing_failed or error_tracker.has_error_occured(): test.output.print_line("TESTING FAILED %s" % runtime_label, *ERROR_ATTR) diff --git a/stem/connection.py b/stem/connection.py index 737776f..0291a82 100644 --- a/stem/connection.py +++ b/stem/connection.py @@ -188,10 +188,13 @@ def _connect(control_socket, password, chroot_path, controller): else: return controller(control_socket) except MissingPassword: - assert password is None, "BUG: authenticate raised MissingPassword despite getting one" + if password is None: + raise ValueError("BUG: authenticate raised MissingPassword despite getting one")
- try: password = getpass.getpass("Controller password: ") - except KeyboardInterrupt: return None + try: + password = getpass.getpass("Controller password: ") + except KeyboardInterrupt: + return None
return _connect(control_socket, password, chroot_path, controller) except AuthenticationFailure, exc: @@ -352,7 +355,8 @@ def authenticate(controller, password = None, chroot_path = None, protocolinfo_r
# iterating over AuthMethods so we can try them in this order for auth_type in (AuthMethod.NONE, AuthMethod.PASSWORD, AuthMethod.SAFECOOKIE, AuthMethod.COOKIE): - if not auth_type in auth_methods: continue + if not auth_type in auth_methods: + continue
try: if auth_type == AuthMethod.NONE: @@ -437,16 +441,22 @@ def authenticate_none(controller, suppress_ctl_errors = True):
# if we got anything but an OK response then error if str(auth_response) != "OK": - try: controller.connect() - except: pass + try: + controller.connect() + except: + pass
raise OpenAuthRejected(str(auth_response), auth_response) except stem.ControllerError, exc: - try: controller.connect() - except: pass + try: + controller.connect() + except: + pass
- if not suppress_ctl_errors: raise exc - else: raise OpenAuthRejected("Socket failed (%s)" % exc) + if not suppress_ctl_errors: + raise exc + else: + raise OpenAuthRejected("Socket failed (%s)" % exc)
def authenticate_password(controller, password, suppress_ctl_errors = True): """ @@ -493,8 +503,10 @@ def authenticate_password(controller, password, suppress_ctl_errors = True):
# if we got anything but an OK response then error if str(auth_response) != "OK": - try: controller.connect() - except: pass + try: + controller.connect() + except: + pass
# all we have to go on is the error message from tor... # Password did not match HashedControlPassword value value from configuration... @@ -505,11 +517,15 @@ def authenticate_password(controller, password, suppress_ctl_errors = True): else: raise PasswordAuthRejected(str(auth_response), auth_response) except stem.ControllerError, exc: - try: controller.connect() - except: pass + try: + controller.connect() + except: + pass
- if not suppress_ctl_errors: raise exc - else: raise PasswordAuthRejected("Socket failed (%s)" % exc) + if not suppress_ctl_errors: + raise exc + else: + raise PasswordAuthRejected("Socket failed (%s)" % exc)
def authenticate_cookie(controller, cookie_path, suppress_ctl_errors = True): """ @@ -564,8 +580,10 @@ def authenticate_cookie(controller, cookie_path, suppress_ctl_errors = True):
# if we got anything but an OK response then error if str(auth_response) != "OK": - try: controller.connect() - except: pass + try: + controller.connect() + except: + pass
# all we have to go on is the error message from tor... # ... Authentication cookie did not match expected value. @@ -577,11 +595,15 @@ def authenticate_cookie(controller, cookie_path, suppress_ctl_errors = True): else: raise CookieAuthRejected(str(auth_response), cookie_path, False, auth_response) except stem.ControllerError, exc: - try: controller.connect() - except: pass + try: + controller.connect() + except: + pass
- if not suppress_ctl_errors: raise exc - else: raise CookieAuthRejected("Socket failed (%s)" % exc, cookie_path, False) + if not suppress_ctl_errors: + raise exc + else: + raise CookieAuthRejected("Socket failed (%s)" % exc, cookie_path, False)
def authenticate_safecookie(controller, cookie_path, suppress_ctl_errors = True): """ @@ -651,10 +673,13 @@ def authenticate_safecookie(controller, cookie_path, suppress_ctl_errors = True) authchallenge_response = _msg(controller, "AUTHCHALLENGE SAFECOOKIE %s" % client_nonce_hex)
if not authchallenge_response.is_ok(): - try: controller.connect() - except: pass + try: + controller.connect() + except: + pass
authchallenge_response_str = str(authchallenge_response) + if "Authentication required." in authchallenge_response_str: raise AuthChallengeUnsupported("SAFECOOKIE authentication isn't supported", cookie_path) elif "AUTHCHALLENGE only supports" in authchallenge_response_str: @@ -666,17 +691,23 @@ def authenticate_safecookie(controller, cookie_path, suppress_ctl_errors = True) else: raise AuthChallengeFailed(authchallenge_response, cookie_path) except stem.ControllerError, exc: - try: controller.connect() - except: pass + try: + controller.connect() + except: + pass
- if not suppress_ctl_errors: raise exc - else: raise AuthChallengeFailed("Socket failed (%s)" % exc, cookie_path, True) + if not suppress_ctl_errors: + raise exc + else: + raise AuthChallengeFailed("Socket failed (%s)" % exc, cookie_path, True)
try: stem.response.convert("AUTHCHALLENGE", authchallenge_response) except stem.ProtocolError, exc: - if not suppress_ctl_errors: raise exc - else: raise AuthChallengeFailed("Unable to parse AUTHCHALLENGE response: %s" % exc, cookie_path) + if not suppress_ctl_errors: + raise exc + else: + raise AuthChallengeFailed("Unable to parse AUTHCHALLENGE response: %s" % exc, cookie_path)
expected_server_hash = stem.util.connection.hmac_sha256( SERVER_HASH_CONSTANT, @@ -689,18 +720,25 @@ 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.ControllerError, exc: - try: controller.connect() - except: pass + try: + controller.connect() + except: + pass
- if not suppress_ctl_errors: raise exc - else: raise CookieAuthRejected("Socket failed (%s)" % exc, cookie_path, True, auth_response) + if not suppress_ctl_errors: + raise exc + else: + raise CookieAuthRejected("Socket failed (%s)" % exc, cookie_path, True, auth_response)
# if we got anything but an OK response then err if not auth_response.is_ok(): - try: controller.connect() - except: pass + try: + controller.connect() + except: + pass
# all we have to go on is the error message from tor... # ... Safe cookie response did not match expected value @@ -841,10 +879,14 @@ def _expand_cookie_path(protocolinfo_response, pid_resolver, pid_resolution_arg) if cookie_path and not os.path.isabs(cookie_path): try: tor_pid = pid_resolver(pid_resolution_arg) - if not tor_pid: raise IOError("pid lookup failed") + + if not tor_pid: + raise IOError("pid lookup failed")
tor_cwd = stem.util.system.get_cwd(tor_pid) - if not tor_cwd: raise IOError("cwd lookup failed") + + if not tor_cwd: + raise IOError("cwd lookup failed")
cookie_path = stem.util.system.expand_path(cookie_path, tor_cwd) except IOError, exc: diff --git a/stem/control.py b/stem/control.py index fc4af05..feb7834 100644 --- a/stem/control.py +++ b/stem/control.py @@ -426,7 +426,8 @@ class BaseController(object): for listener, spawn in self._status_listeners: if listener != callback: new_listeners.append((listener, spawn)) - else: is_changed = True + else: + is_changed = True
self._status_listeners = new_listeners return is_changed @@ -577,7 +578,8 @@ class BaseController(object): event_message = self._event_queue.get_nowait() self._handle_event(event_message) except Queue.Empty: - if not self.is_alive(): break + if not self.is_alive(): + break
self._event_notice.wait() self._event_notice.clear() @@ -656,8 +658,10 @@ class Controller(BaseController): def close(self): # making a best-effort attempt to quit before detaching the socket if self.is_alive(): - try: self.msg("QUIT") - except: pass + try: + self.msg("QUIT") + except: + pass
super(Controller, self).close()
@@ -703,7 +707,9 @@ class Controller(BaseController): is_multiple = False params = set([params]) else: - if not params: return {} + if not params: + return {} + is_multiple = True params = set(params)
@@ -718,14 +724,17 @@ class Controller(BaseController): # the geoip database already looks to be unavailable - abort the request if default == UNDEFINED: raise stem.ProtocolError("Tor geoip database is unavailable") - else: return default + else: + return default
# if everything was cached then short circuit making the query if not params: log.trace("GETINFO %s (cache fetch)" % " ".join(reply.keys()))
- if is_multiple: return reply - else: return reply.values()[0] + if is_multiple: + return reply + else: + return reply.values()[0]
try: response = self.msg("GETINFO %s" % " ".join(params)) @@ -766,8 +775,10 @@ class Controller(BaseController):
log.debug("GETINFO %s (failed: %s)" % (" ".join(params), exc))
- if default == UNDEFINED: raise exc - else: return default + if default == UNDEFINED: + raise exc + else: + return default
def get_version(self, default = UNDEFINED): """ @@ -795,8 +806,10 @@ class Controller(BaseController):
return self._request_cache["version"] except Exception, exc: - if default == UNDEFINED: raise exc - else: return default + if default == UNDEFINED: + raise exc + else: + return default
def get_socks_listeners(self, default = UNDEFINED): """ @@ -845,8 +858,10 @@ class Controller(BaseController):
return [(addr, int(port)) for (addr, port) in proxy_addrs] except Exception, exc: - if default == UNDEFINED: raise exc - else: return default + if default == UNDEFINED: + raise exc + else: + return default
def get_protocolinfo(self, default = UNDEFINED): """ @@ -870,8 +885,10 @@ class Controller(BaseController): try: return stem.connection.get_protocolinfo(self) except Exception, exc: - if default == UNDEFINED: raise exc - else: return default + if default == UNDEFINED: + raise exc + else: + return default
def get_server_descriptor(self, relay, default = UNDEFINED): """ @@ -903,8 +920,10 @@ class Controller(BaseController): desc_content = self.get_info(query) return stem.descriptor.server_descriptor.RelayDescriptor(desc_content) except Exception, exc: - if default == UNDEFINED: raise exc - else: return default + if default == UNDEFINED: + raise exc + else: + return default
def get_server_descriptors(self, default = UNDEFINED): """ @@ -930,7 +949,8 @@ class Controller(BaseController): for desc in stem.descriptor.server_descriptor.parse_file(StringIO.StringIO(desc_content)): yield desc except Exception, exc: - if default == UNDEFINED: raise exc + if default == UNDEFINED: + raise exc else: if entry is not None: for entry in default: @@ -967,8 +987,10 @@ class Controller(BaseController): desc_content = self.get_info(query) return stem.descriptor.router_status_entry.RouterStatusEntryV2(desc_content) except Exception, exc: - if default == UNDEFINED: raise exc - else: return default + if default == UNDEFINED: + raise exc + else: + return default
def get_network_statuses(self, default = UNDEFINED): """ @@ -1000,7 +1022,8 @@ class Controller(BaseController): for desc in desc_iterator: yield desc except Exception, exc: - if default == UNDEFINED: raise exc + if default == UNDEFINED: + raise exc else: if entry is not None: for entry in default: @@ -1104,7 +1127,9 @@ class Controller(BaseController):
# remove strings which contain only whitespace params = filter(lambda entry: entry.strip(), params) - if params == []: return {} + + if params == []: + return {}
# translate context sensitive options lookup_params = set([MAPPED_CONFIG_KEYS.get(entry, entry) for entry in params]) @@ -1154,8 +1179,10 @@ class Controller(BaseController): except stem.ControllerError, exc: log.debug("GETCONF %s (failed: %s)" % (" ".join(lookup_params), exc))
- if default != UNDEFINED: return dict((param, default) for param in params) - else: raise exc + if default != UNDEFINED: + return dict((param, default) for param in params) + else: + raise exc
def _get_conf_dict_to_response(self, config_dict, default, multiple): """ @@ -1467,15 +1494,19 @@ class Controller(BaseController): * :class:`stem.InvalidArguments` if features passed were invalid """
- if isinstance(features, str): features = [features] + if isinstance(features, str): + features = [features] + response = self.msg("USEFEATURE %s" % " ".join(features)) stem.response.convert("SINGLELINE", response)
if not response.is_ok(): if response.code == "552": invalid_feature = [] + if response.message.startswith("Unrecognized feature ""): invalid_feature = [response.message[22:response.message.find(""", 22)]] + raise stem.InvalidArguments(response.code, response.message, invalid_feature)
raise stem.ProtocolError("USEFEATURE provided an invalid response code: %s" % response.code) @@ -1505,8 +1536,10 @@ class Controller(BaseController):
raise ValueError("Tor presently does not have a circuit with the id of '%s'" % circuit_id) except Exception, exc: - if default == UNDEFINED: raise exc - else: return default + if default == UNDEFINED: + raise exc + else: + return default
def get_circuits(self, default = UNDEFINED): """ @@ -1530,8 +1563,10 @@ class Controller(BaseController):
return circuits except Exception, exc: - if default == UNDEFINED: raise exc - else: return default + if default == UNDEFINED: + raise exc + else: + return default
def new_circuit(self, path = None, purpose = "general", await_build = False): """ @@ -1609,9 +1644,15 @@ class Controller(BaseController): raise stem.InvalidRequest(512, "EXTENDCIRCUIT requires the path prior to version %s" % path_opt_version)
args = [circuit_id] - if isinstance(path, str): path = [path] - if path: args.append(",".join(path)) - if purpose: args.append("purpose=%s" % purpose) + + if isinstance(path, str): + path = [path] + + if path: + args.append(",".join(path)) + + if purpose: + args.append("purpose=%s" % purpose)
response = self.msg("EXTENDCIRCUIT %s" % " ".join(args)) stem.response.convert("SINGLELINE", response) @@ -1710,8 +1751,10 @@ class Controller(BaseController):
return streams except Exception, exc: - if default == UNDEFINED: raise exc - else: return default + if default == UNDEFINED: + raise exc + else: + return default
def attach_stream(self, stream_id, circuit_id, exiting_hop = None): """ @@ -1730,7 +1773,10 @@ class Controller(BaseController): """
query = "ATTACHSTREAM %s %s" % (stream_id, circuit_id) - if exiting_hop: query += " HOP=%s" % exiting_hop + + if exiting_hop: + query += " HOP=%s" % exiting_hop + response = self.msg(query) stem.response.convert("SINGLELINE", response)
@@ -1976,5 +2022,7 @@ def _case_insensitive_lookup(entries, key, default = UNDEFINED): if entry.lower() == key.lower(): return entry
- if default != UNDEFINED: return default - else: raise ValueError("key '%s' doesn't exist in dict: %s" % (key, entries)) + if default != UNDEFINED: + return default + else: + raise ValueError("key '%s' doesn't exist in dict: %s" % (key, entries)) diff --git a/stem/descriptor/__init__.py b/stem/descriptor/__init__.py index ed52b42..0dba96c 100644 --- a/stem/descriptor/__init__.py +++ b/stem/descriptor/__init__.py @@ -196,7 +196,8 @@ def _read_until_keywords(keywords, descriptor_file, inclusive = False, ignore_fi content = None if skip else [] ending_keyword = None
- if isinstance(keywords, str): keywords = (keywords,) + if isinstance(keywords, str): + keywords = (keywords,)
if ignore_first: first_line = descriptor_file.readline() @@ -211,7 +212,9 @@ def _read_until_keywords(keywords, descriptor_file, inclusive = False, ignore_fi break
line = descriptor_file.readline() - if not line: break # EOF + + if not line: + break # EOF
line_match = KEYWORD_LINE.match(line)
@@ -314,27 +317,35 @@ def _get_descriptor_components(raw_contents, validate, extra_keywords = ()): # ... and server descriptors end with an extra newline. But other documents # don't say how blank lines should be handled so globally ignoring them.
- if not line: continue + if not line: + continue
# Some lines have an 'opt ' for backward compatibility. They should be # ignored. This prefix is being removed in... # https://trac.torproject.org/projects/tor/ticket/5124
- if line.startswith("opt "): line = line[4:] + if line.startswith("opt "): + line = line[4:]
line_match = KEYWORD_LINE.match(line)
if not line_match: - if not validate: continue + if not validate: + continue + raise ValueError("Line contains invalid characters: %s" % line)
keyword, value = line_match.groups() - if value is None: value = '' + + if value is None: + value = ''
try: block_contents = _get_pseudo_pgp_block(remaining_lines) except ValueError, exc: - if not validate: continue + if not validate: + continue + raise exc
if keyword in extra_keywords: diff --git a/stem/descriptor/extrainfo_descriptor.py b/stem/descriptor/extrainfo_descriptor.py index 7ea457c..2c14c92 100644 --- a/stem/descriptor/extrainfo_descriptor.py +++ b/stem/descriptor/extrainfo_descriptor.py @@ -158,7 +158,8 @@ def parse_file(descriptor_file, validate = True):
if extrainfo_content: yield RelayExtraInfoDescriptor("".join(extrainfo_content), validate) - else: break # done parsing file + else: + break # done parsing file
def _parse_timestamp_and_interval(keyword, content): """ @@ -180,7 +181,9 @@ def _parse_timestamp_and_interval(keyword, content): raise ValueError("Malformed %s line: %s" % (keyword, line))
timestamp_str, interval, remainder = content_match.groups() - if remainder: remainder = remainder[1:] # remove leading space + + if remainder: + remainder = remainder[1:] # remove leading space
if not interval.isdigit(): raise ValueError("%s line's interval wasn't a number: %s" % (keyword, line)) @@ -430,7 +433,9 @@ class ExtraInfoDescriptor(stem.descriptor.Descriptor): extra_info_comp = value.split()
if len(extra_info_comp) < 2: - if not validate: continue + if not validate: + continue + raise ValueError("Extra-info line must have two values: %s" % line)
if validate: @@ -527,8 +532,10 @@ class ExtraInfoDescriptor(stem.descriptor.Descriptor): if value: for entry in value.split(","): if not "=" in entry: - if validate: raise ValueError(error_msg) - else: continue + if validate: + raise ValueError(error_msg) + else: + continue
status, count = entry.split("=", 1)
@@ -562,7 +569,9 @@ class ExtraInfoDescriptor(stem.descriptor.Descriptor): # "<keyword>" num%
try: - if not value.endswith("%"): raise ValueError() + if not value.endswith("%"): + raise ValueError() + percentage = float(value[:-1]) / 100
# Bug lets these be above 100%, however they're soon going away... @@ -593,7 +602,8 @@ class ExtraInfoDescriptor(stem.descriptor.Descriptor):
entries.append(float(entry)) except ValueError: - if validate: raise ValueError("Non-numeric entry in %s listing: %s" % (keyword, line)) + if validate: + raise ValueError("Non-numeric entry in %s listing: %s" % (keyword, line))
if keyword == "cell-processed-cells": self.cell_processed_cells = entries @@ -636,7 +646,8 @@ class ExtraInfoDescriptor(stem.descriptor.Descriptor): self.dir_stats_end = timestamp self.dir_stats_interval = interval except ValueError, exc: - if validate: raise exc + if validate: + raise exc elif keyword == "conn-bi-direct": # "conn-bi-direct" YYYY-MM-DD HH:MM:SS (NSEC s) BELOW,READ,WRITE,BOTH
@@ -655,7 +666,8 @@ class ExtraInfoDescriptor(stem.descriptor.Descriptor): self.conn_bi_direct_write = int(stats[2]) self.conn_bi_direct_both = int(stats[3]) except ValueError, exc: - if validate: raise exc + if validate: + raise exc elif keyword in ("read-history", "write-history", "dirreq-read-history", "dirreq-write-history"): # "<keyword>" YYYY-MM-DD HH:MM:SS (NSEC s) NUM,NUM,NUM,NUM,NUM... try: @@ -685,7 +697,8 @@ class ExtraInfoDescriptor(stem.descriptor.Descriptor): self.dir_write_history_interval = interval self.dir_write_history_values = history_values except ValueError, exc: - if validate: raise exc + if validate: + raise exc elif keyword in ("exit-kibibytes-written", "exit-kibibytes-read", "exit-streams-opened"): # "<keyword>" port=N,port=N,...
@@ -695,13 +708,16 @@ class ExtraInfoDescriptor(stem.descriptor.Descriptor): if value: for entry in value.split(","): if not "=" in entry: - if validate: raise ValueError(error_msg) - else: continue + if validate: + raise ValueError(error_msg) + else: + continue
port, stat = entry.split("=", 1)
if (port == 'other' or stem.util.connection.is_valid_port(port)) and stat.isdigit(): - if port != 'other': port = int(port) + if port != 'other': + port = int(port) port_mappings[port] = int(stat) elif validate: raise ValueError(error_msg) @@ -727,8 +743,10 @@ class ExtraInfoDescriptor(stem.descriptor.Descriptor): if value: for entry in value.split(","): if not "=" in entry: - if validate: raise ValueError(error_msg) - else: continue + if validate: + raise ValueError(error_msg) + else: + continue
locale, count = entry.split("=", 1)
@@ -807,7 +825,9 @@ class RelayExtraInfoDescriptor(ExtraInfoDescriptor): value, block_contents = values[0]
line = "%s %s" % (keyword, value) # original line - if block_contents: line += "\n%s" % block_contents + + if block_contents: + line += "\n%s" % block_contents
if keyword == "router-signature": if validate and not block_contents: diff --git a/stem/descriptor/networkstatus.py b/stem/descriptor/networkstatus.py index 2bdfbc4..28537c2 100644 --- a/stem/descriptor/networkstatus.py +++ b/stem/descriptor/networkstatus.py @@ -303,7 +303,10 @@ class NetworkStatusDocumentV2(NetworkStatusDocument): document_content += "\n" + document_file.read()
entries = stem.descriptor._get_descriptor_components(document_content, validate) - if validate: self._check_constraints(entries) + + if validate: + self._check_constraints(entries) + self._parse(entries, validate)
def _parse(self, entries, validate): @@ -311,11 +314,15 @@ class NetworkStatusDocumentV2(NetworkStatusDocument): value, block_contents = values[0]
line = "%s %s" % (keyword, value) # original line - if block_contents: line += "\n%s" % block_contents + + if block_contents: + line += "\n%s" % block_contents
if keyword == "network-status-version": if not value.isdigit(): - if not validate: continue + if not validate: + continue + raise ValueError("Network status document has a non-numeric version: %s" % line)
self.version = int(value) @@ -326,7 +333,9 @@ class NetworkStatusDocumentV2(NetworkStatusDocument): dir_source_comp = value.split()
if len(dir_source_comp) < 3: - if not validate: continue + if not validate: + continue + raise ValueError("The 'dir-source' line of a v2 network status document must have three values: %s" % line)
if validate: @@ -569,7 +578,9 @@ class _DocumentHeader(object): version, flavor = value, None
if not version.isdigit(): - if not validate: continue + if not validate: + continue + raise ValueError("Network status document has a non-numeric version: %s" % line)
self.version = int(version) @@ -663,11 +674,14 @@ class _DocumentHeader(object): # Parameters ::= Parameter | Parameters SP Parameter
# should only appear in consensus-method 7 or later + if validate and not self.meets_consensus_method(7): raise ValueError("A network status document's 'params' line should only appear in consensus-method 7 or later")
# skip if this is a blank line - if value == "": continue + + if value == "": + continue
self.params.update(_parse_int_mappings(keyword, value, validate))
@@ -769,7 +783,9 @@ class _DocumentFooter(object): elif keyword == "directory-signature": for sig_value, block_contents in values: if not sig_value.count(" ") in (1, 2) or not block_contents: - if not validate: continue + if not validate: + continue + raise ValueError("Authority signatures in a network status document are expected to be of the form 'directory-signature [METHOD] FINGERPRINT KEY_DIGEST\nSIGNATURE', got:\n%s\n%s" % (sig_value, block_contents))
if sig_value.count(" ") == 1: @@ -872,7 +888,9 @@ def _parse_int_mappings(keyword, value, validate): results[entry_key] = entry_value seen_keys.append(entry_key) except ValueError, exc: - if not validate: continue + if not validate: + continue + raise ValueError("Unable to parse network status document's '%s' line (%s): %s'" % (keyword, exc, value))
return results @@ -999,7 +1017,9 @@ class DirectoryAuthority(stem.descriptor.Descriptor): dir_source_comp = value.split(" ")
if len(dir_source_comp) < 6: - if not validate: continue + if not validate: + continue + raise ValueError("Authority entry's 'dir-source' line must have six values: %s" % line)
if validate: @@ -1139,7 +1159,9 @@ class KeyCertificate(stem.descriptor.Descriptor): # "dir-key-certificate-version" version
if not value.isdigit(): - if not validate: continue + if not validate: + continue + raise ValueError("Key certificate has a non-integer version: %s" % line)
self.version = int(value) @@ -1150,7 +1172,9 @@ class KeyCertificate(stem.descriptor.Descriptor): # "dir-address" IPPort
if not ':' in value: - if not validate: continue + if not validate: + continue + raise ValueError("Key certificate's 'dir-address' is expected to be of the form ADDRESS:PORT: %s" % line)
address, dirport = value.split(':', 1) @@ -1255,7 +1279,9 @@ class DocumentSignature(object): return 1
for attr in ("identity", "key_digest", "signature"): - if getattr(self, attr) > getattr(other, attr): return 1 - elif getattr(self, attr) < getattr(other, attr): return -1 + if getattr(self, attr) > getattr(other, attr): + return 1 + elif getattr(self, attr) < getattr(other, attr): + return -1
return 0 diff --git a/stem/descriptor/reader.py b/stem/descriptor/reader.py index d47a5ed..9f9f505 100644 --- a/stem/descriptor/reader.py +++ b/stem/descriptor/reader.py @@ -173,7 +173,8 @@ def load_processed_files(path): for line in input_file.readlines(): line = line.strip()
- if not line: continue # skip blank lines + if not line: + continue # skip blank lines
if not " " in line: raise TypeError("Malformed line: %s" % line) @@ -208,8 +209,11 @@ def save_processed_files(path, processed_files): # makes the parent directory if it doesn't already exist try: path_dir = os.path.dirname(path) - if not os.path.exists(path_dir): os.makedirs(path_dir) - except OSError, exc: raise IOError(exc) + + if not os.path.exists(path_dir): + os.makedirs(path_dir) + except OSError, exc: + raise IOError(exc)
with open(path, "w") as output_file: for path, timestamp in processed_files.items(): @@ -243,8 +247,10 @@ class DescriptorReader(object): """
def __init__(self, target, follow_links = False, buffer_size = 100, persistence_path = None): - if isinstance(target, str): self._targets = [target] - else: self._targets = target + if isinstance(target, str): + self._targets = [target] + else: + self._targets = target
self._follow_links = follow_links self._persistence_path = persistence_path @@ -270,7 +276,8 @@ class DescriptorReader(object): try: processed_files = load_processed_files(self._persistence_path) self.set_processed_files(processed_files) - except: pass + except: + pass
def get_processed_files(self): """ @@ -371,10 +378,12 @@ class DescriptorReader(object): self._iter_notice.set()
# clears our queue to unblock enqueue calls + try: while True: self._unreturned_descriptors.get_nowait() - except Queue.Empty: pass + except Queue.Empty: + pass
self._reader_thread.join() self._reader_thread = None @@ -383,7 +392,8 @@ class DescriptorReader(object): try: processed_files = self.get_processed_files() save_processed_files(self._persistence_path, processed_files) - except: pass + except: + pass
def _read_descriptor_files(self): new_processed_files = {} @@ -419,8 +429,10 @@ class DescriptorReader(object): try: descriptor = self._unreturned_descriptors.get_nowait()
- if descriptor == FINISHED: break - else: yield descriptor + if descriptor == FINISHED: + break + else: + yield descriptor except Queue.Empty: self._iter_notice.wait() self._iter_notice.clear() @@ -431,7 +443,8 @@ class DescriptorReader(object): self._handle_file(os.path.join(root, filename), new_processed_files)
# this can take a while if, say, we're including the root directory - if self._is_stopped.isSet(): return + if self._is_stopped.isSet(): + return
def _handle_file(self, target, new_processed_files): # This is a file. Register its last modified timestamp and check if @@ -452,7 +465,8 @@ class DescriptorReader(object): # Block devices and such are never descriptors, and can cause us to block # for quite a while so skipping anything that isn't a regular file.
- if not os.path.isfile(target): return + if not os.path.isfile(target): + return
# The mimetypes module only checks the file extension. To actually # check the content (like the 'file' command) we'd need something like @@ -483,7 +497,9 @@ class DescriptorReader(object): self._notify_read_listeners(target) with open(target) as target_file: for desc in stem.descriptor.parse_file(target, target_file): - if self._is_stopped.isSet(): return + if self._is_stopped.isSet(): + return + self._unreturned_descriptors.put(desc) self._iter_notice.set() except TypeError, exc: @@ -509,7 +525,9 @@ class DescriptorReader(object): entry = tar_file.extractfile(tar_entry)
for desc in stem.descriptor.parse_file(target, entry): - if self._is_stopped.isSet(): return + if self._is_stopped.isSet(): + return + self._unreturned_descriptors.put(desc) self._iter_notice.set()
@@ -521,7 +539,8 @@ class DescriptorReader(object): except IOError, exc: self._notify_skip_listeners(target, ReadFailed(exc)) finally: - if tar_file: tar_file.close() + if tar_file: + tar_file.close()
def _notify_read_listeners(self, path): for listener in self._read_listeners: diff --git a/stem/descriptor/router_status_entry.py b/stem/descriptor/router_status_entry.py index bc6aa46..6e048dd 100644 --- a/stem/descriptor/router_status_entry.py +++ b/stem/descriptor/router_status_entry.py @@ -83,7 +83,8 @@ def parse_file(document_file, validate, entry_class, entry_keyword = "r", start_ yield entry_class(desc_content, validate, *extra_args)
# check if we stopped at the end of the section - if ending_keyword in section_end_keywords: break + if ending_keyword in section_end_keywords: + break else: break
@@ -139,7 +140,10 @@ class RouterStatusEntry(stem.descriptor.Descriptor): self._unrecognized_lines = []
entries = stem.descriptor._get_descriptor_components(content, validate) - if validate: self._check_constraints(entries) + + if validate: + self._check_constraints(entries) + self._parse(entries, validate)
def _parse(self, entries, validate): @@ -427,7 +431,8 @@ def _parse_r_line(desc, value, validate, include_digest = True): r_comp.insert(2, None)
if len(r_comp) < 8: - if not validate: return + if not validate: + return
expected_field_count = 'eight' if include_digest else 'seven' raise ValueError("%s 'r' line must have %s values: r %s" % (desc._name(), expected_field_count, value)) @@ -446,7 +451,10 @@ def _parse_r_line(desc, value, validate, include_digest = True):
desc.nickname = r_comp[0] desc.fingerprint = _decode_fingerprint(r_comp[1], validate) - if include_digest: desc.digest = r_comp[2] + + if include_digest: + desc.digest = r_comp[2] + desc.address = r_comp[5] desc.or_port = int(r_comp[6]) desc.dir_port = None if r_comp[7] == '0' else int(r_comp[7]) @@ -463,7 +471,9 @@ def _parse_a_line(desc, value, validate): # example: a [2001:888:2133:0:82:94:251:204]:9001
if not ':' in value: - if not validate: return + if not validate: + return + raise ValueError("%s 'a' line must be of the form '[address]:[ports]': a %s" % (desc._name(), value))
address, ports = value.rsplit(':', 1) @@ -481,7 +491,10 @@ def _parse_a_line(desc, value, validate):
if not stem.util.connection.is_valid_port(min_port) or \ not stem.util.connection.is_valid_port(max_port): - if not validate: continue + + if not validate: + continue + raise ValueError("%s 'a' line had an invalid port range (%s): a %s" % (desc._name(), port_entry, value))
desc.addresses_v6.setdefault(address, []).append((int(min_port), int(max_port))) @@ -524,10 +537,14 @@ def _parse_w_line(desc, value, validate): w_comp = value.split(" ")
if len(w_comp) < 1: - if not validate: return + if not validate: + return + raise ValueError("%s 'w' line is blank: w %s" % (desc._name(), value)) elif not w_comp[0].startswith("Bandwidth="): - if not validate: return + if not validate: + return + raise ValueError("%s 'w' line needs to start with a 'Bandwidth=' entry: w %s" % (desc._name(), value))
for w_entry in w_comp: @@ -538,13 +555,17 @@ def _parse_w_line(desc, value, validate):
if w_key == "Bandwidth": if not (w_value and w_value.isdigit()): - if not validate: return + if not validate: + return + raise ValueError("%s 'Bandwidth=' entry needs to have a numeric value: w %s" % (desc._name(), value))
desc.bandwidth = int(w_value) elif w_key == "Measured": if not (w_value and w_value.isdigit()): - if not validate: return + if not validate: + return + raise ValueError("%s 'Measured=' entry needs to have a numeric value: w %s" % (desc._name(), value))
desc.measured = int(w_value) @@ -559,7 +580,9 @@ def _parse_p_line(desc, value, validate): try: desc.exit_policy = stem.exit_policy.MicroExitPolicy(value) except ValueError, exc: - if not validate: return + if not validate: + return + raise ValueError("%s exit policy is malformed (%s): p %s" % (desc._name(), exc, value))
def _parse_m_line(desc, value, validate): @@ -569,25 +592,32 @@ def _parse_m_line(desc, value, validate): m_comp = value.split(" ")
if not (desc.document and desc.document.is_vote): - if not validate: return + if not validate: + return
vote_status = "vote" if desc.document else "<undefined document>" raise ValueError("%s 'm' line should only appear in votes (appeared in a %s): m %s" % (desc._name(), vote_status, value)) elif len(m_comp) < 1: - if not validate: return + if not validate: + return + raise ValueError("%s 'm' line needs to start with a series of methods: m %s" % (desc._name(), value))
try: methods = [int(entry) for entry in m_comp[0].split(",")] except ValueError: - if not validate: return + if not validate: + return + raise ValueError("%s microdescriptor methods should be a series of comma separated integers: m %s" % (desc._name(), value))
hashes = {}
for entry in m_comp[1:]: if not '=' in entry: - if not validate: continue + if not validate: + continue + raise ValueError("%s can only have a series of 'algorithm=digest' mappings after the methods: m %s" % (desc._name(), value))
hash_name, digest = entry.split('=', 1) @@ -622,7 +652,9 @@ def _decode_fingerprint(identity, validate): try: identity_decoded = base64.b64decode(identity) except TypeError: - if not validate: return None + if not validate: + return None + raise ValueError("Unable to decode identity string '%s'" % identity)
for char in identity_decoded: @@ -639,7 +671,9 @@ def _decode_fingerprint(identity, validate): fingerprint += hex(ord(char))[2:].zfill(2).upper()
if not stem.util.tor_tools.is_valid_fingerprint(fingerprint): - if not validate: return None + if not validate: + return None + raise ValueError("Decoded '%s' to be '%s', which isn't a valid fingerprint" % (identity, fingerprint))
return fingerprint diff --git a/stem/descriptor/server_descriptor.py b/stem/descriptor/server_descriptor.py index 1ea13a2..037a4bd 100644 --- a/stem/descriptor/server_descriptor.py +++ b/stem/descriptor/server_descriptor.py @@ -126,7 +126,8 @@ def parse_file(descriptor_file, validate = True):
descriptor_text = "".join(descriptor_content) yield RelayDescriptor(descriptor_text, validate, annotations) - else: break # done parsing descriptors + else: + break # done parsing descriptors
class ServerDescriptor(stem.descriptor.Descriptor): """ @@ -257,7 +258,9 @@ class ServerDescriptor(stem.descriptor.Descriptor):
self.exit_policy = stem.exit_policy.ExitPolicy(*policy) self._parse(entries, validate) - if validate: self._check_constraints(entries) + + if validate: + self._check_constraints(entries)
def digest(self): """ @@ -292,7 +295,8 @@ class ServerDescriptor(stem.descriptor.Descriptor): if " " in line: key, value = line.split(" ", 1) annotation_dict[key] = value - else: annotation_dict[line] = None + else: + annotation_dict[line] = None
self._annotation_dict = annotation_dict
@@ -326,14 +330,18 @@ class ServerDescriptor(stem.descriptor.Descriptor): value, block_contents = values[0]
line = "%s %s" % (keyword, value) # original line - if block_contents: line += "\n%s" % block_contents + + if block_contents: + line += "\n%s" % block_contents
if keyword == "router": # "router" nickname address ORPort SocksPort DirPort router_comp = value.split()
if len(router_comp) < 5: - if not validate: continue + if not validate: + continue + raise ValueError("Router line must have five values: %s" % line)
if validate: @@ -360,17 +368,24 @@ class ServerDescriptor(stem.descriptor.Descriptor): bandwidth_comp = value.split()
if len(bandwidth_comp) < 3: - if not validate: continue + if not validate: + continue + raise ValueError("Bandwidth line must have three values: %s" % line) - - if not bandwidth_comp[0].isdigit(): - if not validate: continue + elif not bandwidth_comp[0].isdigit(): + if not validate: + continue + raise ValueError("Bandwidth line's average rate isn't numeric: %s" % bandwidth_comp[0]) elif not bandwidth_comp[1].isdigit(): - if not validate: continue + if not validate: + continue + raise ValueError("Bandwidth line's burst rate isn't numeric: %s" % bandwidth_comp[1]) elif not bandwidth_comp[2].isdigit(): - if not validate: continue + if not validate: + continue + raise ValueError("Bandwidth line's observed rate isn't numeric: %s" % bandwidth_comp[2])
self.average_bandwidth = int(bandwidth_comp[0]) @@ -395,7 +410,8 @@ class ServerDescriptor(stem.descriptor.Descriptor):
try: self.tor_version = stem.version.Version(version_str) - except ValueError: pass + except ValueError: + pass elif keyword == "published": # "published" YYYY-MM-DD HH:MM:SS
@@ -458,7 +474,9 @@ class ServerDescriptor(stem.descriptor.Descriptor): try: self.uptime = int(value) except ValueError: - if not validate: continue + if not validate: + continue + raise ValueError("Uptime line must have an integer value: %s" % value) elif keyword == "contact": self.contact = value @@ -484,23 +502,31 @@ class ServerDescriptor(stem.descriptor.Descriptor): line = "%s %s" % (keyword, entry)
if not ":" in entry: - if not validate: continue - else: raise ValueError("or-address line missing a colon: %s" % line) + if not validate: + continue + else: + raise ValueError("or-address line missing a colon: %s" % line)
div = entry.rfind(":") address, ports = entry[:div], entry[div + 1:] is_ipv6 = address.startswith("[") and address.endswith("]") - if is_ipv6: address = address[1:-1] # remove brackets + + if is_ipv6: + address = address[1:-1] # remove brackets
if not ((not is_ipv6 and stem.util.connection.is_valid_ip_address(address)) or (is_ipv6 and stem.util.connection.is_valid_ipv6_address(address))): - if not validate: continue - else: raise ValueError("or-address line has a malformed address: %s" % line) + if not validate: + continue + else: + raise ValueError("or-address line has a malformed address: %s" % line)
for port in ports.split(","): if not stem.util.connection.is_valid_port(port): - if not validate: break - else: raise ValueError("or-address line has malformed ports: %s" % line) + if not validate: + break + else: + raise ValueError("or-address line has malformed ports: %s" % line)
self.address_alt.append((address, int(port), is_ipv6)) elif keyword in ("read-history", "write-history"): @@ -525,7 +551,8 @@ class ServerDescriptor(stem.descriptor.Descriptor): self.write_history_interval = interval self.write_history_values = history_values except ValueError, exc: - if validate: raise exc + if validate: + raise exc else: self._unrecognized_lines.append(line)
diff --git a/stem/exit_policy.py b/stem/exit_policy.py index 9b0a111..56c68dc 100644 --- a/stem/exit_policy.py +++ b/stem/exit_policy.py @@ -171,11 +171,14 @@ class ExitPolicy(object): display_ports, skip_ports = [], set()
for rule in self._get_rules(): - if not rule.is_address_wildcard(): continue - elif rule.is_port_wildcard(): break + if not rule.is_address_wildcard(): + continue + elif rule.is_port_wildcard(): + break
for port in xrange(rule.min_port, rule.max_port + 1): - if port in skip_ports: continue + if port in skip_ports: + continue
# if accept + white-list or reject + blacklist then add if rule.is_accept == is_whitelist: @@ -447,9 +450,11 @@ class ExitPolicyRule(object): address_type = self.get_address_type()
if stem.util.connection.is_valid_ip_address(address): - if address_type == AddressType.IPv6: return False + if address_type == AddressType.IPv6: + return False elif stem.util.connection.is_valid_ipv6_address(address, allow_brackets = True): - if address_type == AddressType.IPv4: return False + if address_type == AddressType.IPv4: + return False
address = address.lstrip("[").rstrip("]") else: @@ -468,7 +473,9 @@ class ExitPolicyRule(object): else: comparison_addr_bin = int(stem.util.connection.get_address_binary(address), 2) comparison_addr_bin &= self._get_mask_bin() - if self._get_address_bin() != comparison_addr_bin: return False + + if self._get_address_bin() != comparison_addr_bin: + return False
if not self.is_port_wildcard(): if port is None: @@ -510,7 +517,9 @@ class ExitPolicyRule(object): elif address_type == AddressType.IPv6: mask = stem.util.connection.get_mask_ipv6(self._masked_bits)
- if not cache: return mask + if not cache: + return mask + self._mask = mask
return self._mask diff --git a/stem/process.py b/stem/process.py index 4db51d3..e654e85 100644 --- a/stem/process.py +++ b/stem/process.py @@ -82,7 +82,9 @@ def launch_tor(tor_cmd = "tor", args = None, torrc_path = None, completion_perce
# starts a tor subprocess, raising an OSError if it fails runtime_args, temp_file = [tor_cmd], None - if args: runtime_args += args + + if args: + runtime_args += args
if torrc_path: if torrc_path == NO_TORRC: @@ -100,8 +102,10 @@ def launch_tor(tor_cmd = "tor", args = None, torrc_path = None, completion_perce def timeout_handler(signum, frame): # terminates the uninitialized tor process and raise on timeout if temp_file: - try: os.remove(temp_file) - except: pass + try: + os.remove(temp_file) + except: + pass
# We can't kill the subprocess on python 2.5 running Windows without the # win32process module... @@ -126,7 +130,8 @@ def launch_tor(tor_cmd = "tor", args = None, torrc_path = None, completion_perce
# this will provide empty results if the process is terminated if not init_line: - if timeout: signal.alarm(0) # stop alarm + if timeout: + signal.alarm(0) # stop alarm
# ... but best make sure if stem.prereq.is_python_26(): @@ -137,25 +142,32 @@ def launch_tor(tor_cmd = "tor", args = None, torrc_path = None, completion_perce raise OSError("Process terminated: %s" % last_problem)
# provide the caller with the initialization message if they want it - if init_msg_handler: init_msg_handler(init_line) + + if init_msg_handler: + init_msg_handler(init_line)
# return the process if we're done with bootstrapping bootstrap_match = bootstrap_line.search(init_line) problem_match = problem_line.search(init_line)
if bootstrap_match and int(bootstrap_match.groups()[0]) >= completion_percent: - if timeout: signal.alarm(0) # stop alarm + if timeout: + signal.alarm(0) # stop alarm
if temp_file: - try: os.remove(temp_file) - except: pass + try: + os.remove(temp_file) + except: + pass
return tor_process elif problem_match: runlevel, msg = problem_match.groups()
if not "see warnings above" in msg: - if ": " in msg: msg = msg.split(": ")[-1].strip() + if ": " in msg: + msg = msg.split(": ")[-1].strip() + last_problem = msg
def launch_tor_with_config(config, tor_cmd = "tor", completion_percent = 100, init_msg_handler = None, timeout = DEFAULT_INIT_TIMEOUT, take_ownership = False): @@ -213,8 +225,10 @@ def launch_tor_with_config(config, tor_cmd = "tor", completion_percent = 100, in
return launch_tor(tor_cmd, args, torrc_path, completion_percent, init_msg_handler, timeout, take_ownership) finally: - try: os.remove(torrc_path) - except: pass + try: + os.remove(torrc_path) + except: + pass
def _get_pid(): return str(os.getpid()) diff --git a/stem/response/__init__.py b/stem/response/__init__.py index 388d755..dbf50f9 100644 --- a/stem/response/__init__.py +++ b/stem/response/__init__.py @@ -137,7 +137,8 @@ class ControlMessage(object): """
for code, _, _ in self._parsed_content: - if code == "250": return True + if code == "250": + return True
return False
@@ -367,7 +368,9 @@ class ControlLine(str): """
with self._remainder_lock: - if self.is_empty(): raise IndexError("no remaining content to parse") + if self.is_empty(): + raise IndexError("no remaining content to parse") + key_match = KEY_ARG.match(self._remainder)
if not key_match: @@ -411,8 +414,10 @@ def _parse_entry(line, quoted, escaped): next_entry, remainder = remainder[1:end_quote], remainder[end_quote + 1:] else: # non-quoted value, just need to check if there's more data afterward - if " " in remainder: next_entry, remainder = remainder.split(" ", 1) - else: next_entry, remainder = remainder, "" + if " " in remainder: + next_entry, remainder = remainder.split(" ", 1) + else: + next_entry, remainder = remainder, ""
if escaped: for esc_sequence, replacement in CONTROL_ESCAPES.items(): diff --git a/stem/response/events.py b/stem/response/events.py index 7ba077f..51aa3d2 100644 --- a/stem/response/events.py +++ b/stem/response/events.py @@ -103,7 +103,9 @@ class Event(stem.response.ControlMessage): raise stem.ProtocolError("The %s value should be quoted, but didn't have an ending quote: %s" % (attr_name, self))
attr_values.append(positional.pop(0)) - if attr_values[-1].endswith('"'): break + + if attr_values[-1].endswith('"'): + break
attr_value = " ".join(attr_values)[1:-1] else: diff --git a/stem/response/getconf.py b/stem/response/getconf.py index bf16ec1..c8b7da3 100644 --- a/stem/response/getconf.py +++ b/stem/response/getconf.py @@ -22,7 +22,8 @@ class GetConfResponse(stem.response.ControlMessage): self.entries = {} remaining_lines = list(self)
- if self.content() == [("250", " ", "OK")]: return + if self.content() == [("250", " ", "OK")]: + return
if not self.is_ok(): unrecognized_keywords = [] diff --git a/stem/socket.py b/stem/socket.py index 4dca361..b23b247 100644 --- a/stem/socket.py +++ b/stem/socket.py @@ -75,12 +75,17 @@ class ControlSocket(object):
with self._send_lock: try: - if not self.is_alive(): raise stem.SocketClosed() + if not self.is_alive(): + raise stem.SocketClosed() + send_message(self._socket_file, message, raw) except stem.SocketClosed, exc: # if send_message raises a SocketClosed then we should properly shut # everything down - if self.is_alive(): self.close() + + if self.is_alive(): + self.close() + raise exc
def recv(self): @@ -102,7 +107,9 @@ class ControlSocket(object):
socket_file = self._socket_file
- if not socket_file: raise stem.SocketClosed() + if not socket_file: + raise stem.SocketClosed() + return recv_message(socket_file) except stem.SocketClosed, exc: # If recv_message raises a SocketClosed then we should properly shut @@ -168,7 +175,8 @@ class ControlSocket(object): # longer alive it'll be safe to acquire the recv lock because recv() # calls no longer block (raising SocketClosed instead).
- if self.is_alive(): self.close() + if self.is_alive(): + self.close()
with self._recv_lock: self._socket = self._make_socket() @@ -200,20 +208,26 @@ class ControlSocket(object): # if we haven't yet established a connection then this raises an error # socket.error: [Errno 107] Transport endpoint is not connected
- try: self._socket.shutdown(socket.SHUT_RDWR) - except socket.error: pass + try: + self._socket.shutdown(socket.SHUT_RDWR) + except socket.error: + pass
# Suppressing unexpected exceptions from close. For instance, if the # socket's file has already been closed then with python 2.7 that raises # with... # error: [Errno 32] Broken pipe
- try: self._socket.close() - except: pass + try: + self._socket.close() + except: + pass
if self._socket_file: - try: self._socket_file.close() - except: pass + try: + self._socket_file.close() + except: + pass
self._socket = None self._socket_file = None @@ -290,7 +304,8 @@ class ControlPort(ControlSocket): self._control_addr = control_addr self._control_port = control_port
- if connect: self.connect() + if connect: + self.connect()
def get_address(self): """ @@ -341,7 +356,8 @@ class ControlSocketFile(ControlSocket): super(ControlSocketFile, self).__init__() self._socket_path = socket_path
- if connect: self.connect() + if connect: + self.connect()
def get_socket_path(self): """ @@ -395,7 +411,8 @@ def send_message(control_file, message, raw = False): * :class:`stem.SocketClosed` if the socket is known to be shut down """
- if not raw: message = send_formatting(message) + if not raw: + message = send_formatting(message)
try: control_file.write(message) @@ -441,7 +458,8 @@ def recv_message(control_file): logging_prefix = "Error while receiving a control message (%s): "
while True: - try: line = control_file.readline() + try: + line = control_file.readline() except AttributeError: # if the control_file has been closed then we will receive: # AttributeError: 'NoneType' object has no attribute 'recv' @@ -501,7 +519,8 @@ def recv_message(control_file): # get a line with just a period
while True: - try: line = control_file.readline() + try: + line = control_file.readline() 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))) @@ -520,7 +539,9 @@ def recv_message(control_file):
# lines starting with a period are escaped by a second period (as per # section 2.4 of the control-spec) - if line.startswith(".."): line = line[1:] + + if line.startswith(".."): + line = line[1:]
# appends to previous content, using a newline rather than CRLF # separator (more conventional for multi-line string content outside diff --git a/stem/util/conf.py b/stem/util/conf.py index 0166ad9..57f1fda 100644 --- a/stem/util/conf.py +++ b/stem/util/conf.py @@ -169,11 +169,15 @@ class _SyncListener(object): def update(self, config, key): if key in self.config_dict: new_value = config.get(key, self.config_dict[key]) - if new_value == self.config_dict[key]: return # no change + + if new_value == self.config_dict[key]: + return # no change
if self.interceptor: interceptor_value = self.interceptor(key, new_value) - if interceptor_value: new_value = interceptor_value + + if interceptor_value: + new_value = interceptor_value
self.config_dict[key] = new_value
@@ -219,7 +223,9 @@ def get_config(handle): :param str handle: unique identifier used to access this config instance """
- if not handle in CONFS: CONFS[handle] = Config() + if not handle in CONFS: + CONFS[handle] = Config() + return CONFS[handle]
def parse_enum(key, value, enumeration): @@ -265,7 +271,9 @@ def parse_enum_csv(key, value, enumeration, count = None): """
values = [val.upper().strip() for val in value.split(',')] - if values == ['']: return [] + + if values == ['']: + return []
if count is None: pass # no count validateion checks to do @@ -415,7 +423,10 @@ class Config(object):
# strips any commenting or excess whitespace comment_start = line.find("#") - if comment_start != -1: line = line[:comment_start] + + if comment_start != -1: + line = line[:comment_start] + line = line.strip()
# parse the key/value pair @@ -463,7 +474,8 @@ class Config(object): for entry_key in sorted(self.keys()): for entry_value in self.get_value(entry_key, multiple = True): # check for multi line entries - if "\n" in entry_value: entry_value = "\n|" + entry_value.replace("\n", "\n|") + if "\n" in entry_value: + entry_value = "\n|" + entry_value.replace("\n", "\n|")
output_file.write('%s %s\n' % (entry_key, entry_value))
@@ -535,16 +547,21 @@ class Config(object):
with self._contents_lock: if isinstance(value, str): - if not overwrite and key in self._contents: self._contents[key].append(value) - else: self._contents[key] = [value] + if not overwrite and key in self._contents: + self._contents[key].append(value) + else: + self._contents[key] = [value]
- for listener in self._listeners: listener(self, key) + for listener in self._listeners: + listener(self, key) elif isinstance(value, (list, tuple)): if not overwrite and key in self._contents: self._contents[key] += value - else: self._contents[key] = value + else: + self._contents[key] = value
- for listener in self._listeners: listener(self, key) + for listener in self._listeners: + listener(self, key) else: raise ValueError("Config.set() only accepts str, list, or tuple. Provided value was a '%s'" % type(value))
@@ -588,21 +605,27 @@ class Config(object):
is_multivalue = isinstance(default, (list, tuple, dict)) val = self.get_value(key, default, is_multivalue) - if val == default: return val # don't try to infer undefined values + + if val == default: + return val # don't try to infer undefined values
if isinstance(default, bool): - if val.lower() == "true": val = True - elif val.lower() == "false": val = False + if val.lower() == "true": + val = True + elif val.lower() == "false": + val = False else: log.debug("Config entry '%s' is expected to be a boolean, defaulting to '%s'" % (key, str(default))) val = default elif isinstance(default, int): - try: val = int(val) + try: + val = int(val) except ValueError: log.debug("Config entry '%s' is expected to be an integer, defaulting to '%i'" % (key, default)) val = default elif isinstance(default, float): - try: val = float(val) + try: + val = float(val) except ValueError: log.debug("Config entry '%s' is expected to be a float, defaulting to '%f'" % (key, default)) val = default diff --git a/stem/util/connection.py b/stem/util/connection.py index 3b16c1f..6892bed 100644 --- a/stem/util/connection.py +++ b/stem/util/connection.py @@ -39,10 +39,13 @@ def is_valid_ip_address(address): :returns: **True** if input is a valid IPv4 address, **False** otherwise """
- if not isinstance(address, str): return False + if not isinstance(address, str): + return False
# checks if theres four period separated values - if address.count(".") != 3: return False + + if address.count(".") != 3: + return False
# checks that each value in the octet are decimal values between 0-255 for entry in address.split("."): @@ -110,7 +113,8 @@ def is_valid_port(entry, allow_zero = False):
entry = int(entry)
- if allow_zero and entry == 0: return True + if allow_zero and entry == 0: + return True
return entry > 0 and entry < 65536
diff --git a/stem/util/enum.py b/stem/util/enum.py index e07772d..d22cd22 100644 --- a/stem/util/enum.py +++ b/stem/util/enum.py @@ -73,7 +73,8 @@ class Enum(object): key, val = entry, stem.util.str_tools.to_camel_case(entry) elif isinstance(entry, tuple) and len(entry) == 2: key, val = entry - else: raise ValueError("Unrecognized input: %s" % args) + else: + raise ValueError("Unrecognized input: %s" % args)
keys.append(key) values.append(val) diff --git a/stem/util/log.py b/stem/util/log.py index c2f7912..14b09df 100644 --- a/stem/util/log.py +++ b/stem/util/log.py @@ -78,7 +78,8 @@ DEDUPLICATION_MESSAGE_IDS = set() # http://docs.python.org/release/3.1.3/library/logging.html#configuring-loggin...
class _NullHandler(logging.Handler): - def emit(self, record): pass + def emit(self, record): + pass
if not LOGGER.handlers: LOGGER.addHandler(_NullHandler()) @@ -99,8 +100,10 @@ def logging_level(runlevel): :param stem.util.log.Runlevel runlevel: runlevel to be returned, no logging if **None** """
- if runlevel: return LOG_VALUES[runlevel] - else: return logging.FATAL + 5 + if runlevel: + return LOG_VALUES[runlevel] + else: + return logging.FATAL + 5
def escape(message): """ @@ -146,12 +149,24 @@ def log_once(message_id, runlevel, message): log(runlevel, message)
# shorter aliases for logging at a runlevel -def trace(message): log(Runlevel.TRACE, message) -def debug(message): log(Runlevel.DEBUG, message) -def info(message): log(Runlevel.INFO, message) -def notice(message): log(Runlevel.NOTICE, message) -def warn(message): log(Runlevel.WARN, message) -def error(message): log(Runlevel.ERROR, message) + +def trace(message): + log(Runlevel.TRACE, message) + +def debug(message): + log(Runlevel.DEBUG, message) + +def info(message): + log(Runlevel.INFO, message) + +def notice(message): + log(Runlevel.NOTICE, message) + +def warn(message): + log(Runlevel.WARN, message) + +def error(message): + log(Runlevel.ERROR, message)
class LogBuffer(logging.Handler): """ diff --git a/stem/util/proc.py b/stem/util/proc.py index 05a7ff0..436e061 100644 --- a/stem/util/proc.py +++ b/stem/util/proc.py @@ -52,8 +52,10 @@ IS_PROC_AVAILABLE, SYS_START_TIME, SYS_PHYSICAL_MEMORY = None, None, None CLOCK_TICKS = None
# os.sysconf is only defined on unix -try: CLOCK_TICKS = os.sysconf(os.sysconf_names["SC_CLK_TCK"]) -except AttributeError: pass +try: + CLOCK_TICKS = os.sysconf(os.sysconf_names["SC_CLK_TCK"]) +except AttributeError: + pass
Stat = stem.util.enum.Enum( ("COMMAND", "command"), ("CPU_UTIME", "utime"), @@ -148,9 +150,11 @@ def get_cwd(pid): start_time, parameter = time.time(), "cwd" proc_cwd_link = "/proc/%s/cwd" % pid
- if pid == 0: cwd = "" + if pid == 0: + cwd = "" else: - try: cwd = os.readlink(proc_cwd_link) + try: + cwd = os.readlink(proc_cwd_link) except OSError: exc = IOError("unable to read %s" % proc_cwd_link) _log_failure(parameter, exc) @@ -196,7 +200,9 @@ def get_memory_usage(pid): """
# checks if this is the kernel process - if pid == 0: return (0, 0) + + if pid == 0: + return (0, 0)
start_time, parameter = time.time(), "memory usage" status_path = "/proc/%s/status" % pid @@ -253,16 +259,23 @@ def get_stats(pid, *stat_types): results = [] for stat_type in stat_types: if stat_type == Stat.COMMAND: - if pid == 0: results.append("sched") - else: results.append(stat_comp[1]) + if pid == 0: + results.append("sched") + else: + results.append(stat_comp[1]) elif stat_type == Stat.CPU_UTIME: - if pid == 0: results.append("0") - else: results.append(str(float(stat_comp[13]) / CLOCK_TICKS)) + if pid == 0: + results.append("0") + else: + results.append(str(float(stat_comp[13]) / CLOCK_TICKS)) elif stat_type == Stat.CPU_STIME: - if pid == 0: results.append("0") - else: results.append(str(float(stat_comp[14]) / CLOCK_TICKS)) + if pid == 0: + results.append("0") + else: + results.append(str(float(stat_comp[14]) / CLOCK_TICKS)) elif stat_type == Stat.START_TIME: - if pid == 0: return get_system_start_time() + if pid == 0: + return get_system_start_time() else: # According to documentation, starttime is in field 21 and the unit is # jiffies (clock ticks). We divide it for clock ticks, then add the @@ -288,7 +301,8 @@ def get_connections(pid): :raises: **IOError** if it can't be determined """
- if pid == 0: return [] + if pid == 0: + return []
# fetches the inode numbers for socket file descriptors start_time, parameter = time.time(), "process connections" @@ -384,7 +398,9 @@ def _decode_proc_address_encoding(addr):
def _is_float(*value): try: - for v in value: float(v) + for v in value: + float(v) + return True except ValueError: return False @@ -411,7 +427,8 @@ def _get_lines(file_path, line_prefixes, parameter): proc_file, results = open(file_path), {}
for line in proc_file: - if not remaining_prefixes: break # found everything we're looking for + if not remaining_prefixes: + break # found everything we're looking for
for prefix in remaining_prefixes: if line.startswith(prefix): diff --git a/stem/util/str_tools.py b/stem/util/str_tools.py index b1e854d..443bd4f 100644 --- a/stem/util/str_tools.py +++ b/stem/util/str_tools.py @@ -62,9 +62,12 @@ def to_camel_case(label, divider = "_", joiner = " "):
words = [] for entry in label.split(divider): - if len(entry) == 0: words.append("") - elif len(entry) == 1: words.append(entry.upper()) - else: words.append(entry[0].upper() + entry[1:].lower()) + if len(entry) == 0: + words.append("") + elif len(entry) == 1: + words.append(entry.upper()) + else: + words.append(entry[0].upper() + entry[1:].lower())
return joiner.join(words)
@@ -95,8 +98,10 @@ def get_size_label(byte_count, decimal = 0, is_long = False, is_bytes = True): :returns: **str** with human readable representation of the size """
- if is_bytes: return _get_label(SIZE_UNITS_BYTES, byte_count, decimal, is_long) - else: return _get_label(SIZE_UNITS_BITS, byte_count, decimal, is_long) + if is_bytes: + return _get_label(SIZE_UNITS_BYTES, byte_count, decimal, is_long) + else: + return _get_label(SIZE_UNITS_BITS, byte_count, decimal, is_long)
def get_time_label(seconds, decimal = 0, is_long = False): """ diff --git a/stem/util/system.py b/stem/util/system.py index a3a4c5f..acba9c1 100644 --- a/stem/util/system.py +++ b/stem/util/system.py @@ -104,7 +104,8 @@ def is_available(command, cached=True): PATH, **False** otherwise """
- if " " in command: command = command.split(" ")[0] + if " " in command: + command = command.split(" ")[0]
if command in SHELL_COMMANDS: # we can't actually look it up, so hope the shell really provides it... @@ -116,7 +117,9 @@ def is_available(command, cached=True): cmd_exists = False for path in os.environ["PATH"].split(os.pathsep): cmd_path = os.path.join(path, command) - if is_windows(): cmd_path += ".exe" + + if is_windows(): + cmd_path += ".exe"
if os.path.exists(cmd_path) and os.access(cmd_path, os.X_OK): cmd_exists = True @@ -198,7 +201,9 @@ def get_pid_by_name(process_name):
if results and len(results) == 1: pid = results[0].strip() - if pid.isdigit(): return int(pid) + + if pid.isdigit(): + return int(pid)
# attempts to resolve using pidof, failing if: # - we're running on bsd (command unavailable) @@ -212,7 +217,9 @@ def get_pid_by_name(process_name):
if results and len(results) == 1 and len(results[0].split()) == 1: pid = results[0].strip() - if pid.isdigit(): return int(pid) + + if pid.isdigit(): + return int(pid)
# attempts to resolve using ps, failing if: # - system's ps variant doesn't handle these flags (none known at the moment) @@ -237,7 +244,9 @@ def get_pid_by_name(process_name):
if results and len(results) == 2: pid = results[1].strip() - if pid.isdigit(): return int(pid) + + if pid.isdigit(): + return int(pid)
if is_bsd(): # bsd variant of ps @@ -249,7 +258,9 @@ def get_pid_by_name(process_name):
if len(results) == 1 and len(results[0].split()) > 0: pid = results[0].split()[0] - if pid.isdigit(): return int(pid) + + if pid.isdigit(): + return int(pid)
# resolves using lsof which works on both Linux and BSD, only failing if: # - lsof is unavailable (not included by default on OpenBSD) @@ -270,7 +281,9 @@ def get_pid_by_name(process_name):
if results and len(results) == 1: pid = results[0].strip() - if pid.isdigit(): return int(pid) + + if pid.isdigit(): + return int(pid)
log.debug("failed to resolve a pid for '%s'" % process_name) return None @@ -324,7 +337,9 @@ def get_pid_by_port(port): if len(results) == 1 and len(results[0].split()) == 7: results = results[0].split()[6] # process field (ex. "7184/tor") pid = results[:results.find("/")] - if pid.isdigit(): return int(pid) + + if pid.isdigit(): + return int(pid)
# attempts to resolve using sockstat, failing if: # - sockstat doesn't accept the -4 flag (BSD only) @@ -358,7 +373,9 @@ def get_pid_by_port(port):
if len(results) == 1: pid = results[0].split()[2] - if pid.isdigit(): return int(pid) + + if pid.isdigit(): + return int(pid)
# resolves using lsof which works on both Linux and BSD, only failing if: # - lsof is unavailable (not included by default on OpenBSD) @@ -388,7 +405,9 @@ def get_pid_by_port(port):
if len(results) == 1: pid = results[0].split()[1] - if pid.isdigit(): return int(pid) + + if pid.isdigit(): + return int(pid)
return None # all queries failed
@@ -423,7 +442,9 @@ def get_pid_by_open_file(path):
if results and len(results) == 1: pid = results[0].strip() - if pid.isdigit(): return int(pid) + + if pid.isdigit(): + return int(pid)
return None # all queries failed
@@ -438,8 +459,10 @@ def get_cwd(pid):
# try fetching via the proc contents if it's available if stem.util.proc.is_available(): - try: return stem.util.proc.get_cwd(pid) - except IOError: pass + try: + return stem.util.proc.get_cwd(pid) + except IOError: + pass
# Fall back to a pwdx query. This isn't available on BSD. logging_prefix = "get_cwd(%s):" % pid @@ -485,7 +508,8 @@ def get_cwd(pid): # p2683 # n/proc/2683/cwd (readlink: Permission denied)
- if not " " in lsof_result: return lsof_result + if not " " in lsof_result: + return lsof_result else: log.debug("%s we got unexpected output from lsof: %s" % (logging_prefix, results))
@@ -513,7 +537,9 @@ def get_bsd_jail_id(pid):
if ps_output and len(ps_output) == 2 and len(ps_output[1].split()) == 1: jid = ps_output[1].strip() - if jid.isdigit(): return int(jid) + + if jid.isdigit(): + return int(jid)
os_name = platform.system() if os_name == "FreeBSD": @@ -549,7 +575,9 @@ def expand_path(path, cwd = None): relative_path = os.path.expanduser(relative_path) else: # relative path, expand with the cwd - if not cwd: cwd = os.getcwd() + + if not cwd: + cwd = os.getcwd()
# we'll be dealing with both "my/path/" and "./my/path" entries, so # cropping the later @@ -597,10 +625,14 @@ def call(command, default = UNDEFINED): elif stderr: log.trace(trace_prefix + ", stderr:\n%s" % stderr)
- if stdout: return stdout.splitlines() - else: return [] + if stdout: + return stdout.splitlines() + else: + return [] except OSError, exc: log.debug("System call (failed): %s (error: %s)" % (command, exc))
- if default != UNDEFINED: return default - else: raise exc + if default != UNDEFINED: + return default + else: + raise exc diff --git a/stem/util/term.py b/stem/util/term.py index 05b51e3..d77fccf 100644 --- a/stem/util/term.py +++ b/stem/util/term.py @@ -84,8 +84,11 @@ def format(msg, *attr): encoding = FG_ENCODING.get(text_attr, encoding) encoding = BG_ENCODING.get(text_attr, encoding) encoding = ATTR_ENCODING.get(text_attr, encoding) - if encoding: encodings.append(encoding) + + if encoding: + encodings.append(encoding)
if encodings: return (CSI % ";".join(encodings)) + msg + RESET - else: return msg + else: + return msg diff --git a/stem/util/tor_tools.py b/stem/util/tor_tools.py index d7a785a..3f15eb2 100644 --- a/stem/util/tor_tools.py +++ b/stem/util/tor_tools.py @@ -47,7 +47,9 @@ def is_valid_fingerprint(entry, check_prefix = False): if not isinstance(entry, str): return False elif check_prefix: - if not entry or entry[0] != "$": return False + if not entry or entry[0] != "$": + return False + entry = entry[1:]
return bool(FINGERPRINT_PATTERN.match(entry)) diff --git a/stem/version.py b/stem/version.py index bf8c32c..76b8a88 100644 --- a/stem/version.py +++ b/stem/version.py @@ -125,9 +125,14 @@ class Version(object): # The patch and status matches are optional (may be None) and have an extra # proceeding period or dash if they exist. Stripping those off.
- if patch: patch = int(patch[1:]) - if status: status = status[1:] - if extra: extra = extra[2:-1] + if patch: + patch = int(patch[1:]) + + if status: + status = status[1:] + + if extra: + extra = extra[2:-1]
self.major = int(major) self.minor = int(minor) @@ -140,7 +145,8 @@ class Version(object): self.git_commit = extra[4:] else: self.git_commit = None - else: raise ValueError("'%s' isn't a properly formatted tor version" % version_str) + else: + raise ValueError("'%s' isn't a properly formatted tor version" % version_str)
def meets_requirements(self, requirements): """ @@ -155,7 +161,8 @@ class Version(object): return self >= requirements else: for rule in requirements.rules: - if rule(self): return True + if rule(self): + return True
return False
@@ -178,8 +185,10 @@ class Version(object): my_version = max(0, self.__dict__[attr]) other_version = max(0, other.__dict__[attr])
- if my_version > other_version: return 1 - elif my_version < other_version: return -1 + if my_version > other_version: + return 1 + elif my_version < other_version: + return -1
# According to the version spec... # @@ -189,9 +198,12 @@ class Version(object): my_status = self.status if self.status else "" other_status = other.status if other.status else ""
- if my_status > other_status: return 1 - elif my_status < other_status: return -1 - else: return 0 + if my_status > other_status: + return 1 + elif my_status < other_status: + return -1 + else: + return 0
class VersionRequirements(object): """ diff --git a/test/check_whitespace.py b/test/check_whitespace.py index d65c5b5..6bbbea4 100644 --- a/test/check_whitespace.py +++ b/test/check_whitespace.py @@ -62,7 +62,7 @@ def pep8_issues(base_path = DEFAULT_TARGET): # # Someone else can change this if they really care.
- ignored_issues = "E111,E121,W293,E501,E302,E701,E251,E127" + ignored_issues = "E111,E121,W293,E501,E302,E251,E127"
issues = {} pep8_output = system.call("pep8 --ignore %s %s" % (ignored_issues, base_path)) @@ -92,7 +92,9 @@ def get_issues(base_path = DEFAULT_TARGET): issues = {}
for file_path in _get_files_with_suffix(base_path): - with open(file_path) as f: file_contents = f.read() + with open(file_path) as f: + file_contents = f.read() + lines, file_issues, prev_indent = file_contents.split("\n"), [], 0 has_with_import, given_with_warning = False, False is_block_comment = False diff --git a/test/integ/connection/authentication.py b/test/integ/connection/authentication.py index 5396d02..e707b49 100644 --- a/test/integ/connection/authentication.py +++ b/test/integ/connection/authentication.py @@ -47,10 +47,14 @@ def _can_authenticate(auth_type): if not password_auth and not cookie_auth: # open socket, anything but safecookie will work return auth_type != stem.connection.AuthMethod.SAFECOOKIE - elif auth_type == stem.connection.AuthMethod.PASSWORD: return password_auth - elif auth_type == stem.connection.AuthMethod.COOKIE: return cookie_auth - elif auth_type == stem.connection.AuthMethod.SAFECOOKIE: return safecookie_auth - else: return False + elif auth_type == stem.connection.AuthMethod.PASSWORD: + return password_auth + elif auth_type == stem.connection.AuthMethod.COOKIE: + return cookie_auth + elif auth_type == stem.connection.AuthMethod.SAFECOOKIE: + return safecookie_auth + else: + return False
def _get_auth_failure_message(auth_type): """ @@ -105,7 +109,8 @@ class TestAuthenticate(unittest.TestCase): Tests that the authenticate function can authenticate to our socket. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
runner = test.runner.get_runner() with runner.get_tor_socket(False) as control_socket: @@ -117,7 +122,8 @@ class TestAuthenticate(unittest.TestCase): Tests that the authenticate function can authenticate via a Controller. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
runner = test.runner.get_runner() with runner.get_tor_controller(False) as controller: @@ -129,7 +135,8 @@ class TestAuthenticate(unittest.TestCase): Tests the authenticate function with something like its pydoc example. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
runner = test.runner.get_runner() tor_options = runner.get_options() @@ -166,7 +173,8 @@ class TestAuthenticate(unittest.TestCase): Tests the authenticate function's password argument. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
# this is a much better test if we're just using password auth, since # authenticate will work reguardless if there's something else to @@ -204,7 +212,8 @@ class TestAuthenticate(unittest.TestCase): individually. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
runner = test.runner.get_runner() tor_options = runner.get_options() @@ -228,7 +237,8 @@ class TestAuthenticate(unittest.TestCase): Tests the authenticate_none function. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
auth_type = stem.connection.AuthMethod.NONE
@@ -242,7 +252,8 @@ class TestAuthenticate(unittest.TestCase): Tests the authenticate_password function. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
auth_type = stem.connection.AuthMethod.PASSWORD auth_value = test.runner.CONTROL_PASSWORD @@ -271,7 +282,8 @@ class TestAuthenticate(unittest.TestCase): Tests the authenticate_cookie function. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
auth_value = test.runner.get_runner().get_auth_cookie_path()
@@ -295,7 +307,8 @@ class TestAuthenticate(unittest.TestCase): value. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
auth_value = test.runner.get_runner().get_test_dir("fake_cookie")
@@ -333,7 +346,8 @@ class TestAuthenticate(unittest.TestCase): shouldn't exist. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
for auth_type in self.cookie_auth_methods: auth_value = "/if/this/exists/then/they're/asking/for/a/failure" @@ -346,7 +360,8 @@ class TestAuthenticate(unittest.TestCase): socket. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
auth_value = test.runner.get_runner().get_torrc_path(True)
diff --git a/test/integ/connection/connect.py b/test/integ/connection/connect.py index fcf55a9..66b793d 100644 --- a/test/integ/connection/connect.py +++ b/test/integ/connection/connect.py @@ -23,7 +23,8 @@ class TestConnect(unittest.TestCase): Basic sanity checks for the connect_port function. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
runner = test.runner.get_runner()
@@ -44,7 +45,8 @@ class TestConnect(unittest.TestCase): Basic sanity checks for the connect_socket_file function. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
runner = test.runner.get_runner()
diff --git a/test/integ/control/base_controller.py b/test/integ/control/base_controller.py index d43b009..25af63d 100644 --- a/test/integ/control/base_controller.py +++ b/test/integ/control/base_controller.py @@ -41,7 +41,8 @@ class TestBaseController(unittest.TestCase): trigger concurrency issues. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return elif stem.util.system.is_mac(): test.runner.skip(self, "(ticket #6235)") return @@ -58,7 +59,8 @@ class TestBaseController(unittest.TestCase): Tests a basic query with the msg() method. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
with test.runner.get_runner().get_tor_socket() as control_socket: controller = stem.control.BaseController(control_socket) @@ -69,7 +71,8 @@ class TestBaseController(unittest.TestCase): Tests the msg() method against an invalid controller command. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
with test.runner.get_runner().get_tor_socket() as control_socket: controller = stem.control.BaseController(control_socket) @@ -81,7 +84,8 @@ class TestBaseController(unittest.TestCase): Tests the msg() method against a non-existant GETINFO option. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
with test.runner.get_runner().get_tor_socket() as control_socket: controller = stem.control.BaseController(control_socket) @@ -94,7 +98,8 @@ class TestBaseController(unittest.TestCase): is a simple attempt to trigger concurrency issues. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return elif stem.util.system.is_mac(): test.runner.skip(self, "(ticket #6235)") return @@ -133,7 +138,8 @@ class TestBaseController(unittest.TestCase): listeners will still receive all of the enqueued events. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
class ControlledListener(stem.control.BaseController): """ @@ -188,7 +194,8 @@ class TestBaseController(unittest.TestCase): Basic check for get_latest_heartbeat(). """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
# makes a getinfo query, then checks that the heartbeat is close to now with test.runner.get_runner().get_tor_socket() as control_socket: @@ -202,7 +209,8 @@ class TestBaseController(unittest.TestCase): remove_status_listener() methods. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
state_observer = StateObserver()
diff --git a/test/integ/control/controller.py b/test/integ/control/controller.py index b769fbc..6d91f50 100644 --- a/test/integ/control/controller.py +++ b/test/integ/control/controller.py @@ -33,7 +33,8 @@ class TestController(unittest.TestCase): Basic sanity check for the from_port constructor. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
if test.runner.Torrc.PORT in test.runner.get_runner().get_options(): with stem.control.Controller.from_port(control_port = test.runner.CONTROL_PORT) as controller: @@ -46,7 +47,8 @@ class TestController(unittest.TestCase): Basic sanity check for the from_socket_file constructor. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
if test.runner.Torrc.SOCKET in test.runner.get_runner().get_options(): with stem.control.Controller.from_socket_file(socket_path = test.runner.CONTROL_SOCKET_PATH) as controller: @@ -60,7 +62,8 @@ class TestController(unittest.TestCase): them. Then remove the listeners. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
event_notice1, event_notice2 = threading.Event(), threading.Event() event_buffer1, event_buffer2 = [], [] @@ -74,6 +77,7 @@ class TestController(unittest.TestCase): event_notice2.set()
runner = test.runner.get_runner() + with runner.get_tor_controller() as controller: controller.add_event_listener(listener1, EventType.BW) controller.add_event_listener(listener2, EventType.BW, EventType.DEBUG) @@ -116,7 +120,8 @@ class TestController(unittest.TestCase): then reconnects to tor. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
event_notice = threading.Event() event_buffer = [] @@ -126,6 +131,7 @@ class TestController(unittest.TestCase): event_notice.set()
runner = test.runner.get_runner() + with runner.get_tor_controller() as controller: controller.add_event_listener(listener, EventType.BW)
@@ -192,7 +198,8 @@ class TestController(unittest.TestCase): Exercises GETINFO with valid and invalid queries. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
runner = test.runner.get_runner()
@@ -231,9 +238,11 @@ class TestController(unittest.TestCase): Test that the convenient method get_version() works. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
runner = test.runner.get_runner() + with runner.get_tor_controller() as controller: version = controller.get_version() self.assertTrue(isinstance(version, stem.version.Version)) @@ -244,9 +253,11 @@ class TestController(unittest.TestCase): Test that the convenient method authenticate() works. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
runner = test.runner.get_runner() + with runner.get_tor_controller(False) as controller: controller.authenticate(test.runner.CONTROL_PASSWORD) test.runner.exercise_controller(self, controller) @@ -256,7 +267,8 @@ class TestController(unittest.TestCase): Test that the convenient method protocolinfo() works. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
runner = test.runner.get_runner()
@@ -288,12 +300,14 @@ class TestController(unittest.TestCase): Exercises GETCONF with valid and invalid queries. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
runner = test.runner.get_runner()
with runner.get_tor_controller() as controller: socket = controller.get_socket() + if isinstance(socket, stem.socket.ControlPort): connection_value = str(socket.get_port()) config_key = "ControlPort" @@ -352,7 +366,8 @@ class TestController(unittest.TestCase): and invalid requests. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
runner = test.runner.get_runner() tmpdir = tempfile.mkdtemp() @@ -425,8 +440,10 @@ class TestController(unittest.TestCase): Exercises Controller.load_conf with valid and invalid requests. """
- if test.runner.require_control(self): return - elif test.runner.require_version(self, stem.version.Requirement.LOADCONF): return + if test.runner.require_control(self): + return + elif test.runner.require_version(self, stem.version.Requirement.LOADCONF): + return
runner = test.runner.get_runner()
@@ -436,6 +453,7 @@ class TestController(unittest.TestCase): try: # invalid requests self.assertRaises(stem.InvalidRequest, controller.load_conf, "ContactInfo confloaded") + try: controller.load_conf("Blahblah blah") self.fail() @@ -443,6 +461,7 @@ class TestController(unittest.TestCase): self.assertEqual(["Blahblah"], exc.arguments)
# valid config + controller.load_conf(runner.get_torrc_contents() + "\nContactInfo confloaded\n") self.assertEqual("confloaded", controller.get_conf("ContactInfo")) finally: @@ -450,7 +469,8 @@ class TestController(unittest.TestCase): controller.load_conf(oldconf)
def test_saveconf(self): - if test.runner.require_control(self): return + if test.runner.require_control(self): + return
runner = test.runner.get_runner()
@@ -462,6 +482,7 @@ class TestController(unittest.TestCase): try: controller.set_conf("ContactInfo", "confsaved") controller.save_conf() + with file(runner.get_torrc_path()) as torrcfile: self.assertTrue("\nContactInfo confsaved\n" in torrcfile.read()) finally: @@ -472,7 +493,9 @@ class TestController(unittest.TestCase): """ Test Controller.get_socks_ports against a running tor instance. """ - if test.runner.require_control(self): return + + if test.runner.require_control(self): + return
runner = test.runner.get_runner()
@@ -484,7 +507,8 @@ class TestController(unittest.TestCase): Test Controller.enable_feature with valid and invalid inputs. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
runner = test.runner.get_runner()
@@ -498,22 +522,26 @@ class TestController(unittest.TestCase):
# the orconn-status results will be empty if we don't have a connection if orconn_output == '': - if test.runner.require_online(self): return + if test.runner.require_online(self): + return
self.assertTrue("VERBOSE_NAMES" in controller._enabled_features) self.assertRaises(stem.InvalidArguments, controller.enable_feature, ["NOT", "A", "FEATURE"]) + try: controller.enable_feature(["NOT", "A", "FEATURE"]) except stem.InvalidArguments, exc: self.assertEqual(["NOT"], exc.arguments) - else: self.fail() + else: + self.fail()
def test_signal(self): """ Test controller.signal with valid and invalid signals. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
with test.runner.get_runner().get_tor_controller() as controller: # valid signal @@ -523,9 +551,12 @@ class TestController(unittest.TestCase): self.assertRaises(stem.InvalidArguments, controller.signal, "FOOBAR")
def test_extendcircuit(self): - if test.runner.require_control(self): return - elif test.runner.require_online(self): return - elif test.runner.require_version(self, Requirement.EXTENDCIRCUIT_PATH_OPTIONAL): return + if test.runner.require_control(self): + return + elif test.runner.require_online(self): + return + elif test.runner.require_version(self, Requirement.EXTENDCIRCUIT_PATH_OPTIONAL): + return
with test.runner.get_runner().get_tor_controller() as controller: circuit_id = controller.extend_circuit('0') @@ -544,9 +575,12 @@ class TestController(unittest.TestCase): Tests Controller.repurpose_circuit with valid and invalid input. """
- if test.runner.require_control(self): return - elif test.runner.require_online(self): return - elif test.runner.require_version(self, Requirement.EXTENDCIRCUIT_PATH_OPTIONAL): return + if test.runner.require_control(self): + return + elif test.runner.require_online(self): + return + elif test.runner.require_version(self, Requirement.EXTENDCIRCUIT_PATH_OPTIONAL): + return
runner = test.runner.get_runner()
@@ -568,9 +602,12 @@ class TestController(unittest.TestCase): Tests Controller.close_circuit with valid and invalid input. """
- if test.runner.require_control(self): return - elif test.runner.require_online(self): return - elif test.runner.require_version(self, Requirement.EXTENDCIRCUIT_PATH_OPTIONAL): return + if test.runner.require_control(self): + return + elif test.runner.require_online(self): + return + elif test.runner.require_version(self, Requirement.EXTENDCIRCUIT_PATH_OPTIONAL): + return
runner = test.runner.get_runner()
@@ -596,8 +633,10 @@ class TestController(unittest.TestCase): Tests Controller.get_streams(). """
- if test.runner.require_control(self): return - elif test.runner.require_online(self): return + if test.runner.require_control(self): + return + elif test.runner.require_online(self): + return
host = "38.229.72.14" # www.torproject.org port = 443 @@ -622,8 +661,10 @@ class TestController(unittest.TestCase): Tests Controller.close_stream with valid and invalid input. """
- if test.runner.require_control(self): return - elif test.runner.require_online(self): return + if test.runner.require_control(self): + return + elif test.runner.require_online(self): + return
runner = test.runner.get_runner()
@@ -647,8 +688,10 @@ class TestController(unittest.TestCase): self.assertRaises(stem.InvalidArguments, controller.close_stream, "blarg")
def test_mapaddress(self): - if test.runner.require_control(self): return - elif test.runner.require_online(self): return + if test.runner.require_control(self): + return + elif test.runner.require_online(self): + return
runner = test.runner.get_runner()
@@ -675,7 +718,8 @@ class TestController(unittest.TestCase): runner = test.runner.get_runner() descriptor_path = runner.get_test_dir("cached-descriptors")
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return elif not os.path.exists(descriptor_path): test.runner.skip(self, "(no cached descriptors)") return @@ -711,7 +755,8 @@ class TestController(unittest.TestCase):
runner = test.runner.get_runner()
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
with runner.get_tor_controller() as controller: count = 0 @@ -725,7 +770,8 @@ class TestController(unittest.TestCase): # while to do so).
count += 1 - if count > 10: break + if count > 10: + break
def test_get_network_status(self): """ @@ -735,7 +781,8 @@ class TestController(unittest.TestCase): runner = test.runner.get_runner() descriptor_path = runner.get_test_dir("cached-consensus")
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return elif not os.path.exists(descriptor_path): test.runner.skip(self, "(no cached descriptors)") return @@ -777,7 +824,8 @@ class TestController(unittest.TestCase):
runner = test.runner.get_runner()
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
with runner.get_tor_controller() as controller: count = 0 @@ -787,12 +835,16 @@ class TestController(unittest.TestCase): self.assertTrue(desc.nickname is not None)
count += 1 - if count > 10: break + if count > 10: + break
def test_attachstream(self): - if test.runner.require_control(self): return - elif test.runner.require_online(self): return - elif test.runner.require_version(self, Requirement.EXTENDCIRCUIT_PATH_OPTIONAL): return + if test.runner.require_control(self): + return + elif test.runner.require_online(self): + return + elif test.runner.require_version(self, Requirement.EXTENDCIRCUIT_PATH_OPTIONAL): + return
circuit_id = None
@@ -823,9 +875,12 @@ class TestController(unittest.TestCase): Fetches circuits via the get_circuits() method. """
- if test.runner.require_control(self): return - elif test.runner.require_online(self): return - elif test.runner.require_version(self, Requirement.EXTENDCIRCUIT_PATH_OPTIONAL): return + if test.runner.require_control(self): + return + elif test.runner.require_online(self): + return + elif test.runner.require_version(self, Requirement.EXTENDCIRCUIT_PATH_OPTIONAL): + return
runner = test.runner.get_runner() with runner.get_tor_controller() as controller: diff --git a/test/integ/descriptor/extrainfo_descriptor.py b/test/integ/descriptor/extrainfo_descriptor.py index a2bf144..1293b3c 100644 --- a/test/integ/descriptor/extrainfo_descriptor.py +++ b/test/integ/descriptor/extrainfo_descriptor.py @@ -139,7 +139,9 @@ k0d2aofcVbHr4fPQOSST0LXDrhFl5Fqo5um296zpJGvRUeO6S44U/EfJAGShtqWw """
# lengthy test and uneffected by targets, so only run once - if test.runner.only_run_once(self, "test_cached_descriptor"): return + + if test.runner.only_run_once(self, "test_cached_descriptor"): + return
descriptor_path = test.runner.get_runner().get_test_dir("cached-extrainfo")
diff --git a/test/integ/descriptor/networkstatus.py b/test/integ/descriptor/networkstatus.py index ad2933e..862c166 100644 --- a/test/integ/descriptor/networkstatus.py +++ b/test/integ/descriptor/networkstatus.py @@ -21,7 +21,9 @@ class TestNetworkStatus(unittest.TestCase): """
# lengthy test and uneffected by targets, so only run once - if test.runner.only_run_once(self, "test_cached_consensus"): return + + if test.runner.only_run_once(self, "test_cached_consensus"): + return
consensus_path = test.runner.get_runner().get_test_dir("cached-consensus")
@@ -67,7 +69,9 @@ class TestNetworkStatus(unittest.TestCase): """
# lengthy test and uneffected by targets, so only run once - if test.runner.only_run_once(self, "test_cached_microdesc_consensus"): return + + if test.runner.only_run_once(self, "test_cached_microdesc_consensus"): + return
consensus_path = test.runner.get_runner().get_test_dir("cached-microdesc-consensus")
diff --git a/test/integ/descriptor/reader.py b/test/integ/descriptor/reader.py index 637583e..ba807f0 100644 --- a/test/integ/descriptor/reader.py +++ b/test/integ/descriptor/reader.py @@ -64,7 +64,8 @@ def _get_raw_tar_descriptors(): raw_descriptors.append(entry.read()) entry.close() finally: - if tar_file: tar_file.close() + if tar_file: + tar_file.close()
TAR_DESCRIPTORS = raw_descriptors
@@ -240,7 +241,9 @@ class TestDescriptorReader(unittest.TestCase): # the saving functionality.
reader = stem.descriptor.reader.DescriptorReader(descriptor_path, persistence_path = persistence_path) - with reader: self.assertEqual(1, len(list(reader))) + + with reader: + self.assertEqual(1, len(list(reader)))
# check that we've saved reading example_descriptor self.assertTrue(os.path.exists(persistence_path)) @@ -254,7 +257,9 @@ class TestDescriptorReader(unittest.TestCase): # descriptor file. This in essence just tests its loading functionality.
reader = stem.descriptor.reader.DescriptorReader(descriptor_path, persistence_path = persistence_path) - with reader: self.assertEqual(0, len(list(reader))) + + with reader: + self.assertEqual(0, len(list(reader)))
def test_archived_uncompressed(self): """ @@ -299,7 +304,9 @@ class TestDescriptorReader(unittest.TestCase): """
# Skip on windows since SIGALRM is unavailable - if system.is_windows(): test.runner.skip(self, "(SIGALRM unavailable)") + + if system.is_windows(): + test.runner.skip(self, "(SIGALRM unavailable)")
is_test_running = True reader = stem.descriptor.reader.DescriptorReader("/usr") @@ -335,7 +342,9 @@ class TestDescriptorReader(unittest.TestCase): expected_results[path] = last_modified
reader = stem.descriptor.reader.DescriptorReader(DESCRIPTOR_TEST_DATA) - with reader: list(reader) # iterates over all of the descriptors + + with reader: + list(reader) # iterates over all of the descriptors
self.assertEquals(expected_results, reader.get_processed_files())
@@ -349,12 +358,14 @@ class TestDescriptorReader(unittest.TestCase): reader = stem.descriptor.reader.DescriptorReader(DESCRIPTOR_TEST_DATA) reader.register_skip_listener(skip_listener.listener)
- with reader: list(reader) # iterates over all of the descriptors + with reader: + list(reader) # iterates over all of the descriptors
self.assertEqual(4, len(skip_listener.results))
for skip_path, skip_exception in skip_listener.results: - if skip_path.endswith(".swp"): continue # skip vim temp files + if skip_path.endswith(".swp"): + continue # skip vim temp files
if not os.path.basename(skip_path) in ("riddle", "tiny.png", "vote", "new_metrics_type"): self.fail("Unexpected non-descriptor content: %s" % skip_path) @@ -378,7 +389,9 @@ class TestDescriptorReader(unittest.TestCase): reader.set_processed_files(initial_processed_files)
self.assertEquals(initial_processed_files, reader.get_processed_files()) - with reader: list(reader) # iterates over all of the descriptors + + with reader: + list(reader) # iterates over all of the descriptors
self.assertEquals(1, len(skip_listener.results))
@@ -405,7 +418,9 @@ class TestDescriptorReader(unittest.TestCase): skip_listener = SkipListener() reader = stem.descriptor.reader.DescriptorReader(test_path) reader.register_skip_listener(skip_listener.listener) - with reader: list(reader) # iterates over all of the descriptors + + with reader: + list(reader) # iterates over all of the descriptors
self.assertEqual(1, len(skip_listener.results))
@@ -437,7 +452,9 @@ class TestDescriptorReader(unittest.TestCase): skip_listener = SkipListener() reader = stem.descriptor.reader.DescriptorReader(test_path) reader.register_skip_listener(skip_listener.listener) - with reader: list(reader) # iterates over all of the descriptors + + with reader: + list(reader) # iterates over all of the descriptors
self.assertEqual(1, len(skip_listener.results))
@@ -459,7 +476,9 @@ class TestDescriptorReader(unittest.TestCase): skip_listener = SkipListener() reader = stem.descriptor.reader.DescriptorReader(test_path) reader.register_skip_listener(skip_listener.listener) - with reader: list(reader) # iterates over all of the descriptors + + with reader: + list(reader) # iterates over all of the descriptors
self.assertEqual(1, len(skip_listener.results))
@@ -477,7 +496,9 @@ class TestDescriptorReader(unittest.TestCase): skip_listener = SkipListener() reader = stem.descriptor.reader.DescriptorReader(test_path) reader.register_skip_listener(skip_listener.listener) - with reader: list(reader) # iterates over all of the descriptors + + with reader: + list(reader) # iterates over all of the descriptors
self.assertEqual(1, len(skip_listener.results))
diff --git a/test/integ/descriptor/server_descriptor.py b/test/integ/descriptor/server_descriptor.py index a2ee34a..b6b8e62 100644 --- a/test/integ/descriptor/server_descriptor.py +++ b/test/integ/descriptor/server_descriptor.py @@ -147,7 +147,9 @@ Qlx9HNCqCY877ztFRC624ja2ql6A2hBcuoYMbkHjcQ4= """
# lengthy test and uneffected by targets, so only run once - if test.runner.only_run_once(self, "test_cached_descriptor"): return + + if test.runner.only_run_once(self, "test_cached_descriptor"): + return
descriptor_path = test.runner.get_runner().get_test_dir("cached-descriptors")
diff --git a/test/integ/process.py b/test/integ/process.py index ea8909a..6629575 100644 --- a/test/integ/process.py +++ b/test/integ/process.py @@ -45,7 +45,8 @@ class TestProcess(unittest.TestCase): test.runner.skip(self, "(unable to kill subprocesses)") return
- if test.runner.only_run_once(self, "test_launch_tor_with_config"): return + if test.runner.only_run_once(self, "test_launch_tor_with_config"): + return
# Launch tor without a torrc, but with a control port. Confirms that this # works by checking that we're still able to access the new instance. @@ -71,7 +72,9 @@ class TestProcess(unittest.TestCase): getconf_response = control_socket.recv() self.assertEquals("ControlPort=2778", str(getconf_response)) finally: - if control_socket: control_socket.close() + if control_socket: + control_socket.close() + _kill_process(tor_process)
def test_launch_tor_with_timeout(self): @@ -83,7 +86,8 @@ class TestProcess(unittest.TestCase): test.runner.skip(self, "(unable to kill subprocesses)") return
- if test.runner.only_run_once(self, "test_launch_tor_with_timeout"): return + if test.runner.only_run_once(self, "test_launch_tor_with_timeout"): + return
runner = test.runner.get_runner() start_time = time.time() @@ -106,8 +110,10 @@ class TestProcess(unittest.TestCase): elif not stem.util.system.is_available("sleep"): test.runner.skip(self, "('sleep' command is unavailable)") return - elif test.runner.only_run_once(self, "test_take_ownership_via_pid"): return - elif test.runner.require_version(self, stem.version.Requirement.TAKEOWNERSHIP): return + elif test.runner.only_run_once(self, "test_take_ownership_via_pid"): + return + elif test.runner.require_version(self, stem.version.Requirement.TAKEOWNERSHIP): + return
# Have os.getpid provide the pid of a process we can safely kill. I hate # needing to a _get_pid() helper but after much head scratching I haven't @@ -148,8 +154,10 @@ class TestProcess(unittest.TestCase): connects, then disconnects.. """
- if test.runner.only_run_once(self, "test_take_ownership_via_controller"): return - elif test.runner.require_version(self, stem.version.Requirement.TAKEOWNERSHIP): return + if test.runner.only_run_once(self, "test_take_ownership_via_controller"): + return + elif test.runner.require_version(self, stem.version.Requirement.TAKEOWNERSHIP): + return
tor_process = stem.process.launch_tor_with_config( tor_cmd = test.runner.get_runner().get_tor_command(), diff --git a/test/integ/response/protocolinfo.py b/test/integ/response/protocolinfo.py index 2affe17..623ce48 100644 --- a/test/integ/response/protocolinfo.py +++ b/test/integ/response/protocolinfo.py @@ -30,7 +30,8 @@ class TestProtocolInfo(unittest.TestCase): connection. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
control_socket = test.runner.get_runner().get_tor_socket(False) control_socket.send("PROTOCOLINFO 1") @@ -58,7 +59,8 @@ class TestProtocolInfo(unittest.TestCase): with the 'RELATIVE' target. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
if test.runner.Torrc.PORT in test.runner.get_runner().get_options(): cwd_by_port_lookup_prefixes = ( @@ -93,7 +95,8 @@ class TestProtocolInfo(unittest.TestCase): re-establish it. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
with test.runner.get_runner().get_tor_socket(False) as control_socket: for _ in range(5): @@ -106,7 +109,8 @@ class TestProtocolInfo(unittest.TestCase): already disconnected it. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
with test.runner.get_runner().get_tor_socket(False) as control_socket: # makes a couple protocolinfo queries outside of get_protocolinfo first diff --git a/test/integ/socket/control_message.py b/test/integ/socket/control_message.py index 2a358cb..5c78f1a 100644 --- a/test/integ/socket/control_message.py +++ b/test/integ/socket/control_message.py @@ -17,7 +17,8 @@ class TestControlMessage(unittest.TestCase): Checks message parsing when we have a valid but unauthenticated socket. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
# If an unauthenticated connection gets a message besides AUTHENTICATE or # PROTOCOLINFO then tor will give an 'Authentication required.' message and @@ -59,7 +60,8 @@ class TestControlMessage(unittest.TestCase): Parses the response for a command which doesn't exist. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
with test.runner.get_runner().get_tor_socket() as control_socket: control_socket.send("blarg") @@ -74,7 +76,8 @@ class TestControlMessage(unittest.TestCase): Parses the response for a GETINFO query which doesn't exist. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
with test.runner.get_runner().get_tor_socket() as control_socket: control_socket.send("GETINFO blarg") @@ -89,7 +92,8 @@ class TestControlMessage(unittest.TestCase): Parses the 'GETINFO config-file' response. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
runner = test.runner.get_runner() torrc_dst = runner.get_torrc_path() @@ -152,7 +156,8 @@ class TestControlMessage(unittest.TestCase): Issues 'SETEVENTS BW' and parses a couple events. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
with test.runner.get_runner().get_tor_socket() as control_socket: control_socket.send("SETEVENTS BW") diff --git a/test/integ/socket/control_socket.py b/test/integ/socket/control_socket.py index 2f2a4e7..13daaf4 100644 --- a/test/integ/socket/control_socket.py +++ b/test/integ/socket/control_socket.py @@ -23,7 +23,8 @@ class TestControlSocket(unittest.TestCase): Sends multiple requests before receiving back any of the replies. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
runner = test.runner.get_runner() tor_version = runner.get_tor_version() @@ -42,7 +43,8 @@ class TestControlSocket(unittest.TestCase): Sends a message after we've closed the connection. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
with test.runner.get_runner().get_tor_socket() as control_socket: self.assertTrue(control_socket.is_alive()) @@ -61,7 +63,8 @@ class TestControlSocket(unittest.TestCase): call. With a file socket, however, we'll also fail when calling send(). """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
with test.runner.get_runner().get_tor_socket() as control_socket: control_socket.send("QUIT") @@ -83,7 +86,8 @@ class TestControlSocket(unittest.TestCase): Receives a message after we've closed the connection. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
with test.runner.get_runner().get_tor_socket() as control_socket: self.assertTrue(control_socket.is_alive()) @@ -98,7 +102,8 @@ class TestControlSocket(unittest.TestCase): end. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
with test.runner.get_runner().get_tor_socket() as control_socket: control_socket.send("QUIT") @@ -117,7 +122,8 @@ class TestControlSocket(unittest.TestCase): Checks that we can reconnect, use, and disconnect a socket repeatedly. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
with test.runner.get_runner().get_tor_socket(False) as control_socket: for _ in range(10): diff --git a/test/integ/version.py b/test/integ/version.py index 9195126..9542c63 100644 --- a/test/integ/version.py +++ b/test/integ/version.py @@ -37,7 +37,8 @@ class TestVersion(unittest.TestCase): test instance provides. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
runner = test.runner.get_runner() system_tor_version = stem.version.get_system_tor_version(runner.get_tor_command()) @@ -49,7 +50,8 @@ class TestVersion(unittest.TestCase): we can parse it. """
- if test.runner.require_control(self): return + if test.runner.require_control(self): + return
control_socket = test.runner.get_runner().get_tor_socket() control_socket.send("GETINFO version") diff --git a/test/mocking.py b/test/mocking.py index ff314ee..1ebe88d 100644 --- a/test/mocking.py +++ b/test/mocking.py @@ -193,16 +193,25 @@ NETWORK_STATUS_DOCUMENT_FOOTER = ( )
def no_op(): - def _no_op(*args): pass + def _no_op(*args): + pass + return _no_op
def return_value(value): - def _return_value(*args): return value + def _return_value(*args): + return value + return _return_value
-def return_true(): return return_value(True) -def return_false(): return return_value(False) -def return_none(): return return_value(None) +def return_true(): + return return_value(True) + +def return_false(): + return return_value(False) + +def return_none(): + return return_value(None)
def return_for_args(args_to_return_value, default = None, is_method = False): """ @@ -266,7 +275,9 @@ def return_for_args(args_to_return_value, default = None, is_method = False): return _return_value
def raise_exception(exception): - def _raise(*args): raise exception + def _raise(*args): + raise exception + return _raise
def support_with(obj): @@ -425,7 +436,8 @@ def get_all_combinations(attr, include_empty = False): # * itertools.product(attr, attr) => all two-element combinations # * ... etc
- if include_empty: yield () + if include_empty: + yield ()
seen = set() for index in xrange(1, len(attr) + 1): @@ -485,7 +497,9 @@ def get_message(content, reformat = True): """
if reformat: - if not content.endswith("\n"): content += "\n" + if not content.endswith("\n"): + content += "\n" + content = content.replace("\n", "\r\n")
return stem.socket.recv_message(StringIO.StringIO(content)) @@ -547,18 +561,23 @@ def _get_descriptor_content(attr = None, exclude = (), header_template = (), foo """
header_content, footer_content = [], [] - if attr is None: attr = {} + + if attr is None: + attr = {} + attr = dict(attr) # shallow copy since we're destructive
for content, template in ((header_content, header_template), (footer_content, footer_template)): for keyword, value in template: - if keyword in exclude: continue + if keyword in exclude: + continue elif keyword in attr: value = attr[keyword] del attr[keyword]
- if value is None: continue + if value is None: + continue elif value == "": content.append(keyword) elif keyword == "onion-key" or keyword == "signing-key" or keyword == "router-signature": @@ -569,8 +588,10 @@ def _get_descriptor_content(attr = None, exclude = (), header_template = (), foo remainder = []
for k, v in attr.items(): - if v: remainder.append("%s %s" % (k, v)) - else: remainder.append(k) + if v: + remainder.append("%s %s" % (k, v)) + else: + remainder.append(k)
return "\n".join(header_content + remainder + footer_content)
diff --git a/test/output.py b/test/output.py index d79db70..cadf071 100644 --- a/test/output.py +++ b/test/output.py @@ -37,12 +37,16 @@ LINE_ATTR = { }
def print_line(msg, *attr): - if CONFIG["argument.no_color"]: print msg - else: print term.format(msg, *attr) + if CONFIG["argument.no_color"]: + print msg + else: + print term.format(msg, *attr)
def print_noline(msg, *attr): - if CONFIG["argument.no_color"]: sys.stdout.write(msg) - else: sys.stdout.write(term.format(msg, *attr)) + if CONFIG["argument.no_color"]: + sys.stdout.write(msg) + else: + sys.stdout.write(term.format(msg, *attr))
def print_divider(msg, is_header = False): attr = HEADER_ATTR if is_header else CATEGORY_ATTR @@ -98,7 +102,9 @@ def apply_filters(testing_output, *filters):
for result_filter in filters: line = result_filter(line_type, line) - if line is None: break + + if line is None: + break
if line is not None: results.append(line) @@ -110,8 +116,10 @@ def colorize(line_type, line_content): Applies escape sequences so each line is colored according to its type. """
- if CONFIG["argument.no_color"]: return line_content - else: return term.format(line_content, *LINE_ATTR[line_type]) + if CONFIG["argument.no_color"]: + return line_content + else: + return term.format(line_content, *LINE_ATTR[line_type])
def strip_module(line_type, line_content): """ @@ -120,7 +128,10 @@ def strip_module(line_type, line_content): """
m = re.match(".*( (.*?)).*", line_content) - if m: line_content = line_content.replace(m.groups()[0], "", 1) + + if m: + line_content = line_content.replace(m.groups()[0], "", 1) + return line_content
def align_results(line_type, line_content): @@ -129,7 +140,8 @@ def align_results(line_type, line_content): a bold attribute. """
- if line_type == LineType.CONTENT: return line_content + if line_type == LineType.CONTENT: + return line_content
# strip our current ending for ending in LINE_ENDINGS: diff --git a/test/prompt.py b/test/prompt.py index 32e75ab..afbd743 100644 --- a/test/prompt.py +++ b/test/prompt.py @@ -63,7 +63,9 @@ def stop(prompt = False): if tor_pid: if prompt: response = raw_input("\n" + STOP_CONFIRMATION) - if not response.lower() in ("y", "yes"): return + + if not response.lower() in ("y", "yes"): + return
os.kill(tor_pid, signal.SIGTERM)
@@ -84,7 +86,9 @@ def controller(): already running. """
- if not is_running(): start() + if not is_running(): + start() + controller = stem.control.Controller.from_port(control_port = CONTROL_PORT) controller.authenticate() return controller diff --git a/test/runner.py b/test/runner.py index af5ed73..dbfed24 100644 --- a/test/runner.py +++ b/test/runner.py @@ -207,7 +207,10 @@ def get_runner(): """
global INTEG_RUNNER - if not INTEG_RUNNER: INTEG_RUNNER = Runner() + + if not INTEG_RUNNER: + INTEG_RUNNER = Runner() + return INTEG_RUNNER
class _MockChrootFile(object): @@ -255,7 +258,9 @@ class Runner(object): with self._runner_lock: # if we're holding on to a tor process (running or not) then clean up after # it so we can start a fresh instance - if self._tor_process: self.stop() + + if self._tor_process: + self.stop()
test.output.print_line("Setting up a test instance...", *STATUS_ATTR)
@@ -273,7 +278,9 @@ class Runner(object):
if CONFIG["integ.target.relative_data_dir"]: tor_cwd = os.path.dirname(self._test_dir) - if not os.path.exists(tor_cwd): os.makedirs(tor_cwd) + + if not os.path.exists(tor_cwd): + os.makedirs(tor_cwd)
os.chdir(tor_cwd) data_dir_path = "./%s" % os.path.basename(self._test_dir) @@ -330,7 +337,8 @@ class Runner(object): os.kill(self._tor_process.pid, signal.SIGTERM) else: test.output.print_line("failed (unable to call kill() in python 2.5)", *ERROR_ATTR) - except OSError: pass + except OSError: + pass
self._tor_process.communicate() # blocks until the process is done
@@ -508,7 +516,8 @@ class Runner(object): control_socket = stem.socket.ControlPort(control_port = CONTROL_PORT) elif Torrc.SOCKET in self._custom_opts: control_socket = stem.socket.ControlSocketFile(CONTROL_SOCKET_PATH) - else: raise TorInaccessable("Unable to connect to tor") + else: + raise TorInaccessable("Unable to connect to tor")
if authenticate: stem.connection.authenticate(control_socket, CONTROL_PASSWORD, self.get_chroot()) @@ -547,7 +556,9 @@ class Runner(object):
tor_version = list(version_response)[0] tor_version = tor_version[8:] - if " " in tor_version: tor_version = tor_version.split(' ', 1)[0] + + if " " in tor_version: + tor_version = tor_version.split(' ', 1)[0]
return stem.version.Version(tor_version) except TorInaccessable: @@ -575,7 +586,8 @@ class Runner(object): with self._runner_lock: if self.is_running(): return self.__dict__[attr] - else: raise RunnerStopped() + else: + raise RunnerStopped()
def _run_setup(self): """ diff --git a/test/unit/descriptor/router_status_entry.py b/test/unit/descriptor/router_status_entry.py index 5d74678..9565702 100644 --- a/test/unit/descriptor/router_status_entry.py +++ b/test/unit/descriptor/router_status_entry.py @@ -208,7 +208,8 @@ class TestRouterStatusEntry(unittest.TestCase): # is that our validation doesn't catch the new SP restriction on V3 # entries.
- if value == "": value = None + if value == "": + value = None
self._expect_invalid_attr(content, "nickname", value)
diff --git a/test/unit/exit_policy/policy.py b/test/unit/exit_policy/policy.py index 12cc52a..dce4cb7 100644 --- a/test/unit/exit_policy/policy.py +++ b/test/unit/exit_policy/policy.py @@ -152,7 +152,8 @@ class TestExitPolicy(unittest.TestCase): else: self.fail() except ValueError: - if expect_success: self.fail() + if expect_success: + self.fail()
def test_microdescriptor_attributes(self): # checks that its is_accept attribute is properly set diff --git a/test/unit/util/system.py b/test/unit/util/system.py index a3c5e5a..e780375 100644 --- a/test/unit/util/system.py +++ b/test/unit/util/system.py @@ -82,8 +82,10 @@ def mock_call(base_cmd, responses):
def _mock_call(base_cmd, responses, command): if isinstance(responses, list): - if base_cmd == command: return responses - else: return None + if base_cmd == command: + return responses + else: + return None else: for cmd_completion in responses: if command == base_cmd % cmd_completion: