Auto merge of #8551 - mrobinson:blessings, r=jgraham

Use blessings when possible for WPT UI

Use blessings when it is possible for the WPT UI and fall back to using
raw control characters. This also fixes a bug where the UI didn't work
correctly in iTerm.app. Remove the one line version of the UI, since it
is no longer used as the iTerm fallback.

<!-- Reviewable:start -->
[<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/8551)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2015-11-17 22:56:34 +05:30
commit d7c98f86ff

View file

@ -7,6 +7,9 @@ import collections
import os import os
import sys import sys
DEFAULT_MOVE_UP_CODE = u"\x1b[A"
DEFAULT_CLEAR_EOL_CODE = u"\x1b[K"
class GroupingFormatter(base.BaseFormatter): class GroupingFormatter(base.BaseFormatter):
"""Formatter designed to produce unexpected test results grouped """Formatter designed to produce unexpected test results grouped
@ -17,16 +20,15 @@ class GroupingFormatter(base.BaseFormatter):
self.need_to_erase_last_line = False self.need_to_erase_last_line = False
self.current_display = "" self.current_display = ""
self.running_tests = {} self.running_tests = {}
self.last_test_finished = "Running tests..."
self.test_output = collections.defaultdict(str) self.test_output = collections.defaultdict(str)
self.subtest_failures = collections.defaultdict(list) self.subtest_failures = collections.defaultdict(list)
self.test_failure_text = "" self.test_failure_text = ""
self.tests_with_failing_subtests = [] self.tests_with_failing_subtests = []
self.interactive = os.isatty(sys.stdout.fileno()) self.interactive = os.isatty(sys.stdout.fileno())
# iTerm2 doesn't support the terminal codes used to erase previous lines, # TODO(mrobinson, 8313): We need to add support for Windows terminals here.
# so only print one line and rely only on backspace characters. if self.interactive:
self.one_line = os.environ.get("TERM_PROGRAM", "") == "iTerm.app" self.move_up, self.clear_eol = self.get_move_up_and_clear_eol_codes()
self.expected = { self.expected = {
'OK': 0, 'OK': 0,
@ -47,16 +49,25 @@ class GroupingFormatter(base.BaseFormatter):
'CRASH': [], 'CRASH': [],
} }
def get_move_up_and_clear_eol_codes(self):
try:
import blessings
except ImportError:
return DEFAULT_MOVE_UP_CODE, DEFAULT_CLEAR_EOL_CODE
try:
self.terminal = blessings.Terminal()
return self.terminal.clear_eol, self.terminal.move_up
except Exception as exception:
sys.stderr.write("GroupingFormatter: Could not get terminal "
"control characters: %s\n" % exception)
return DEFAULT_MOVE_UP_CODE, DEFAULT_CLEAR_EOL_CODE
def text_to_erase_display(self): def text_to_erase_display(self):
if not self.interactive or not self.current_display: if not self.interactive or not self.current_display:
return "" return ""
return ((self.move_up + self.clear_eol) *
# TODO(mrobinson, 8313): We need to add support for Windows terminals here. len(self.current_display.splitlines()))
erase_length = len(self.current_display)
if self.one_line:
return "\b \b" * erase_length
else:
return ("\033[F" + "\033[K") * len(self.current_display.splitlines())
def generate_output(self, text=None, new_display=None): def generate_output(self, text=None, new_display=None):
if not self.interactive: if not self.interactive:
@ -75,9 +86,6 @@ class GroupingFormatter(base.BaseFormatter):
else: else:
new_display = " [%i/%i] " % (self.completed_tests, self.number_of_tests) new_display = " [%i/%i] " % (self.completed_tests, self.number_of_tests)
if self.one_line:
return new_display + self.last_test_finished
if self.running_tests: if self.running_tests:
indent = " " * len(new_display) indent = " " * len(new_display)
return new_display + ("\n%s" % indent).join( return new_display + ("\n%s" % indent).join(
@ -175,7 +183,6 @@ class GroupingFormatter(base.BaseFormatter):
subtest_failures = self.subtest_failures.pop(test_name, []) subtest_failures = self.subtest_failures.pop(test_name, [])
del self.running_tests[data['thread']] del self.running_tests[data['thread']]
self.last_test_finished = test_name
new_display = self.build_status_line() new_display = self.build_status_line()
if not had_unexpected_test_result and not subtest_failures: if not had_unexpected_test_result and not subtest_failures: