Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python
- # -*- coding: utf-8 -*-
- import textwrap
- class RowMismatchException(Exception):
- pass
- class XTable(object):
- def __init__(self):
- super(XTable, self).__init__()
- #
- # Type: [str]
- #
- self.set_header([])
- #
- # Type: [[str]]
- #
- self.rows_ = []
- def set_header(self, header):
- """param header: [str]"""
- self.header_ = header[:]
- self.column_num_ = len(self.header_)
- self.column_widths_ = [10] * self.column_num_
- self.column_formats_ = ['l'] * self.column_num_
- def set_column_width(self, widths):
- """param widths: [int]"""
- self.column_widths_ = [max(w, 5) for w in widths]
- def set_column_format(self, formats):
- """param formats: [char]"""
- self.column_formats_ = formats
- def add_row(self, row):
- """param row: [str]"""
- if len(row) != self.column_num_:
- raise RowMismatchException('Table column number %d; Row size: %d' %
- (self.column_num_, len(row)))
- self.rows_.append(row[:])
- def _line_seprator(self, symbol='-', corner_symbol='+'):
- line = [
- symbol * self.column_widths_[i] for i in range(self.column_num_)
- ]
- return '{0}{1}{0}'.format(corner_symbol, corner_symbol.join(line))
- def _format_column_item(self, item, column_idx):
- width = self.column_widths_[column_idx]
- fmt = self.column_formats_[column_idx]
- if fmt == 'l':
- return item.ljust(width)
- elif fmt == 'c':
- return item.center(width)
- elif fmt == 'r':
- return item.rjust(width)
- else:
- return item.ljust(width)
- def _break_row(self, row):
- """For each row, e.g., ('abcd' 'efgh' 'I need be broken')
- we break the long items into multiple lines.
- The result may be [('abcd' 'efgh' 'I need')
- ('' '' 'be broken')]
- """
- all_sub_lines = []
- for (idx, item) in enumerate(row):
- sub_lines = textwrap.wrap(item,
- self.column_widths_[idx],
- break_long_words=False)
- all_sub_lines.append(sub_lines)
- #
- # For shorter item, we add padding here
- #
- max_line = max(map(lambda x: len(x), all_sub_lines))
- for sub_lines in all_sub_lines:
- if len(sub_lines) < max_line:
- sub_lines.extend([''] * (max_line - len(sub_lines)))
- return zip(*all_sub_lines)
- def _format_row(self, row):
- """param row: [str]"""
- line = [
- self._format_column_item(item, idx)
- for (idx, item) in enumerate(row)
- ]
- return '|{0}|'.format('|'.join(line))
- def to_text(self):
- lines = [self._line_seprator('-'),
- self._format_row(self.header_),
- self._line_seprator('=')]
- for row in self.rows_:
- sub_lines = self._break_row(row)
- for r in sub_lines:
- lines.append(self._format_row(r))
- lines.append(self._line_seprator('-'))
- return '\n'.join(lines)
- def dump_text(self):
- print self.to_text()
- def _markdown_line_seprator(self):
- line = []
- for i in range(self.column_num_):
- width = self.column_widths_[i]
- fmt = self.column_formats_[i]
- if fmt == 'l':
- line.append('-' * width)
- elif fmt == 'c':
- line.append(':' + '-' * (width - 2) + ':')
- elif fmt == 'r':
- line.append('-' * (width - 1) + ':')
- else:
- line.append('-' * width)
- return '|{0}|'.format('|'.join(line))
- def to_markdown(self):
- lines = [self._format_row(self.header_),
- self._markdown_line_seprator()]
- for row in self.rows_:
- lines.append(self._format_row(row))
- return '\n'.join(lines)
- def dump_markdown(self):
- print self.to_markdown()
- if __name__ == "__main__":
- import random
- import string
- def rand_str(l=10):
- """Generate a random string of fixed length"""
- letters = string.ascii_lowercase
- return ''.join(random.choice(letters) for i in range(l))
- tb = XTable()
- column_num = 3
- tb.set_header([rand_str(10) for i in range(column_num)])
- tb.set_column_width([random.randint(10, 15) for i in range(column_num)])
- tb.set_column_format(['l', 'l', 'c'])
- for i in range(7):
- tb.add_row([rand_str(random.randint(2, 8)) for i in range(column_num)])
- tb.add_row(['aaaa very long string, here break into multiple lines',
- 'a',
- 'c'])
- tb.dump_text()
- print ''
- tb.dump_markdown()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement