From fec11757d5535e3b186069b6b0d2285fc7d054f7 Mon Sep 17 00:00:00 2001 From: "Adam J. Stewart" Date: Sat, 2 Jun 2018 23:02:28 -0500 Subject: [PATCH] Fix coloring of error messages containing '}' symbol (#8277) --- lib/spack/llnl/util/tty/color.py | 31 ++++++++++++++++++++++------ lib/spack/spack/build_environment.py | 4 ++-- lib/spack/spack/util/log_parse.py | 6 +++--- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/lib/spack/llnl/util/tty/color.py b/lib/spack/llnl/util/tty/color.py index de26deceb2..3e40443a40 100644 --- a/lib/spack/llnl/util/tty/color.py +++ b/lib/spack/llnl/util/tty/color.py @@ -190,7 +190,7 @@ def __call__(self, match): string = styles[style] if color: if color not in colors: - raise ColorParseError("invalid color specifier: '%s' in '%s'" + raise ColorParseError("Invalid color specifier: '%s' in '%s'" % (color, match.string)) string += ';' + str(colors[color]) @@ -215,7 +215,9 @@ def colorize(string, **kwargs): codes, for output to non-console devices. """ color = _color_when_value(kwargs.get('color', get_color_when())) - return re.sub(color_re, match_to_ansi(color), string) + string = re.sub(color_re, match_to_ansi(color), string) + string = string.replace('}}', '}') + return string def clen(string): @@ -224,14 +226,14 @@ def clen(string): def cextra(string): - """"Length of extra color characters in a string""" + """Length of extra color characters in a string""" return len(''.join(re.findall(r'\033[^m]*m', string))) def cwrite(string, stream=sys.stdout, color=None): """Replace all color expressions in string with ANSI control codes and write the result to the stream. If color is - False, this will write plain text with o color. If True, + False, this will write plain text with no color. If True, then it will always write colored output. If not supplied, then it will be set based on stream.isatty(). """ @@ -246,8 +248,25 @@ def cprint(string, stream=sys.stdout, color=None): def cescape(string): - """Replace all @ with @@ in the string provided.""" - return str(string).replace('@', '@@') + """Escapes special characters needed for color codes. + + Replaces the following symbols with their equivalent literal forms: + + ===== ====== + ``@`` ``@@`` + ``}`` ``}}`` + ===== ====== + + Parameters: + string (str): the string to escape + + Returns: + (str): the string with color codes escaped + """ + string = str(string) + string = string.replace('@', '@@') + string = string.replace('}', '}}') + return string class ColorStream(object): diff --git a/lib/spack/spack/build_environment.py b/lib/spack/spack/build_environment.py index 59af563c92..400589b8a0 100644 --- a/lib/spack/spack/build_environment.py +++ b/lib/spack/spack/build_environment.py @@ -62,7 +62,7 @@ from six import StringIO import llnl.util.tty as tty -from llnl.util.tty.color import colorize +from llnl.util.tty.color import cescape, colorize from llnl.util.filesystem import mkdirp, install, install_tree import spack.build_systems.cmake @@ -801,7 +801,7 @@ def make_stack(tb, stack=None): marked = ' {0}{1:-6d}{2}'.format( mark, start + start_ctx + i, line.rstrip()) if is_error: - marked = colorize('@R{%s}' % marked) + marked = colorize('@R{%s}' % cescape(marked)) lines.append(marked) return lines diff --git a/lib/spack/spack/util/log_parse.py b/lib/spack/spack/util/log_parse.py index 34192fd6fd..a5a3dbb7f4 100644 --- a/lib/spack/spack/util/log_parse.py +++ b/lib/spack/spack/util/log_parse.py @@ -30,7 +30,7 @@ from ctest_log_parser import CTestLogParser, BuildError, BuildWarning import llnl.util.tty as tty -from llnl.util.tty.color import colorize +from llnl.util.tty.color import cescape, colorize __all__ = ['parse_log_events', 'make_log_context'] @@ -130,8 +130,8 @@ def make_log_context(log_events, width=None): wrapped_line = line_fmt % (i, '\n'.join(lines)) if i in error_lines: - out.write( - colorize(' @%s{>> %s}\n' % (color, wrapped_line))) + out.write(colorize( + ' @%s{>> %s}\n' % (color, cescape(wrapped_line)))) else: out.write(' %s\n' % wrapped_line)