def testHomogenizedColorizerSortAscii(self): colors = [ console_attr.Colorizer('RED', 'red'), console_attr.Colorizer('GREEN', 'green'), console_attr.Colorizer('BLUE', 'blue'), console_attr.Colorizer('YELLOW', 'yellow'), ] expected = [colors[2], colors[1], colors[0], colors[3]] actual = sorted(colors) self.assertEqual(expected, actual)
def testMixedColorizerSortScreen(self): colors = [ console_attr.Colorizer('RED', 'red'), 'GREEN', console_attr.Colorizer('BLUE', 'blue'), 'YELLOW', ] expected = [colors[2], colors[1], colors[0], colors[3]] actual = sorted(colors) self.assertEqual(expected, actual)
def TransformColor(r, red=None, yellow=None, green=None, blue=None, **kwargs): """Colorizes the resource string value. The *red*, *yellow*, *green* and *blue* args are RE patterns, matched against the resource in order. The first pattern that matches colorizes the matched substring with that color, and the other patterns are skipped. Args: r: A JSON-serializable object. red: The substring pattern for the color red. yellow: The substring pattern for the color yellow. green: The substring pattern for the color green. blue: The substring pattern for the color blue. **kwargs: console_attr.Colorizer() kwargs. Returns: A console_attr.Colorizer() object if any color substring matches, r otherwise. Example: `color(red=STOP,yellow=CAUTION,green=GO)`::: For the resource string "CAUTION means GO FASTER" displays the substring "CAUTION" in yellow. """ string = unicode(r) for color, pattern in (('red', red), ('yellow', yellow), ('green', green), ('blue', blue)): if pattern and re.search(pattern, string): return console_attr.Colorizer(string, color, **kwargs) return string
def testColorizerBlueScreen(self): colorize = console_attr.Colorizer(self._TEST, 'blue') self.assertEqual(self._TEST, str(colorize)) self.assertEqual(len(self._TEST), len(colorize)) colorize.Render(self.buf) self.assertEqual('\x1b[34;1m{0}\x1b[39;0m'.format(self._TEST), self.buf.getvalue())
def testColorizerYellowLeftScreen(self): colorize = console_attr.Colorizer(self._TEST, 'yellow') self.assertEqual(self._TEST, str(colorize)) self.assertEqual(len(self._TEST), len(colorize)) colorize.Render(self.buf, justify=lambda s: s.ljust(len(s) + 5)) self.assertEqual('\x1b[33;1m{0} \x1b[39;0m'.format(self._TEST), self.buf.getvalue())
def testSplitIntoNormalAndControlAscii(self): self.buf.write('This is a line constructed from ') console_attr.Colorizer('colorized', 'red').Render(self.buf) self.buf.write(' parts and long enough to be split into ') console_attr.Colorizer('multiple', 'blue').Render(self.buf) self.buf.write(' lines at ') console_attr.Colorizer('width=20', 'green').Render(self.buf) self.buf.write('.\n') line = self.buf.getvalue() expected = [ ('This is a line constructed from colorized parts and long enough to ' 'be split into multiple lines at width=20.\n', ''), ] actual = self._con.SplitIntoNormalAndControl(line) self.assertEqual(expected, actual)
def testColorizerGreenRightScreen(self): colorize = console_attr.Colorizer( self._TEST, 'green', justify=lambda s: s.rjust(len(s) + 5)) self.assertEqual(self._TEST, str(colorize)) self.assertEqual(len(self._TEST), len(colorize)) colorize.Render(self.buf) self.assertEqual('\x1b[32m {0}\x1b[39;0m'.format(self._TEST), self.buf.getvalue())
def testColorizerRedCenterScreen(self): colorize = console_attr.Colorizer( self._TEST, 'red', justify=lambda s: s.center(len(s) + 5)) self.assertEqual(self._TEST, str(colorize)) self.assertEqual(len(self._TEST), len(colorize)) colorize.Render(self.buf) self.assertEqual('\x1b[31;1m {0} \x1b[39;0m'.format(self._TEST), self.buf.getvalue())
def testSplitLineScreen(self): self.buf.write('This is a line constructed from ') console_attr.Colorizer('colorized', 'red').Render(self.buf) self.buf.write(' parts and long enough to be split into ') console_attr.Colorizer('multiple', 'blue').Render(self.buf) self.buf.write(' lines at ') console_attr.Colorizer('width=32', 'green').Render(self.buf) self.buf.write('.\n') line = self.buf.getvalue() lines = self._con.SplitLine(line, width=32) self.assertEqual(4, len(lines)) expected = [ ('This is a line constructed from ', '\x1b[31;1m'), ] actual = self._con.SplitIntoNormalAndControl(lines[0]) self.assertEqual(expected, actual) expected = [ ('colorized', '\x1b[39;0m'), (' parts and long enough ', ''), ] actual = self._con.SplitIntoNormalAndControl(lines[1]) self.assertEqual(expected, actual) expected = [ ('to be split into ', '\x1b[34;1m'), ('multiple', '\x1b[39;0m'), (' lines ', ''), ] actual = self._con.SplitIntoNormalAndControl(lines[2]) self.assertEqual(expected, actual) expected = [ ('at ', '\x1b[32m'), ('width=32', '\x1b[39;0m'), ('.\n', ''), ] actual = self._con.SplitIntoNormalAndControl(lines[3]) self.assertEqual(expected, actual)
def TransformColor(r, red=None, yellow=None, green=None, blue=None, **kwargs): """Colorizes the resource string value. The resource string is searched for an RE pattern match in Roy.G.Biv order. The first pattern that matches colorizes the resource string with that color. Args: r: A JSON-serializable object. red: Color red resource value pattern. yellow: Color yellow resource value pattern. green: Color green resource value pattern. blue: Color blue resource value pattern. **kwargs: console_attr.Colorizer() kwargs. Returns: A console_attr.Colorizer() object if any color substring matches, r otherwise. """ string = unicode(r) for color, pattern in (('red', red), ('yellow', yellow), ('green', green), ('blue', blue)): if pattern and re.search(pattern, string): return console_attr.Colorizer(string, color, **kwargs) return string
def Finish(self): """Prints the table.""" if not self._rows: # Table is empty. return if self._aggregate: # No parent columns, only nested formats. Aggregate each subformat # column to span all records. self._empty = True for subformat in self._subformats: for row in self._rows: record = row[subformat.index] if record: subformat.printer.Print(record, intermediate=True) subformat.printer.Finish() if subformat.printer.ResourcesWerePrinted(): self._empty = False return # Border box decorations. all_box = 'all-box' in self.attributes if all_box or 'box' in self.attributes: box = self._console_attr.GetBoxLineCharacters() table_column_pad = 1 else: box = None table_column_pad = self.attributes.get('pad', _TABLE_COLUMN_PAD) if self._page_count > 1: self._out.write('\n') # Stringify all column cells for all rows. rows = [[_Stringify(cell) for cell in row] for row in self._rows] if not self._has_subprinters: self._rows = [] # Sort by columns if requested. if self.column_attributes: # Order() is a list of (key,reverse) tuples from highest to lowest key # precedence. This loop partitions the keys into groups with the same # reverse value. The groups are then applied in reverse order to maintain # the original precedence. groups = [] # [(keys, reverse)] LIFO to preserve precedence keys = [] # keys for current group for key_index, key_reverse in self.column_attributes.Order(): if not keys: # This only happens the first time through the loop. reverse = key_reverse if reverse != key_reverse: groups.insert(0, (keys, reverse)) keys = [] reverse = key_reverse keys.append(key_index) if keys: groups.insert(0, (keys, reverse)) for keys, reverse in groups: rows = sorted(rows, key=operator.itemgetter(*keys), reverse=reverse) align = self.column_attributes.Alignments() else: align = None # Remove the hidden/subformat alignments and columns from rows. if self._visible: rows = [self._Visible(row) for row in rows] align = self._Visible(align) # Determine the max column widths of heading + rows heading = [] if 'no-heading' not in self.attributes: if self._heading: labels = self._heading elif self.column_attributes: labels = self._Visible(self.column_attributes.Labels()) else: labels = None if labels: if self._subformats: cells = [] for subformat in self._subformats: if not subformat.printer and subformat.index < len(labels): cells.append(_Stringify(labels[subformat.index])) heading = [cells] else: heading = [[_Stringify(cell) for cell in labels]] col_widths = [0] * max(len(x) for x in rows + heading) for row in rows: for i, col in enumerate(row): col_widths[i] = max(col_widths[i], self._console_attr.DisplayWidth(col)) if self._optional: # Delete optional columns that have no data. optional = False visible = [] # col_widths[i] == 0 => column i has no data. for i, col in enumerate(self._Visible(self.column_attributes.Columns())): if not col.attribute.optional or col_widths[i]: visible.append(i) else: optional = True if optional: # At least one optional column has no data. Adjust all column lists. if not visible: # All columns are optional and have no data => no output. self._empty = True return self._visible = visible rows = [self._Visible(row) for row in rows] align = self._Visible(align) heading = [self._Visible(heading[0])] col_widths = self._Visible(col_widths) if heading: # Check the heading widths too. for i, col in enumerate(heading[0]): col_widths[i] = max(col_widths[i], self._console_attr.DisplayWidth(col)) # If table is wider than the console and columns can be wrapped, # change wrapped column widths to fit within the available space. wrap = [] for i, col in enumerate(self._Visible(self.column_attributes.Columns())): if col.attribute.wrap: wrap.append(i) if wrap: visible_cols = len(self._Visible(self.column_attributes.Columns())) table_padding = (visible_cols - 1) * table_column_pad if box: table_padding = (_BOX_CHAR_LENGTH * (visible_cols + 1) + visible_cols * table_column_pad * 2) total_col_width = self._console_attr.GetTermSize()[0] - table_padding if total_col_width < sum(col_widths): non_wrappable_width = sum( [col_width for (i, col_width) in enumerate(col_widths) if i not in wrap]) available_width = total_col_width - non_wrappable_width for i, col_width in enumerate(col_widths): if i in wrap: col_widths[i] = max(int((available_width * 1.0)/len(wrap)), 1) # Print the title if specified. title = self.attributes.get('title') if self._page_count <= 1 else None if title is not None: if box: line = box.dr width = 0 sep = 2 for i in range(len(col_widths)): width += col_widths[i] if box: line += box.h * (col_widths[i] + sep) sep = 3 if width < self._console_attr.DisplayWidth(title) and not wrap: # Title is wider than the table => pad each column to make room. pad = ((self._console_attr.DisplayWidth(title) + len(col_widths) - 1) / len(col_widths)) width += len(col_widths) * pad if box: line += box.h * len(col_widths) * pad for i in range(len(col_widths)): col_widths[i] += pad if box: width += 3 * len(col_widths) - 1 line += box.dl self._out.write(line) self._out.write('\n') line = u'{0}{1}{2}'.format( box.v, _Justify(self._console_attr, title).center(width), box.v) else: width += table_column_pad * (len(col_widths) - 1) line = _Justify(self._console_attr, title).center(width).rstrip() self._out.write(line) self._out.write('\n') # Set up box borders. if box: t_sep = box.vr if title else box.dr m_sep = box.vr b_sep = box.ur t_rule = '' m_rule = '' b_rule = '' for i in range(len(col_widths)): cell = box.h * (col_widths[i] + 2) t_rule += t_sep + cell t_sep = box.hd m_rule += m_sep + cell m_sep = box.vh b_rule += b_sep + cell b_sep = box.hu t_rule += box.vl if title else box.dl m_rule += box.vl b_rule += box.ul self._out.write(t_rule) self._out.write('\n') if heading: line = [] row = heading[0] heading = [] for i in range(len(row)): line.append(box.v) line.append(row[i].center(col_widths[i])) line.append(box.v) self._out.write(u' '.join(line)) self._out.write('\n') self._out.write(m_rule) self._out.write('\n') # Print the left-adjusted columns with space stripped from rightmost column. # We must flush directly to the output just in case there is a Windows-like # colorizer. This complicates the trailing space logic. first = True for row in heading + rows: if first: first = False elif box: if self._subformats: self._out.write(t_rule) self._out.write('\n') elif all_box: self._out.write(m_rule) self._out.write('\n') row_finished = False while not row_finished: pad = 0 row_finished = True for i in range(len(row)): width = col_widths[i] if box: self._out.write(box.v + ' ') justify = align[i] if align else lambda s, w: s.ljust(w) # Wrap text if needed. s = row[i] is_colorizer = isinstance(s, console_attr.Colorizer) if self._console_attr.DisplayWidth(s) > width or '\n' in unicode(s): cell_value, remainder = self._GetNextLineAndRemainder( unicode(s), width, include_all_whitespace=is_colorizer) if is_colorizer: # pylint:disable=protected-access cell = console_attr.Colorizer(cell_value, s._color, s._justify) row[i] = console_attr.Colorizer(remainder, s._color, s._justify) # pylint:disable=protected-access else: cell = cell_value row[i] = remainder if remainder: row_finished = False else: cell = s row[i] = ' ' if not box and i == len(row) - 1: width = 0 if is_colorizer: if pad: self._out.write(' ' * pad) pad = 0 # pylint: disable=cell-var-from-loop cell.Render(justify=lambda s: justify(s, width)) if box: self._out.write(' ' * table_column_pad) else: pad = table_column_pad else: value = justify(_Justify(self._console_attr, cell), width) if box: self._out.write(value) self._out.write(' ' * table_column_pad) elif value.strip(): if pad: self._out.write(' ' * pad) pad = 0 stripped = value.rstrip() self._out.write(stripped) pad = (table_column_pad + self._console_attr.DisplayWidth(value) - self._console_attr.DisplayWidth(stripped)) else: pad += table_column_pad + self._console_attr.DisplayWidth(value) if box: self._out.write(box.v) if self._rows: self._out.write('\n') if heading: heading = [] continue if row_finished: if box: self._out.write(b_rule) self._out.write('\n') r = self._rows.pop(0) for subformat in self._subformats: if subformat.printer: # Indent the nested printer lines. subformat.printer.Print(r[subformat.index]) nested_output = subformat.out.getvalue() for line in nested_output.split('\n')[:-1]: self._out.write(' ' + line + '\n') # Rewind the output buffer. subformat.out.truncate(0) else: self._out.write('\n') if box and not self._subformats: self._out.write(b_rule) self._out.write('\n')
def Finish(self): """Prints the table.""" if not self._rows: # Table is empty. return if self._aggregate: # No parent columns, only nested formats. Aggregate each subformat # column to span all records. self._empty = True for subformat in self._subformats: for row in self._rows: record = row[subformat.index] if record: subformat.printer.Print(record, intermediate=True) subformat.printer.Finish() if subformat.printer.ResourcesWerePrinted(): self._empty = False return # Border box decorations. all_box = 'all-box' in self.attributes if all_box or 'box' in self.attributes: box = self._console_attr.GetBoxLineCharacters() table_column_pad = 1 else: box = None table_column_pad = self.attributes.get('pad', _TABLE_COLUMN_PAD) # Sort by columns if requested. rows = self._rows if self.column_attributes: # Order() is a list of (key,reverse) tuples from highest to lowest key # precedence. This loop partitions the keys into groups with the same # reverse value. The groups are then applied in reverse order to maintain # the original precedence. groups = [] # [(keys, reverse)] LIFO to preserve precedence keys = [] # keys for current group for key_index, key_reverse in self.column_attributes.Order(): if not keys: # This only happens the first time through the loop. reverse = key_reverse if reverse != key_reverse: groups.insert(0, (keys, reverse)) keys = [] reverse = key_reverse keys.append(key_index) if keys: groups.insert(0, (keys, reverse)) for keys, reverse in groups: # For reverse sort of multiple keys we reverse the entire table, sort by # each key ascending, and then reverse the entire table again. If we # sorted by each individual column in descending order, we would end up # flip-flopping between ascending and descending as we went. if reverse: rows = reversed(rows) for key in reversed(keys): decorated = [(_Numify(row[key]), _Stringify(row[key]), i, row) for i, row in enumerate(rows)] decorated.sort() rows = [row for _, _, _, row in decorated] if reverse: rows = reversed(rows) align = self.column_attributes.Alignments() else: align = None # Flatten the table under screen reader mode for accessibility, # ignore box wrappers if any. screen_reader = properties.VALUES.accessibility.screen_reader.GetBool() if screen_reader: # Print the title if specified. title = self.attributes.get('title') if title is not None: self._out.write(title) self._out.write('\n\n') # Get indexes of all columns with no data if self._optional: # Delete optional columns that have no data. optional = False visible = [] for i, col in enumerate( self._Visible(self.column_attributes.Columns())): if not col.attribute.optional: visible.append(i) else: optional = True if optional: # At least one optional column has no data. Adjust all column lists. if not visible: # All columns are optional and have no data => no output. self._empty = True return self._visible = visible labels = self._GetVisibleLabels() subs = self._GetSubformatIndexes() # Print items for i, row in enumerate(rows): if i: self._out.write('\n') for j in range(len(row)): # Skip columns that have no data in entire column if self._visible is not None and j not in self._visible: continue # Skip columns with subformats, which will be printed lastly if j in subs: continue content = six.text_type(_Stringify(row[j])) if labels and j < len(labels) and labels[j]: self._out.write('{0}: {1}'.format(labels[j], content)) else: self._out.write(content) self._out.write('\n') if self._subformats: for subformat in self._subformats: if subformat.printer: subformat.printer.Print(row[subformat.index]) nested_output = subformat.out.getvalue() # Indent the nested printer lines. for k, line in enumerate( nested_output.split('\n')[:-1]): if not k: self._out.write('\n') self._out.write(line + '\n') # Rewind the output buffer. subformat.out.truncate(0) subformat.out.seek(0) self._out.write('\n') self._rows = [] super(TablePrinter, self).Finish() return # Stringify all column cells for all rows. rows = [[_Stringify(cell) for cell in row] for row in rows] if not self._has_subprinters: self._rows = [] # Remove the hidden/subformat alignments and columns from rows. if self._visible: rows = [self._Visible(row) for row in rows] align = self._Visible(align) # Determine the max column widths of heading + rows heading = [] if 'no-heading' not in self.attributes: if self._heading: labels = self._heading elif self.column_attributes: labels = self._Visible(self.column_attributes.Labels()) else: labels = None if labels: if self._subformats: cells = [] for subformat in self._subformats: if not subformat.printer and subformat.index < len( labels): cells.append(_Stringify(labels[subformat.index])) heading = [cells] else: heading = [[_Stringify(cell) for cell in labels]] col_widths = [0] * max(len(x) for x in rows + heading) for row in rows: for i, col in enumerate(row): col_widths[i] = max(col_widths[i], self._console_attr.DisplayWidth(col)) if self._optional: # Delete optional columns that have no data. optional = False visible = [] # col_widths[i] == 0 => column i has no data. for i, col in enumerate( self._Visible(self.column_attributes.Columns())): if not col.attribute.optional or col_widths[i]: visible.append(i) else: optional = True if optional: # At least one optional column has no data. Adjust all column lists. if not visible: # All columns are optional and have no data => no output. self._empty = True return self._visible = visible rows = [self._Visible(row) for row in rows] align = self._Visible(align) heading = [self._Visible(heading[0])] if heading else [] col_widths = self._Visible(col_widths) if heading: # Check the heading widths too. for i, col in enumerate(heading[0]): col_widths[i] = max(col_widths[i], self._console_attr.DisplayWidth(col)) if self.column_attributes: # Finally check the fixed column widths. for i, col in enumerate(self.column_attributes.Columns()): if col.attribute.width and col_widths[i] < col.attribute.width: col_widths[i] = col.attribute.width # If table is wider than the console and columns can be wrapped, # change wrapped column widths to fit within the available space. wrap = {} for i, col in enumerate(self._Visible( self.column_attributes.Columns())): if col.attribute.wrap: if isinstance(col.attribute.wrap, bool): wrap[i] = _MIN_WIDTH else: wrap[i] = col.attribute.wrap if wrap: visible_cols = len(self._Visible(self.column_attributes.Columns())) table_padding = (visible_cols - 1) * table_column_pad if box: table_padding = (_BOX_CHAR_LENGTH * (visible_cols + 1) + visible_cols * table_column_pad * 2) table_padding += self.attributes.get('margin', 0) table_width = self.attributes.get( 'width', self._console_attr.GetTermSize()[0]) total_col_width = table_width - table_padding if total_col_width < sum(col_widths): non_wrappable_width = sum([ col_width for (i, col_width) in enumerate(col_widths) if i not in wrap ]) available_width = total_col_width - non_wrappable_width for i, col_width in enumerate(col_widths): if i in wrap: min_width = min(wrap[i], col_widths[i]) col_widths[i] = max(available_width // len(wrap), min_width) # Print the title if specified. title = self.attributes.get('title') if self._page_count <= 1 else None if title is not None: if box: line = box.dr width = 0 sep = 2 for i in range(len(col_widths)): width += col_widths[i] if box: line += box.h * (col_widths[i] + sep) sep = 3 if width < self._console_attr.DisplayWidth(title) and not wrap: # Title is wider than the table => pad each column to make room. pad = ((self._console_attr.DisplayWidth(title) + len(col_widths) - 1) // len(col_widths)) width += len(col_widths) * pad if box: line += box.h * len(col_widths) * pad for i in range(len(col_widths)): col_widths[i] += pad if box: width += 3 * len(col_widths) - 1 line += box.dl self._out.write(line) self._out.write('\n') line = '{0}{1}{2}'.format( box.v, _Justify(self._console_attr, title).center(width), box.v) else: width += table_column_pad * (len(col_widths) - 1) line = _Justify(self._console_attr, title).center(width).rstrip() self._out.write(line) self._out.write('\n') # Set up box borders. if box: t_sep = box.vr if title else box.dr m_sep = box.vr b_sep = box.ur t_rule = '' m_rule = '' b_rule = '' for i in range(len(col_widths)): cell = box.h * (col_widths[i] + 2) t_rule += t_sep + cell t_sep = box.hd m_rule += m_sep + cell m_sep = box.vh b_rule += b_sep + cell b_sep = box.hu t_rule += box.vl if title else box.dl m_rule += box.vl b_rule += box.ul self._out.write(t_rule) self._out.write('\n') if heading: line = [] row = heading[0] heading = [] for i in range(len(row)): line.append(box.v) line.append(row[i].center(col_widths[i])) line.append(box.v) self._out.write(' '.join(line)) self._out.write('\n') self._out.write(m_rule) self._out.write('\n') # Print the left-adjusted columns with space stripped from rightmost column. # We must flush directly to the output just in case there is a Windows-like # colorizer. This complicates the trailing space logic. first = True # Used for boxed tables to determine whether any subformats are visible. has_visible_subformats = box and self._subformats and any( [(not subformat.hidden and subformat.printer) for subformat in self._subformats]) for row in heading + rows: if first: first = False elif box: if has_visible_subformats: self._out.write(t_rule) self._out.write('\n') elif all_box: self._out.write(m_rule) self._out.write('\n') row_finished = False while not row_finished: pad = 0 row_finished = True for i in range(len(row)): width = col_widths[i] if box: self._out.write(box.v + ' ') justify = align[i] if align else lambda s, w: s.ljust(w) # Wrap text if needed. s = row[i] is_colorizer = isinstance(s, console_attr.Colorizer) if (self._console_attr.DisplayWidth(s) > width or '\n' in six.text_type(s)): cell_value, remainder = self._GetNextLineAndRemainder( six.text_type(s), width, include_all_whitespace=is_colorizer) if is_colorizer: # pylint:disable=protected-access cell = console_attr.Colorizer( cell_value, s._color, s._justify) row[i] = console_attr.Colorizer( remainder, s._color, s._justify) # pylint:disable=protected-access else: cell = cell_value row[i] = remainder if remainder: row_finished = False else: cell = s row[i] = ' ' if is_colorizer: if pad: self._out.write(' ' * pad) pad = 0 # NOTICE: This may result in trailing space after the last column. cell.Render(self._out, justify=lambda s: justify(s, width)) # pylint: disable=cell-var-from-loop if box: self._out.write(' ' * table_column_pad) else: pad = table_column_pad else: value = justify(_Justify(self._console_attr, cell), width) if box: self._out.write(value) self._out.write(' ' * table_column_pad) elif value.strip(): if pad: self._out.write(' ' * pad) pad = 0 stripped = value.rstrip() self._out.write(stripped) pad = (table_column_pad + self._console_attr.DisplayWidth(value) - self._console_attr.DisplayWidth(stripped)) else: pad += table_column_pad + self._console_attr.DisplayWidth( value) if box: self._out.write(box.v) if self._rows: self._out.write('\n') if heading: heading = [] continue if row_finished: if box: self._out.write(b_rule) self._out.write('\n') r = self._rows.pop(0) for subformat in self._subformats: if subformat.printer: # Indent the nested printer lines. subformat.printer.Print(r[subformat.index]) nested_output = subformat.out.getvalue() for line in nested_output.split('\n')[:-1]: self._out.write(' ' + line + '\n') # Rewind the output buffer. subformat.out.truncate(0) subformat.out.seek(0) else: self._out.write('\n') if box: if not has_visible_subformats: self._out.write(b_rule) self._out.write('\n') super(TablePrinter, self).Finish()
def testColorizerBlueScreenDefaultOutImplicitInit(self): console_attr.ResetConsoleAttr(encoding='UTF-8') s = 'Am I blue?' colorize = console_attr.Colorizer(s, 'blue') colorize.Render(sys.stdout) self.AssertOutputEquals('\x1b[34;1m{0}\x1b[39;0m'.format(s))