commit e7513978c0a39fb815eecaff2f8d9a8c958236df Author: Damian Johnson atagar@torproject.org Date: Sat Apr 13 12:41:22 2013 -0700
Less verbose usage of the test.output module
We use the print_line() function throughout the runner and run_tests.py. Shortening it to 'println()' (pity we can't call it print()) and making its usage a little nicer by flattening the input attributes. --- run_tests.py | 59 +++++++++++++++++++++++++------------------------ test/integ/process.py | 1 - test/output.py | 57 +++++++++++++++++++++++++++++++++-------------- test/runner.py | 42 +++++++++++++++------------------- 4 files changed, 89 insertions(+), 70 deletions(-)
diff --git a/run_tests.py b/run_tests.py index 5e80441..4116e40 100755 --- a/run_tests.py +++ b/run_tests.py @@ -25,6 +25,7 @@ import test.output import test.runner import test.util
+from test.output import println, STATUS, ERROR, NO_NL from test.runner import Target
OPT = "auist:l:h" @@ -67,7 +68,7 @@ def _python3_setup(python3_destination, clean): shutil.rmtree(python3_destination, ignore_errors = True)
if os.path.exists(python3_destination): - test.output.print_error("Reusing '%s'. Run again with '--clean' if you want to recreate the python3 export." % python3_destination) + println("Reusing '%s'. Run again with '--clean' if you want to recreate the python3 export." % python3_destination, ERROR) print return True
@@ -81,21 +82,21 @@ def _python3_setup(python3_destination, clean): else: return []
- test.output.print_noline(" copying stem to '%s'... " % python3_destination, *test.runner.STATUS_ATTR) + println(" copying stem to '%s'... " % python3_destination, STATUS, NO_NL) shutil.copytree('stem', os.path.join(python3_destination, 'stem')) shutil.copytree('test', os.path.join(python3_destination, 'test'), ignore = _ignore) shutil.copy('run_tests.py', os.path.join(python3_destination, 'run_tests.py')) - test.output.print_line("done", *test.runner.STATUS_ATTR) + println("done", STATUS) except OSError, exc: - test.output.print_error("failed\n%s" % exc) + println("failed\n%s" % exc, ERROR) return False
try: - test.output.print_noline(" running 2to3... ", *test.runner.STATUS_ATTR) + println(" running 2to3... ", STATUS, NO_NL) system.call("2to3 --write --nobackups --no-diffs %s" % python3_destination) - test.output.print_line("done", *test.runner.STATUS_ATTR) + println("done", STATUS) except OSError, exc: - test.output.print_error("failed\n%s" % exc) + println("failed\n%s" % exc, ERROR) return False
return True @@ -112,23 +113,23 @@ def _print_static_issues(run_unit, run_integ, run_style): if system.is_available("pyflakes"): static_check_issues.update(test.util.get_pyflakes_issues(SOURCE_BASE_PATHS)) else: - test.output.print_error("Static error checking requires pyflakes. Please install it from ...\n http://pypi.python.org/pypi/pyflakes%5Cn") + println("Static error checking requires pyflakes. Please install it from ...\n http://pypi.python.org/pypi/pyflakes%5Cn", ERROR)
if run_style: if system.is_available("pep8"): static_check_issues = test.util.get_stylistic_issues(SOURCE_BASE_PATHS) else: - test.output.print_error("Style checks require pep8. Please install it from...\n http://pypi.python.org/pypi/pep8%5Cn") + println("Style checks require pep8. Please install it from...\n http://pypi.python.org/pypi/pep8%5Cn", ERROR)
if static_check_issues: - test.output.print_line("STATIC CHECKS", term.Color.BLUE, term.Attr.BOLD) + println("STATIC CHECKS", term.Color.BLUE, term.Attr.BOLD)
for file_path in static_check_issues: - test.output.print_line("* %s" % file_path, term.Color.BLUE, term.Attr.BOLD) + println("* %s" % file_path, term.Color.BLUE, term.Attr.BOLD)
for line_number, msg in static_check_issues[file_path]: line_count = "%-4s" % line_number - test.output.print_line(" line %s - %s" % (line_count, msg)) + println(" line %s - %s" % (line_count, msg))
@@ -259,7 +260,7 @@ if __name__ == '__main__': if run_python3: for required_cmd in ("2to3", "python3"): if not system.is_available(required_cmd): - test.output.print_error("Unable to test python 3 because %s isn't in your path" % required_cmd) + println("Unable to test python 3 because %s isn't in your path" % required_cmd, ERROR) sys.exit(1)
if run_python3 and sys.version_info[0] != 3: @@ -273,7 +274,7 @@ if __name__ == '__main__': sys.exit(1) # failed to do python3 setup
if not run_unit and not run_integ and not run_style: - test.output.print_line("Nothing to run (for usage provide --help)\n") + println("Nothing to run (for usage provide --help)\n") sys.exit()
# if we have verbose logging then provide the testing config @@ -297,18 +298,18 @@ if __name__ == '__main__':
test.output.print_divider("INITIALISING", True)
- test.output.print_line("Performing startup activities...", *test.runner.STATUS_ATTR) - test.output.print_noline(" checking for orphaned .pyc files... ", *test.runner.STATUS_ATTR) + println("Performing startup activities...", STATUS) + println(" checking for orphaned .pyc files... ", STATUS, NO_NL)
orphaned_pyc = test.util.clean_orphaned_pyc(SOURCE_BASE_PATHS)
if not orphaned_pyc: # no orphaned files, nothing to do - test.output.print_line("done", *test.runner.STATUS_ATTR) + println("done", STATUS) else: print for pyc_file in orphaned_pyc: - test.output.print_error(" removed %s" % pyc_file) + println(" removed %s" % pyc_file, ERROR)
@@ -364,12 +365,12 @@ if __name__ == '__main__': if opt in test.runner.Torrc.keys(): torrc_opts.append(test.runner.Torrc[opt]) else: - test.output.print_line("'%s' isn't a test.runner.Torrc enumeration" % opt) + println("'%s' isn't a test.runner.Torrc enumeration" % opt) sys.exit(1)
integ_runner.start(target, attribute_targets, tor_path, extra_torrc_opts = torrc_opts)
- test.output.print_line("Running tests...", term.Color.BLUE, term.Attr.BOLD) + println("Running tests...", term.Color.BLUE, term.Attr.BOLD) print
for test_class in test.util.get_integ_tests(test_prefix): @@ -391,15 +392,15 @@ if __name__ == '__main__': active_threads = threading.enumerate()
if len(active_threads) > 1: - test.output.print_error("Threads lingering after test run:") + println("Threads lingering after test run:", ERROR)
for lingering_thread in active_threads: - test.output.print_error(" %s" % lingering_thread) + println(" %s" % lingering_thread, ERROR)
testing_failed = True break except KeyboardInterrupt: - test.output.print_error(" aborted starting tor: keyboard interrupt\n") + println(" aborted starting tor: keyboard interrupt\n", ERROR) break except OSError: testing_failed = True @@ -411,7 +412,7 @@ if __name__ == '__main__':
for target in skip_targets: req_version = stem.version.Requirement[CONFIG["target.prereq"][target]] - test.output.print_line("Unable to run target %s, this requires tor version %s" % (target, req_version), term.Color.RED, term.Attr.BOLD) + println("Unable to run target %s, this requires tor version %s" % (target, req_version), ERROR)
@@ -430,16 +431,16 @@ if __name__ == '__main__': has_error = testing_failed or error_tracker.has_error_occured()
if has_error: - test.output.print_error("TESTING FAILED %s" % runtime_label) + println("TESTING FAILED %s" % runtime_label, ERROR)
for line in error_tracker: - test.output.print_error(" %s" % line) + println(" %s" % line, ERROR) elif skipped_test_count > 0: - test.output.print_line("%i TESTS WERE SKIPPED" % skipped_test_count, term.Color.BLUE, term.Attr.BOLD) - test.output.print_line("ALL OTHER TESTS PASSED %s" % runtime_label, term.Color.GREEN, term.Attr.BOLD) + println("%i TESTS WERE SKIPPED" % skipped_test_count, term.Color.BLUE, term.Attr.BOLD) + println("ALL OTHER TESTS PASSED %s" % runtime_label, term.Color.GREEN, term.Attr.BOLD) print else: - test.output.print_line("TESTING PASSED %s" % runtime_label, term.Color.GREEN, term.Attr.BOLD) + println("TESTING PASSED %s" % runtime_label, term.Color.GREEN, term.Attr.BOLD) print
sys.exit(1 if has_error else 0) diff --git a/test/integ/process.py b/test/integ/process.py index 414d233..3429adf 100644 --- a/test/integ/process.py +++ b/test/integ/process.py @@ -4,7 +4,6 @@ Tests the stem.process functions with various use cases.
import os import shutil -import signal import subprocess import tempfile import time diff --git a/test/output.py b/test/output.py index 22f3605..b39e650 100644 --- a/test/output.py +++ b/test/output.py @@ -18,7 +18,14 @@ COLOR_SUPPORT = sys.stdout.isatty() and not system.is_windows() DIVIDER = "=" * 70 HEADER_ATTR = (term.Color.CYAN, term.Attr.BOLD) CATEGORY_ATTR = (term.Color.GREEN, term.Attr.BOLD) -ERROR_ATTR = (term.Color.RED, term.Attr.BOLD) + +NO_NL = "no newline" + +# formatting for various categories of messages + +STATUS = (term.Color.BLUE, term.Attr.BOLD) +SUBSTATUS = (term.Color.BLUE, ) +ERROR = (term.Color.RED, term.Attr.BOLD)
LineType = stem.util.enum.Enum("OK", "FAIL", "ERROR", "SKIPPED", "CONTENT")
@@ -38,41 +45,40 @@ LINE_ATTR = { }
-def print_line(msg, *attr): - if COLOR_SUPPORT: - msg = term.format(msg, *attr) - - print msg +def println(msg, *attr): + attr = _flatten(attr) + no_newline = False
+ if NO_NL in attr: + no_newline = True + attr.remove(NO_NL)
-def print_noline(msg, *attr): if COLOR_SUPPORT: msg = term.format(msg, *attr)
- sys.stdout.write(msg) - sys.stdout.flush() - - -def print_error(msg): - print_line(msg, *ERROR_ATTR) + if no_newline: + sys.stdout.write(msg) + sys.stdout.flush() + else: + print msg
def print_divider(msg, is_header = False): attr = HEADER_ATTR if is_header else CATEGORY_ATTR - print_line("%s\n%s\n%s\n" % (DIVIDER, msg.center(70), DIVIDER), *attr) + println("%s\n%s\n%s\n" % (DIVIDER, msg.center(70), DIVIDER), *attr)
def print_logging(logging_buffer): if not logging_buffer.is_empty(): for entry in logging_buffer: - print_line(entry.replace("\n", "\n "), term.Color.MAGENTA) + println(entry.replace("\n", "\n "), term.Color.MAGENTA)
def print_config(test_config): print_divider("TESTING CONFIG", True) - print_line("Test configuration... ", term.Color.BLUE, term.Attr.BOLD) + println("Test configuration... ", term.Color.BLUE, term.Attr.BOLD)
for config_key in test_config.keys(): key_entry = " %s => " % config_key @@ -81,7 +87,7 @@ def print_config(test_config): value_div = ",\n" + (" " * len(key_entry)) value_entry = value_div.join(test_config.get_value(config_key, multiple = True))
- print_line(key_entry + value_entry, term.Color.BLUE) + println(key_entry + value_entry, term.Color.BLUE)
@@ -225,3 +231,20 @@ class ErrorTracker(object): def __iter__(self): for error_line in self._errors: yield error_line + + +def _flatten(seq): + # Flattens nested collections into a single list. For instance... + # + # >>> _flatten([1, [2, 3], 4]) + # [1, 2, 3, 4] + + result = [] + + for item in seq: + if (isinstance(item, (tuple, list))): + result.extend(_flatten(item)) + else: + result.append(item) + + return result diff --git a/test/runner.py b/test/runner.py index bcff7a0..2de1852 100644 --- a/test/runner.py +++ b/test/runner.py @@ -42,7 +42,6 @@ about the tor test instance they're running against. import logging import os import shutil -import signal import stat import tempfile import threading @@ -57,7 +56,7 @@ import stem.util.enum import stem.version import test.output
-from stem.util import term +from test.output import println, STATUS, SUBSTATUS, NO_NL
CONFIG = stem.util.conf.config_dict("test", { "integ.test_directory": "./test/data", @@ -79,9 +78,6 @@ Target = stem.util.enum.UppercaseEnum( "RUN_ALL", )
-STATUS_ATTR = (term.Color.BLUE, term.Attr.BOLD) -SUBSTATUS_ATTR = (term.Color.BLUE, ) - SOCKS_HOST = "127.0.0.1" SOCKS_PORT = 1112
@@ -295,7 +291,7 @@ class Runner(object): if self._tor_process: self.stop()
- test.output.print_line("Setting up a test instance...", *STATUS_ATTR) + println("Setting up a test instance...", STATUS)
# if 'test_directory' is unset then we make a new data directory in /tmp # and clean it up when we're done @@ -357,7 +353,7 @@ class Runner(object): """
with self._runner_lock: - test.output.print_noline("Shutting down tor... ", *STATUS_ATTR) + println("Shutting down tor... ", STATUS, NO_NL)
if self._tor_process: # if the tor process has stopped on its own then the following raises @@ -386,7 +382,7 @@ class Runner(object): self._custom_opts = None self._tor_process = None
- test.output.print_line("done", *STATUS_ATTR) + println("done", STATUS)
def is_running(self): """ @@ -631,13 +627,13 @@ class Runner(object):
# makes a temporary data directory if needed try: - test.output.print_noline(" making test directory (%s)... " % self._test_dir, *STATUS_ATTR) + println(" making test directory (%s)... " % self._test_dir, STATUS, NO_NL)
if os.path.exists(self._test_dir): - test.output.print_line("skipped", *STATUS_ATTR) + println("skipped", STATUS) else: os.makedirs(self._test_dir) - test.output.print_line("done", *STATUS_ATTR) + println("done", STATUS) except OSError, exc: test.output.print_error("failed (%s)" % exc) raise exc @@ -649,16 +645,16 @@ class Runner(object): if Torrc.SOCKET in self._custom_opts: try: socket_dir = os.path.dirname(CONTROL_SOCKET_PATH) - test.output.print_noline(" making control socket directory (%s)... " % socket_dir, *STATUS_ATTR) + println(" making control socket directory (%s)... " % socket_dir, STATUS, NO_NL)
if os.path.exists(socket_dir) and stat.S_IMODE(os.stat(socket_dir).st_mode) == 0700: - test.output.print_line("skipped", *STATUS_ATTR) + println("skipped", STATUS) else: if not os.path.exists(socket_dir): os.makedirs(socket_dir)
os.chmod(socket_dir, 0700) - test.output.print_line("done", *STATUS_ATTR) + println("done", STATUS) except OSError, exc: test.output.print_error("failed (%s)" % exc) raise exc @@ -668,7 +664,7 @@ class Runner(object):
if logging_path: logging_path = stem.util.system.expand_path(logging_path, STEM_BASE) - test.output.print_noline(" configuring logger (%s)... " % logging_path, *STATUS_ATTR) + println(" configuring logger (%s)... " % logging_path, STATUS, NO_NL)
# delete the old log if os.path.exists(logging_path): @@ -681,23 +677,23 @@ class Runner(object): datefmt = '%D %H:%M:%S', )
- test.output.print_line("done", *STATUS_ATTR) + println("done", STATUS) else: - test.output.print_line(" configuring logger... skipped", *STATUS_ATTR) + println(" configuring logger... skipped", STATUS)
# writes our testing torrc torrc_dst = os.path.join(self._test_dir, "torrc") try: - test.output.print_noline(" writing torrc (%s)... " % torrc_dst, *STATUS_ATTR) + println(" writing torrc (%s)... " % torrc_dst, STATUS, NO_NL)
torrc_file = open(torrc_dst, "w") torrc_file.write(self._torrc_contents) torrc_file.close()
- test.output.print_line("done", *STATUS_ATTR) + println("done", STATUS)
for line in self._torrc_contents.strip().splitlines(): - test.output.print_line(" %s" % line.strip(), *SUBSTATUS_ATTR) + println(" %s" % line.strip(), SUBSTATUS)
print except Exception, exc: @@ -714,7 +710,7 @@ class Runner(object): :raises: OSError if we either fail to create the tor process or reached a timeout without success """
- test.output.print_line("Starting tor...\n", *STATUS_ATTR) + println("Starting tor...\n", STATUS) start_time = time.time()
try: @@ -723,13 +719,13 @@ class Runner(object): complete_percent = 100 if Target.ONLINE in self.attribute_targets else 5
# prints output from tor's stdout while it starts up - print_init_line = lambda line: test.output.print_line(" %s" % line, *SUBSTATUS_ATTR) + print_init_line = lambda line: println(" %s" % line, SUBSTATUS)
torrc_dst = os.path.join(self._test_dir, "torrc") self._tor_process = stem.process.launch_tor(tor_cmd, None, torrc_dst, complete_percent, print_init_line)
runtime = time.time() - start_time - test.output.print_line(" done (%i seconds)\n" % runtime, *STATUS_ATTR) + println(" done (%i seconds)\n" % runtime, STATUS) except OSError, exc: test.output.print_error(" failed to start tor: %s\n" % exc) raise exc
tor-commits@lists.torproject.org