-
- def __init__(self, double=False, borders=True, hpadding="+", maxwidth=80):
- self.rows = [] # List of row objects
- self.keymap = {} # For fast lookup of row by value of first column
- self.double = double
- self.borders = borders
- self.align_cols = []
- self.hpadding = hpadding
- self.maxwidth = maxwidth
- self._colwidths = []
-
- def add_row(self, row):
- self.rows.append(row)
- for i, col in enumerate(row.columns):
- if len(self._colwidths) >= i + 1:
- self._colwidths[i] = max([self._colwidths[i], len(col.content)])
- else:
- self._colwidths.append(len(col.content))
- logger.debug("Added row with {0} columns. Column widths are now {1}.".format(str(len(row.columns)), str(self._colwidths)))
- if len(row.columns) > 0:
- self.keymap[row.columns[0]] = row
-
- def align_column(self, i, align):
- for row in self.rows:
- row.columns[i].align = align
-
-
- def draw_html(self):
- output = ""
- output += opentag("table", True, cl="data_table")
- for row in self.rows:
- if row.header:
- output += opentag("th", block=True, cl="header")
- else:
- output += opentag("tr", block=True)
- for column in row.columns:
- output += tag("td", content=column.content, style={"text-align": column.align} if column.align else {})
- if row.header:
- output += closetag("th", True)
- else:
- output += closetag("tr", True)
- output += closetag("table", True)
- logger.debug("Built table with {0} rows and {1} columns".format(str(len(self.rows)), str(max([x.n for x in self.rows]))))
- return output
-
- def draw_plain(self):
- output = ""
- cols = [list(x) for x in zip(self.rows)]
- logger.debug("Cols are " + str(cols))
-
- if self.double == True:
- cornerchars = CORNERCHARS_DOUBLE
- linechars = LINECHARS_DOUBLE
- jxnchars = JXNCHARS_DOUBLE
- else:
- cornerchars = CORNERCHARS_SINGLE
- linechars = LINECHARS_SINGLE
- jxnchars = JXNCHARS_SINGLE
-
- lengths = []
- row_lengths = []
- for row in self.rows:
- for i, col in enumerate(row.columns):
- if len(lengths) >= i + 1:
- lengths[i] = max([lengths[i], len(col.content)])
- else:
- lengths.append(len(col.content))
-
- logger.debug("Lengths are " + str(lengths))
-
- for i, row in enumerate(self.rows):
- l = (len(INDENT) + len(self.hpadding)*2*len(row.columns) + ((1+len(row.columns)) if self.borders else 0) + sum([len(col.content) for col in row.columns]))
- if l > self.maxwidth:
- logger.debug("Line overflow for cell in row {0} of table".format(str(i)))
- words = row.columns[-1].content.split()
- if max(map(len, words)) > self.maxwidth:
- continue
- res, part, others = [], words[0], words[1:]
- for word in others:
- if l - len(word) < self.maxwidth:
- res.append(part)
- part = word
- else:
- part += ' ' + word
- if part:
- res.append(part)
- self._colwidths[-1] = max([len(f) for f in res] + [len(r.columns[-1].content) for r in self.rows if r != row])
- if self.borders:
- row.columns[-1].content = res[0][:-1] + self.hpadding + " "*(self._colwidths[-1]-len(res[0])+1) + linechars[0]
- for fragment in res[1:]:
- row.columns[-1].content += "\n" + INDENT + "".join([(linechars[0] + self.hpadding + " "*x + self.hpadding) for x in lengths]) + linechars[0] + self.hpadding + fragment + " " * (max(self._colwidths) - len(fragment))
-
- if self.borders:
- top = INDENT + cornerchars[3] + jxnchars[2].join(linechars[1] * (l+2) for l in self._colwidths) + cornerchars[2] + "\n"
- bottom = INDENT + cornerchars[0] + jxnchars[3].join(linechars[1] * (l+2) for l in self._colwidths) + cornerchars[1] + "\n"
- rowtext = INDENT + linechars[0] + linechars[0].join("{:>%d}" % l for l in self._colwidths) + linechars[0] + "\n"
- line = INDENT + jxnchars[0] + jxnchars[4].join(linechars[1] * (l+2) for l in self._colwidths) + jxnchars[1] + "\n"
- else:
- top = bottom = line = ""
- rowtext = " ".join("{:>%d}" % l for l in self._colwidths) + "\n"
-
- for i, row in enumerate(self.rows):
- logger.debug("Processing row {0} of {1}".format(str(i), str(len(self.rows)-1)))
- row_output = ""
- if i == 0:
- row_output += top
- row_output += (INDENT + linechars[0] if self.borders else "")
- for j, column in enumerate(row.columns):
- if column.align == "right":
- cell_output = self.hpadding + " "*(self._colwidths[j]-len(column.content)) + column.content + self.hpadding + (linechars[0] if self.borders else "")
- elif column.align == "left":
- cell_output = self.hpadding + column.content + " "*(self._colwidths[j]-len(column.content)) + self.hpadding + (linechars[0] if self.borders else "")
- elif column.align == "center":
- n_whitespace = (self._colwidths[j]-len(column.content))/2
- cell_output = self.hpadding + " "*(floor(n_whitespace) if len(column.content) % 2 == 0 else ceil(n_whitespace)) + column.content + " "*(ceil(n_whitespace) if len(column.content) % 2 == 0 else floor(n_whitespace)) + self.hpadding + (linechars[0] if self.borders else "")
- else:
- logger.warning("Couldn't find alignment value for cell {0} of row {1} with content \"{2}\"".format(str(j), str(i), column.content()))
- continue
- row_output += cell_output
- if len(row_output) > self.maxwidth:
- logger.warning("Line overflow for row {0} of table".format(str(i)))
-
- output += row_output + "\n"
- if i == len(self.rows)-1:
- output += (bottom if self.borders else "")
- else:
- output += (line if self.borders else "")
-
- return output
-
-class Row(object):