1class MarkupTable: 2 """ 3 Container for holding table data and render the data in creole markup. 4 Format every cell width to the same col width. 5 """ 6 7 def __init__(self, head_prefix="= ", auto_width=True, debug_msg=None): 8 self.head_prefix = head_prefix 9 self.auto_width = auto_width 10 11 if debug_msg is None: 12 self.debug_msg = self._non_debug 13 else: 14 self.debug_msg = debug_msg 15 16 self.rows = [] 17 self.row_index = None 18 self.has_header = False 19 20 def _non_debug(self, *args): 21 pass 22 23 def add_tr(self): 24 self.debug_msg("Table.add_tr", "") 25 self.rows.append([]) 26 self.row_index = len(self.rows) - 1 27 28 def add_th(self, text): 29 self.has_header = True 30 self.add_td(self.head_prefix + text) 31 32 def add_td(self, text): 33 if self.row_index is None: 34 self.add_tr() 35 36 self.debug_msg("Table.add_td", text) 37 self.rows[self.row_index].append(text) 38 39 def _get_preformat_info(self): 40 cells = [] 41 for row in self.rows: 42 line_cells = [] 43 for cell in row: 44 cell = cell.strip() 45 if cell != "": 46 if self.head_prefix and cell.startswith(self.head_prefix): 47 cell += " " # Headline 48 else: 49 cell = f" {cell} " # normal cell 50 line_cells.append(cell) 51 cells.append(line_cells) 52 53 # Build a list of max len for every column 54 widths = [max(map(len, col)) for col in zip(*cells)] 55 56 return cells, widths 57 58 def get_table_markup(self): 59 """ return the table data in creole/textile markup. """ 60 if not self.auto_width: 61 lines = [] 62 for row in self.rows: 63 lines.append("|" + "|".join([cell for cell in row]) + "|") 64 else: 65 # preformat every table cell 66 cells, widths = self._get_preformat_info() 67 68 # Join every line with ljust 69 lines = [] 70 for row in cells: 71 cells = [cell.ljust(width) for cell, width in zip(row, widths)] 72 lines.append("|" + "|".join(cells) + "|") 73 74 result = "\n".join(lines) 75 76 self.debug_msg("Table.get_table_markup", result) 77 return result 78 79 def get_rest_table(self): 80 """ return the table data in ReSt markup. """ 81 # preformat every table cell 82 cells, widths = self._get_preformat_info() 83 84 separator_line = f"+{'+'.join([('-' * width) for width in widths])}+" 85 headline_separator = f"+{'+'.join([('=' * width) for width in widths])}+" 86 87 lines = [] 88 for no, row in enumerate(cells): 89 if no == 1 and self.has_header: 90 lines.append(headline_separator) 91 else: 92 lines.append(separator_line) 93 94 # Join every line with ljust 95 cells = [cell.ljust(width) for cell, width in zip(row, widths)] 96 lines.append("|" + "|".join(cells) + "|") 97 98 lines.append(separator_line) 99 100 return "\n".join(lines) 101 102 103if __name__ == '__main__': 104 import doctest 105 print(doctest.testmod()) 106