コード例 #1
0
 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)
コード例 #2
0
 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)
コード例 #3
0
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
コード例 #4
0
 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())
コード例 #5
0
 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())
コード例 #6
0
    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)
コード例 #7
0
 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())
コード例 #8
0
 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())
コード例 #9
0
    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)
コード例 #10
0
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
コード例 #11
0
  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')
コード例 #12
0
ファイル: table_printer.py プロジェクト: saranraju90/multik8s
    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()
コード例 #13
0
 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))