From 6d555581c0b160894e08f6b7dfd5ea144b58b849 Mon Sep 17 00:00:00 2001 From: "luke@maurits.id.au" Date: Fri, 29 Jun 2012 01:21:46 +0000 Subject: 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 --- prettytable.py | 118 +++++++++++++++++++++++++++++++++++---------------------- 1 file 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 = '\n") # Headers if options["header"]: - bits.append(" ") + string.write(" \n") for field in self._field_names: if options["fields"] and field not in options["fields"]: continue - bits.append(" %s" % escape(_unicode(field)).replace("\n", "
")) - bits.append(" ") + string.write(" %s\n" % escape(_unicode(field)).replace("\n", "
")) + string.write(" \n") # Data rows = self._get_rows(options) - for row in rows: - bits.append(" ") + formatted_rows = self._format_rows(rows, options) + for row in formatted_rows: + string.write(" \n") for field, datum in zip(self._field_names, row): if options["fields"] and field not in options["fields"]: continue - bits.append(" %s" % escape(_unicode(datum)).replace("\n", "
")) - bits.append(" ") + string.write(" %s\n" % escape(datum).replace("\n", "
")) + string.write(" \n") - bits.append("") - string = "\n".join(bits) + string.write("") + 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 = '\n") + # Headers if options["header"]: - bits.append(" ") + string.write(" \n") for field in self._field_names: if options["fields"] and field not in options["fields"]: continue - bits.append(" %s" % (lpad, rpad, escape(_unicode(field)).replace("\n", "
"))) - bits.append(" ") + string.write(" %s\n" % (lpad, rpad, escape(_unicode(field)).replace("\n", "
"))) + string.write(" \n") + # Data rows = self._get_rows(options) - for row in self._rows: - bits.append(" ") - 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(" \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(" %s" % (lpad, rpad, escape(_unicode(datum)).replace("\n", "
"))) - elif self._align[field] == "r": - bits.append(" %s" % (lpad, rpad, escape(_unicode(datum)).replace("\n", "
"))) - else: - bits.append(" %s" % (lpad, rpad, escape(_unicode(datum)).replace("\n", "
"))) - bits.append(" ") - bits.append("") - string = "\n".join(bits) + string.write(" %s\n" % (lpad, rpad, align, escape(datum).replace("\n", "
"))) + string.write(" \n") + string.write("\n") + + string = string.getvalue() self._nonunicode = string return _unicode(string) -- cgit v1.2.1