diff options
author | luke@maurits.id.au <luke@maurits.id.au@0f58610c-415a-11de-9c03-5d6cfad8e937> | 2012-06-29 01:21:46 +0000 |
---|---|---|
committer | luke@maurits.id.au <luke@maurits.id.au@0f58610c-415a-11de-9c03-5d6cfad8e937> | 2012-06-29 01:21:46 +0000 |
commit | 6d555581c0b160894e08f6b7dfd5ea144b58b849 (patch) | |
tree | d83dd4ea3934dd4bdaf2bb0eecc737b84940509b | |
parent | 807a77540111399cd8b11f9c22313ad2379bdb27 (diff) | |
download | python-prettytable-6d555581c0b160894e08f6b7dfd5ea144b58b849.tar.gz |
Lots of miscellaneous improvements: reduction of code duplication, performance tweaks, validation, etc.
git-svn-id: http://prettytable.googlecode.com/svn/trunk@72 0f58610c-415a-11de-9c03-5d6cfad8e937
-rw-r--r-- | prettytable.py | 118 |
1 files changed, 72 insertions, 46 deletions
diff --git a/prettytable.py b/prettytable.py index b8e2d8d..1be7f72 100644 --- a/prettytable.py +++ b/prettytable.py @@ -91,7 +91,7 @@ class PrettyTable(object): int_format - controls formatting of integer data float_format - controls formatting of floating point data padding_width - number of spaces on either side of column data (only used if left and right paddings are None) - left_padding_width - number of spaces on left hand side of column data + left_padding-2012_width - number of spaces on left hand side of column data right_padding_width - number of spaces on right hand side of column data vertical_char - single character string used to draw vertical lines horizontal_char - single character string used to draw horizontal lines @@ -193,7 +193,9 @@ class PrettyTable(object): # Secondly, in the _get_options method, where keyword arguments are mixed with persistent settings def _validate_option(self, option, val): - if option in ("start", "end", "max_width", "padding_width", "left_padding_width", "right_padding_width", "format"): + if option in ("field_names"): + self._validate_field_names(val) + elif option in ("start", "end", "max_width", "padding_width", "left_padding_width", "right_padding_width", "format"): self._validate_nonnegative_int(option, val) elif option in ("sortby"): self._validate_field_name(option, val) @@ -216,6 +218,24 @@ class PrettyTable(object): else: raise Exception("Unrecognised option: %s!" % option) + def _validate_field_names(self, val): + # Check for appropriate length + if self._field_names: + try: + assert len(val) == len(self._field_names) + except AssertionError: + raise Exception("Field name list has incorrect number of values, (actual) %d!=%d (expected)" % (len(val), len(self._field_names))) + if self._rows: + try: + assert len(val) == len(self._rows[0]) + except AssertionError: + raise Exception("Field name list has incorrect number of values, (actual) %d!=%d (expected)" % (len(val), len(self._rows[0]))) + # Check for uniqueness + try: + assert len(val) == len(set(val)) + except AssertionError: + raise Exception("Field names must be unique!") + def _validate_align(self, val): try: assert val in ["l","c","r"] @@ -305,6 +325,7 @@ class PrettyTable(object): fields - list or tuple of field names""" def _set_field_names(self, val): + self._validate_option("field_names", val) if self._field_names: old_names = self._field_names[:] self._field_names = val @@ -640,6 +661,8 @@ class PrettyTable(object): if self._field_names and len(row) != len(self._field_names): raise Exception("Row has incorrect number of values, (actual) %d!=%d (expected)" %(len(row),len(self._field_names))) + if not self._field_names: + self.field_names = [("Field %d" % (n+1)) for n in range(0,len(row))] self._rows.append(list(row)) def del_row(self, row_index): @@ -715,8 +738,11 @@ class PrettyTable(object): widths = len(self.field_names) * [0] for row in rows: for index, value in enumerate(row): - value = self._format_value(self.field_names[index], value) - widths[index] = max(widths[index], _get_size(_unicode(value))[0]) + fieldname = self.field_names[index] + if fieldname in self.max_width: + widths[index] = max(widths[index], min(_get_size(value)[0], self.max_width[fieldname])) + else: + widths[index] = max(widths[index], _get_size(value)[0]) self._widths = widths def _get_padding_widths(self, options): @@ -869,12 +895,11 @@ class PrettyTable(object): for index, field, value, width, in zip(range(0,len(row)), self._field_names, row, self._widths): # Enforce max widths - max_width = self._max_width.get(field, 0) lines = value.split("\n") new_lines = [] for line in lines: - if max_width and len(line) > max_width: - line = textwrap.fill(line, max_width) + if len(line) > width: + line = textwrap.fill(line, width) new_lines.append(line) lines = new_lines value = "\n".join(lines) @@ -962,81 +987,82 @@ class PrettyTable(object): def _get_simple_html_string(self, options): - bits = [] - # Slow but works - table_tag = '<table' + string = StringIO() + + string.write("<table") if options["border"]: - table_tag += ' border="1"' + string.write(" border=\"1\"") if options["attributes"]: for attr_name in options["attributes"]: - table_tag += ' %s="%s"' % (attr_name, options["attributes"][attr_name]) - table_tag += '>' - bits.append(table_tag) + string.write(" %s=\"%s\"" % (attr_name, options["attributes"][attr_name])) + string.write(">\n") # Headers if options["header"]: - bits.append(" <tr>") + string.write(" <tr>\n") for field in self._field_names: if options["fields"] and field not in options["fields"]: continue - bits.append(" <th>%s</th>" % escape(_unicode(field)).replace("\n", "<br />")) - bits.append(" </tr>") + string.write(" <th>%s</th>\n" % escape(_unicode(field)).replace("\n", "<br />")) + string.write(" </tr>\n") # Data rows = self._get_rows(options) - for row in rows: - bits.append(" <tr>") + formatted_rows = self._format_rows(rows, options) + for row in formatted_rows: + string.write(" <tr>\n") for field, datum in zip(self._field_names, row): if options["fields"] and field not in options["fields"]: continue - bits.append(" <td>%s</td>" % escape(_unicode(datum)).replace("\n", "<br />")) - bits.append(" </tr>") + string.write(" <td>%s</td>\n" % escape(datum).replace("\n", "<br />")) + string.write(" </tr>\n") - bits.append("</table>") - string = "\n".join(bits) + string.write("</table>") + string = string.getvalue() self._nonunicode = string return _unicode(string) def _get_formatted_html_string(self, options): - bits = [] + string = StringIO() + lpad, rpad = self._get_padding_widths(options) - # Slow but works - table_tag = '<table' + string.write("<table") if options["border"]: - table_tag += ' border="1"' + string.write(" border=\"1\"") if options["hrules"] == NONE: - table_tag += ' frame="vsides" rules="cols"' + string.write(" frame=\"vsides\" rules=\"cols\"") if options["attributes"]: for attr_name in options["attributes"]: - table_tag += ' %s="%s"' % (attr_name, options["attributes"][attr_name]) - table_tag += '>' - bits.append(table_tag) + string.write(" %s=\"%s\"" % (attr_name, options["attributes"][attr_name])) + string.write(">\n") + # Headers if options["header"]: - bits.append(" <tr>") + string.write(" <tr>\n") for field in self._field_names: if options["fields"] and field not in options["fields"]: continue - bits.append(" <th style=\"padding-left: %dem; padding-right: %dem; text-align: center\">%s</th>" % (lpad, rpad, escape(_unicode(field)).replace("\n", "<br />"))) - bits.append(" </tr>") + string.write(" <th style=\"padding-left: %dem; padding-right: %dem; text-align: center\">%s</th>\n" % (lpad, rpad, escape(_unicode(field)).replace("\n", "<br />"))) + string.write(" </tr>\n") + # Data rows = self._get_rows(options) - for row in self._rows: - bits.append(" <tr>") - for field, datum in zip(self._field_names, row): + formatted_rows = self._format_rows(rows, options) + aligns = [] + for field in self._field_names: + aligns.append({ "l" : "left", "r" : "right", "c" : "center" }[self._align[field]]) + for row in formatted_rows: + string.write(" <tr>\n") + for field, datum, align in zip(self._field_names, row, aligns): if options["fields"] and field not in options["fields"]: continue - if self._align[field] == "l": - bits.append(" <td style=\"padding-left: %dem; padding-right: %dem; text-align: left\">%s</td>" % (lpad, rpad, escape(_unicode(datum)).replace("\n", "<br />"))) - elif self._align[field] == "r": - bits.append(" <td style=\"padding-left: %dem; padding-right: %dem; text-align: right\">%s</td>" % (lpad, rpad, escape(_unicode(datum)).replace("\n", "<br />"))) - else: - bits.append(" <td style=\"padding-left: %dem; padding-right: %dem; text-align: center\">%s</td>" % (lpad, rpad, escape(_unicode(datum)).replace("\n", "<br />"))) - bits.append(" </tr>") - bits.append("</table>") - string = "\n".join(bits) + string.write(" <td style=\"padding-left: %dem; padding-right: %dem; text-align: %s\">%s</td>\n" % (lpad, rpad, align, escape(datum).replace("\n", "<br />"))) + string.write(" </tr>\n") + string.write("</table>\n") + + string = string.getvalue() self._nonunicode = string return _unicode(string) |