def column_widths(self): """Return a list of integers representing the widths of each table column without padding.""" if not self.table_data: return list() number_of_columns = max(len(r) for r in self.table_data) widths = [0] * number_of_columns for row in self.table_data: for i in range(len(row)): if not row[i]: continue widths[i] = max(widths[i], string_width(max(row[i].splitlines(), key=len))) return widths
def test_string_width(string, expected_length): """Test characters width.""" assert string_width(string) == expected_length
def table(self): """Return a large string of the entire table ready to be printed to the terminal.""" padded_table_data = self.padded_table_data column_widths = [c + self.padding_left + self.padding_right for c in self.column_widths] final_table_data = list() # Append top border. max_title = sum(column_widths) + ((len(column_widths) - 1) if self.inner_column_border else 0) if self.outer_border and self.title and string_width(self.title) <= max_title: pseudo_row = join_row( ['h' * w for w in column_widths], 'l', 't' if self.inner_column_border else '', 'r' ) pseudo_row_key = dict(h=self.CHAR_HORIZONTAL, l=self.CHAR_CORNER_UPPER_LEFT, t=self.CHAR_INTERSECT_TOP, r=self.CHAR_CORNER_UPPER_RIGHT) pseudo_row_re = re.compile('({0})'.format('|'.join(pseudo_row_key.keys()))) substitute = lambda s: pseudo_row_re.sub(lambda x: pseudo_row_key[x.string[x.start():x.end()]], s) row = substitute(pseudo_row[:1]) + self.title + substitute(pseudo_row[1 + string_width(self.title):]) final_table_data.append(row) elif self.outer_border: row = join_row( [self.CHAR_HORIZONTAL * w for w in column_widths], self.CHAR_CORNER_UPPER_LEFT, self.CHAR_INTERSECT_TOP if self.inner_column_border else '', self.CHAR_CORNER_UPPER_RIGHT ) final_table_data.append(row) # Build table body. indexes = range(len(padded_table_data)) for i in indexes: row = join_row( padded_table_data[i], self.CHAR_VERTICAL if self.outer_border else '', self.CHAR_VERTICAL if self.inner_column_border else '', self.CHAR_VERTICAL if self.outer_border else '' ) final_table_data.append(row) # Insert row separator. if i == indexes[-1]: continue if self.inner_row_border or (self.inner_heading_row_border and i == 0): row = join_row( [self.CHAR_HORIZONTAL * w for w in column_widths], self.CHAR_INTERSECT_LEFT if self.outer_border else '', self.CHAR_INTERSECT_CENTER if self.inner_column_border else '', self.CHAR_INTERSECT_RIGHT if self.outer_border else '' ) final_table_data.append(row) if i == indexes[-2] and self.inner_footing_row_border: row = join_row( [self.CHAR_HORIZONTAL * w for w in column_widths], self.CHAR_INTERSECT_LEFT if self.outer_border else '', self.CHAR_INTERSECT_CENTER if self.inner_column_border else '', self.CHAR_INTERSECT_RIGHT if self.outer_border else '' ) final_table_data.append(row) # Append bottom border. if self.outer_border: row = join_row( [self.CHAR_HORIZONTAL * w for w in column_widths], self.CHAR_CORNER_LOWER_LEFT, self.CHAR_INTERSECT_BOTTOM if self.inner_column_border else '', self.CHAR_CORNER_LOWER_RIGHT ) final_table_data.append(row) return '\n'.join(final_table_data)
def table(self): """Return a large string of the entire table ready to be printed to the terminal.""" padded_table_data = self.padded_table_data widths = [ c + self.padding_left + self.padding_right for c in self.column_widths ] final_table_data = list() # Append top border. max_title = sum(widths) + ( (len(widths) - 1) if self.inner_column_border else 0) if self.outer_border and self.title and string_width( self.title) <= max_title: pseudo_row = join_row(['h' * w for w in widths], 'l', 't' if self.inner_column_border else '', 'r') pseudo_row_key = dict(h=self.CHAR_HORIZONTAL, l=self.CHAR_CORNER_UPPER_LEFT, t=self.CHAR_INTERSECT_TOP, r=self.CHAR_CORNER_UPPER_RIGHT) pseudo_row_re = re.compile('({0})'.format('|'.join( pseudo_row_key.keys()))) substitute = lambda s: pseudo_row_re.sub( lambda x: pseudo_row_key[x.string[x.start():x.end()]], s) row = substitute(pseudo_row[:1]) + self.title + substitute( pseudo_row[1 + string_width(self.title):]) final_table_data.append(row) elif self.outer_border: row = join_row( [self.CHAR_HORIZONTAL * w for w in widths], self.CHAR_CORNER_UPPER_LEFT, self.CHAR_INTERSECT_TOP if self.inner_column_border else '', self.CHAR_CORNER_UPPER_RIGHT) final_table_data.append(row) # Build table body. indexes = range(len(padded_table_data)) for i in indexes: row = join_row( padded_table_data[i], self.CHAR_VERTICAL if self.outer_border else '', self.CHAR_VERTICAL if self.inner_column_border else '', self.CHAR_VERTICAL if self.outer_border else '') final_table_data.append(row) # Insert row separator. if i == indexes[-1]: continue if self.inner_row_border or (self.inner_heading_row_border and i == 0): row = join_row( [self.CHAR_HORIZONTAL * w for w in widths], self.CHAR_INTERSECT_LEFT if self.outer_border else '', self.CHAR_INTERSECT_CENTER if self.inner_column_border else '', self.CHAR_INTERSECT_RIGHT if self.outer_border else '') final_table_data.append(row) if i == indexes[-2] and self.inner_footing_row_border: row = join_row( [self.CHAR_HORIZONTAL * w for w in widths], self.CHAR_INTERSECT_LEFT if self.outer_border else '', self.CHAR_INTERSECT_CENTER if self.inner_column_border else '', self.CHAR_INTERSECT_RIGHT if self.outer_border else '') final_table_data.append(row) # Append bottom border. if self.outer_border: row = join_row( [self.CHAR_HORIZONTAL * w for w in widths], self.CHAR_CORNER_LOWER_LEFT, self.CHAR_INTERSECT_BOTTOM if self.inner_column_border else '', self.CHAR_CORNER_LOWER_RIGHT) final_table_data.append(row) return '\n'.join(final_table_data)