39 py3k = sys.version_info[0] >= 3
43 if py3k
and sys.version_info[1] >= 2:
44 from html
import escape
46 from cgi
import escape
63 for line
in text.split(
"\n"):
65 if len(line) > max_width:
68 return (max_width, max_height)
71 if not isinstance(value, basestring):
73 if not isinstance(value, unicode):
74 value =
unicode(value, encoding,
"replace")
79 def __init__(self, field_names=None, encoding="UTF-8", **kwargs):
81 """Return a new PrettyTable instance
85 field_names - list or tuple of field names
86 encoding - Unicode encoding scheme to use
87 fields - list or tuple of field names to include in displays
88 start - index of first data row to include in output
89 end - index of last data row to include in output PLUS ONE (list slice style)
90 fields - names of fields (columns) to include
91 header - print a header showing field names (True or False)
92 border - print a border around the table (True or False)
93 hrules - controls printing of horizontal rules after rows. Allowed values: FRAME, ALL, NONE
94 int_format - controls formatting of integer data
95 float_format - controls formatting of floating point data
96 padding_width - number of spaces on either side of column data (only used if left and right paddings are None)
97 left_padding_width - number of spaces on left hand side of column data
98 right_padding_width - number of spaces on right hand side of column data
99 vertical_char - single character string used to draw vertical lines
100 horizontal_char - single character string used to draw horizontal lines
101 junction_char - single character string used to draw line junctions
102 sortby - name of field to sort rows by
103 sort_key - sorting key function, applied to data points before sorting
104 reversesort - True or False to sort in descending or ascending order"""
120 self.
_options =
"start end fields header border sortby reversesort sort_key attributes format hrules".
split()
121 self._options.extend(
"int_format float_format padding_width left_padding_width right_padding_width".
split())
122 self._options.extend(
"vertical_char horizontal_char junction_char".
split())
127 kwargs[option] =
None
131 self.
_end = kwargs[
"end"]
or None
157 if name ==
"rowcount":
159 elif name ==
"colcount":
167 raise AttributeError(name)
171 newtable = copy.deepcopy(self)
172 if isinstance(index, slice):
173 newtable._rows = self.
_rows[index]
174 elif isinstance(index, int):
175 newtable._rows = [self.
_rows[index],]
177 raise Exception(
"Index %s is invalid, must be an integer or slice" % str(index))
201 if option
in (
"start",
"end",
"padding_width",
"left_padding_width",
"right_padding_width",
"format"):
203 elif option
in (
"sortby"):
205 elif option
in (
"sort_key"):
207 elif option
in (
"hrules"):
209 elif option
in (
"fields"):
211 elif option
in (
"header",
"border",
"reversesort"):
213 elif option
in (
"int_format"):
215 elif option
in (
"float_format"):
217 elif option
in (
"vertical_char",
"horizontal_char",
"junction_char"):
219 elif option
in (
"attributes"):
222 raise Exception(
"Unrecognised option: %s!" % option)
226 assert val
in [
"l",
"c",
"r"]
227 except AssertionError:
228 raise Exception(
"Alignment %s is invalid, use l, c or r!" % val)
233 except AssertionError:
238 assert val
in (
True,
False)
239 except AssertionError:
240 raise Exception(
"Invalid value for %s! Must be True or False." % name)
246 assert type(val)
in (str, unicode)
248 except AssertionError:
249 raise Exception(
"Invalid value for %s! Must be an integer format string." % name)
255 assert type(val)
in (str, unicode)
257 bits = val.split(
".")
258 assert len(bits) <= 2
259 assert bits[0] ==
"" or bits[0].isdigit()
260 assert bits[1] ==
"" or bits[1].isdigit()
261 except AssertionError:
262 raise Exception(
"Invalid value for %s! Must be a float format string." % name)
266 assert hasattr(val,
"__call__")
267 except AssertionError:
268 raise Exception(
"Invalid value for %s! Must be a function." % name)
272 assert val
in (ALL, FRAME, NONE)
273 except AssertionError:
274 raise Exception(
"Invalid value for %s! Must be ALL, FRAME or NONE." % name)
279 except AssertionError:
280 raise Exception(
"Invalid field name: %s!" % val)
286 except AssertionError:
287 raise Exception(
"fields must be a sequence of field names!")
292 except AssertionError:
293 raise Exception(
"Invalid value for %s! Must be a string of length 1." % name)
297 assert isinstance(val, dict)
298 except AssertionError:
299 raise Exception(
"attributes must be a dictionary of name/value pairs!")
307 """The names of the fields
311 fields - list or tuple of field names"""
316 if self.
_align and old_names:
317 for old_name, new_name
in zip(old_names, val):
319 for old_name
in old_names:
320 self._align.pop(old_name)
324 field_names = property(_get_field_names, _set_field_names)
332 align = property(_get_align, _set_align)
337 self._validate_nonnegativeint(val)
340 max_width = property(_get_max_width, _set_max_width)
343 """Start index of the range of rows to print
347 start - index of first data row to include in output"""
353 start = property(_get_start, _set_start)
356 """End index of the range of rows to print
360 end - index of last data row to include in output PLUS ONE (list slice style)"""
365 end = property(_get_end, _set_end)
368 """Name of field by which to sort rows
372 sortby - field name to sort by"""
377 sortby = property(_get_sortby, _set_sortby)
380 """Controls direction of sorting (ascending vs descending)
384 reveresort - set to True to sort by descending order, or False to sort by ascending order"""
389 reversesort = property(_get_reversesort, _set_reversesort)
392 """Sorting key function, applied to data points before sorting
396 sort_key - a function which takes one argument and returns something to be sorted"""
401 sort_key = property(_get_sort_key, _set_sort_key)
404 """Controls printing of table header with field names
408 header - print a header showing field names (True or False)"""
413 header = property(_get_header, _set_header)
416 """Controls printing of border around table
420 border - print a border around the table (True or False)"""
425 border = property(_get_border, _set_border)
428 """Controls printing of horizontal rules after rows
432 hrules - horizontal rules style. Allowed values: FRAME, ALL, NONE"""
437 hrules = property(_get_hrules, _set_hrules)
440 """Controls formatting of integer data
443 int_format - integer format string"""
449 int_format = property(_get_int_format, _set_int_format)
452 """Controls formatting of floating point data
455 float_format - floating point format string"""
461 float_format = property(_get_float_format, _set_float_format)
464 """The number of empty spaces between a column's edge and its content
468 padding_width - number of spaces, must be a positive integer"""
473 padding_width = property(_get_padding_width, _set_padding_width)
476 """The number of empty spaces between a column's left edge and its content
480 left_padding - number of spaces, must be a positive integer"""
485 left_padding_width = property(_get_left_padding_width, _set_left_padding_width)
488 """The number of empty spaces between a column's right edge and its content
492 right_padding - number of spaces, must be a positive integer"""
497 right_padding_width = property(_get_right_padding_width, _set_right_padding_width)
500 """The charcter used when printing table borders to draw vertical lines
504 vertical_char - single character string used to draw vertical lines"""
509 vertical_char = property(_get_vertical_char, _set_vertical_char)
512 """The charcter used when printing table borders to draw horizontal lines
516 horizontal_char - single character string used to draw horizontal lines"""
521 horizontal_char = property(_get_horizontal_char, _set_horizontal_char)
524 """The charcter used when printing table borders to draw line junctions
528 junction_char - single character string used to draw line junctions"""
533 junction_char = property(_get_junction_char, _set_junction_char)
536 """Controls whether or not HTML tables are formatted to match styling options
540 format - True or False"""
545 format = property(_get_format, _set_format)
548 """A dictionary of HTML attribute name/value pairs to be included in the <table> tag when printing HTML
552 attributes - dictionary of attributes"""
555 self.validate_option(
"attributes", val)
557 attributes = property(_get_attributes, _set_attributes)
569 options[option] = kwargs[option]
571 options[option] = getattr(self,
"_"+option)
582 elif style == MSWORD_FRIENDLY:
584 elif style == PLAIN_COLUMNS:
586 elif style == RANDOM:
589 raise Exception(
"Invalid pre-set style!")
624 self.
header = random.choice((
True,
False))
625 self.
border = random.choice((
True,
False))
626 self.
_hrules = random.choice((ALL, FRAME, NONE))
629 self.
vertical_char = random.choice(
"~!@#$%^&*()_+|-=\{}[];':\",./;<>?")
630 self.
horizontal_char = random.choice(
"~!@#$%^&*()_+|-=\{}[];':\",./;<>?")
631 self.
junction_char = random.choice(
"~!@#$%^&*()_+|-=\{}[];':\",./;<>?")
639 """Add a row to the table
643 row - row of data, should be a list with as many elements as the table
648 self._rows.append(list(row))
652 """Delete a row to the table
656 row_index - The index of the row you want to delete. Indexing starts at 0."""
659 raise Exception(
"Cant delete row at index %d, table only has %d rows!" % (row_index,
len(self.
_rows)))
660 del self.
_rows[row_index]
664 """Add a column to the table.
668 fieldname - name of the field to contain the new column of data
669 column - column of data, should be a list with as many elements as the
671 align - desired alignment for this column - "l" for left, "c" for centre and "r" for right"""
673 if len(self._rows) in (0, len(column)):
674 self._validate_align(align)
675 self._field_names.append(fieldname)
676 self._align[fieldname] = align
677 for i in range(0, len(column)):
678 if len(self._rows) < i+1:
679 self._rows.append([])
680 self._rows[i].append(column[i])
682 raise Exception("Column length %d does not match number of rows %d!" % (len(column), len(self._rows)))
684 def clear_rows(self):
686 """Delete all rows from the table but keep the current field names
"""
692 """Delete all rows and field names from the table, maintaining nothing but styling options
"""
695 self._field_names = []
698 ##############################
699 # MISC PUBLIC METHODS #
700 ##############################
703 return copy.deepcopy(self)
705 ##############################
706 # MISC PRIVATE METHODS #
707 ##############################
709 def _format_value(self, field, value):
710 if isinstance(value, int) and field in self._int_format:
711 value = ("%%%sd" % self._int_format[field]) % value
712 elif isinstance(value, float) and field in self._float_format:
713 value = ("%%%sf" % self._float_format[field]) % value
716 def _compute_widths(self, rows, options):
717 if options["header"]:
718 widths = [_get_size(field)[0] for field in self._field_names]
720 widths = len(self.field_names) * [0]
722 for index, value in enumerate(row):
723 value = self._format_value(self.field_names[index], value)
724 widths[index] = max(widths[index], _get_size(_unicode(value))[0])
725 self._widths = widths
727 def _get_padding_widths(self, options):
729 if options["left_padding_width"] is not None:
730 lpad = options["left_padding_width"]
732 lpad = options["padding_width"]
733 if options["right_padding_width"] is not None:
734 rpad = options["right_padding_width"]
736 rpad = options["padding_width"]
739 def _get_rows(self, options):
740 """Return only those data rows that should be printed, based on slicing and sorting.
744 options - dictionary of option settings.
"""
746 # Make a copy of only those rows in the slice range
747 rows = copy.deepcopy(self._rows[options["start"]:options["end"]])
749 if options["sortby"]:
750 sortindex = self._field_names.index(options["sortby"])
752 rows = [[row[sortindex]]+row for row in rows]
754 rows.sort(reverse=options["reversesort"], key=options["sort_key"])
756 rows = [row[1:] for row in rows]
759 ##############################
760 # PLAIN TEXT STRING METHODS #
761 ##############################
763 def get_string(self, **kwargs):
765 """Return string representation of table
in current state.
769 start - index of first data row to include
in output
770 end - index of last data row to include
in output PLUS ONE (list slice style)
771 fields - names of fields (columns) to include
772 header -
print a header showing field names (
True or False)
773 border -
print a border around the table (
True or False)
774 hrules - controls printing of horizontal rules after rows. Allowed values: FRAME, ALL, NONE
775 int_format - controls formatting of integer data
776 float_format - controls formatting of floating point data
777 padding_width - number of spaces on either side of column data (only used
if left
and right paddings are
None)
778 left_padding_width - number of spaces on left hand side of column data
779 right_padding_width - number of spaces on right hand side of column data
780 vertical_char - single character string used to draw vertical lines
781 horizontal_char - single character string used to draw horizontal lines
782 junction_char - single character string used to draw line junctions
783 sortby - name of field to sort rows by
784 sort_key - sorting key function, applied to data points before sorting
785 reversesort -
True or False to sort
in descending
or ascending order
"""
787 options = self._get_options(kwargs)
791 # Don't think too hard about an empty table
792 if self.rowcount == 0:
795 rows = self._get_rows(options)
796 self._compute_widths(rows, options)
799 # (for now, this is done before building headers etc. because rowbits.append
800 # contains width-adjusting voodoo which has to be done first. This is ugly
801 # and Wrong and will change soon)
804 rowbits.append(self._stringify_row(row, options))
807 # Add header or top of border
808 if options["header"]:
809 bits.append(self._stringify_header(options))
810 elif options["border"] and options["hrules"] != NONE:
811 bits.append(self._hrule)
816 # Add bottom of border
817 if options["border"] and not options["hrules"]:
818 bits.append(self._hrule)
820 string = "\n".join(bits)
821 self._nonunicode = string
822 return _unicode(string)
824 def _stringify_hrule(self, options):
826 if not options["border"]:
828 lpad, rpad = self._get_padding_widths(options)
829 bits = [options["junction_char"]]
830 for field, width in zip(self._field_names, self._widths):
831 if options["fields"] and field not in options["fields"]:
833 bits.append((width+lpad+rpad)*options["horizontal_char"])
834 bits.append(options["junction_char"])
837 def _stringify_header(self, options):
840 lpad, rpad = self._get_padding_widths(options)
841 if options["border"]:
842 if options["hrules"] != NONE:
843 bits.append(self._hrule)
845 bits.append(options["vertical_char"])
846 for field, width, in zip(self._field_names, self._widths):
847 if options["fields"] and field not in options["fields"]:
849 if self._align[field] == "l":
850 bits.append(" " * lpad + _unicode(field).ljust(width) + " " * rpad)
851 elif self._align[field] == "r":
852 bits.append(" " * lpad +
_unicode(field).
rjust(width) +
" " * rpad)
854 bits.append(
" " * lpad +
_unicode(field).
center(width) +
" " * rpad)
855 if options[
"border"]:
856 bits.append(options[
"vertical_char"])
857 if options[
"border"]
and options[
"hrules"] != NONE:
864 for index, value
in enumerate(row):
869 max_width = self._max_width.get(field, 0)
873 if max_width
and len(line) > max_width:
874 line = textwrap.fill(line, max_width)
875 new_lines.append(line)
877 value =
"\n".
join(lines)
883 namewidth =
len(field)
884 datawidth =
min(self.
_widths[index], self._max_width.get(field, self.
_widths[index]))
885 if options[
"header"]:
886 self.
_widths[index] =
max(namewidth, datawidth)
888 self.
_widths[index] = datawidth
898 for y
in range(0, row_height):
900 if options[
"border"]:
906 if len(lines) < row_height:
907 lines = lines + ([
""] * (row_height-
len(lines)))
911 if options[
"fields"]
and field
not in options[
"fields"]:
914 if self.
_align[field] ==
"l":
915 bits[y].append(
" " * lpad +
_unicode(l).
ljust(width) +
" " * rpad)
916 elif self.
_align[field] ==
"r":
917 bits[y].append(" " * lpad +
_unicode(l).
rjust(width) +
" " * rpad)
919 bits[y].append(
" " * lpad +
_unicode(l).
center(width) +
" " * rpad)
920 if options[
"border"]:
927 if options[
"border"]
and options[
"hrules"]== ALL:
928 bits[row_height-1].append(
"\n")
929 bits[row_height-1].append(self.
_hrule)
931 for y
in range(0, row_height):
932 bits[y] =
"".
join(bits[y])
936 return "\n".
join(bits)
944 """Return string representation of HTML formatted version of table in current state.
948 start - index of first data row to include in output
949 end - index of last data row to include in output PLUS ONE (list slice style)
950 fields - names of fields (columns) to include
951 header - print a header showing field names (True or False)
952 border - print a border around the table (True or False)
953 hrules - controls printing of horizontal rules after rows. Allowed values: FRAME, ALL, NONE
954 int_format - controls formatting of integer data
955 float_format - controls formatting of floating point data
956 padding_width - number of spaces on either side of column data (only used if left and right paddings are None)
957 left_padding_width - number of spaces on left hand side of column data
958 right_padding_width - number of spaces on right hand side of column data
959 sortby - name of field to sort rows by
960 sort_key - sorting key function, applied to data points before sorting
961 attributes - dictionary of name/value pairs to include as HTML attributes in the <table> tag"""
965 if options[
"format"]:
978 if options[
"border"]:
979 table_tag +=
' border="1"'
980 if options[
"attributes"]:
981 for attr_name
in options[
"attributes"]:
982 table_tag +=
' %s="%s"' % (attr_name, options[
"attributes"][attr_name])
984 bits.append(table_tag)
987 if options[
"header"]:
990 if options[
"fields"]
and field
not in options[
"fields"]:
992 bits.append(
" <th>%s</th>" % escape(
_unicode(field)).replace(
"\n",
"<br />"))
993 bits.append(
" </tr>")
1000 if options[
"fields"]
and field
not in options[
"fields"]:
1002 bits.append(
" <td>%s</td>" % escape(
_unicode(datum)).replace(
"\n",
"<br />"))
1003 bits.append(
" </tr>")
1005 bits.append(
"</table>")
1006 string =
"\n".
join(bits)
1016 table_tag =
'<table'
1017 if options[
"border"]:
1018 table_tag +=
' border="1"'
1019 if options[
"hrules"] == NONE:
1020 table_tag +=
' frame="vsides" rules="cols"'
1021 if options[
"attributes"]:
1022 for attr_name
in options[
"attributes"]:
1023 table_tag +=
' %s="%s"' % (attr_name, options[
"attributes"][attr_name])
1025 bits.append(table_tag)
1027 if options[
"header"]:
1028 bits.append(
" <tr>")
1030 if options[
"fields"]
and field
not in options[
"fields"]:
1032 bits.append(
" <th style=\"padding-left: %dem; padding-right: %dem; text-align: center\">%s</th>" % (lpad, rpad, escape(
_unicode(field)).replace(
"\n",
"<br />")))
1033 bits.append(
" </tr>")
1036 for row
in self.
_rows:
1037 bits.append(
" <tr>")
1039 if options[
"fields"]
and field
not in options[
"fields"]:
1041 if self.
_align[field] ==
"l":
1042 bits.append(
" <td style=\"padding-left: %dem; padding-right: %dem; text-align: left\">%s</td>" % (lpad, rpad, escape(
_unicode(datum)).replace(
"\n",
"<br />")))
1043 elif self.
_align[field] ==
"r":
1044 bits.append(" <td style=\"padding-left: %dem; padding-right: %dem; text-align: right\">%s</td>" % (lpad, rpad, escape(
_unicode(datum)).replace(
"\n",
"<br />")))
1046 bits.append(
" <td style=\"padding-left: %dem; padding-right: %dem; text-align: center\">%s</td>" % (lpad, rpad, escape(
_unicode(datum)).replace(
"\n",
"<br />")))
1047 bits.append(
" </tr>")
1048 bits.append(
"</table>")
1049 string =
"\n".
join(bits)
1056 x =
PrettyTable([
"City name",
"Area",
"Population",
"Annual Rainfall"])
1057 x.sortby =
"Population"
1058 x.reversesort =
True
1059 x.int_format[
"Area"] =
"04"
1060 x.float_format =
"6.1"
1061 x.align[
"City name"] =
"l"
1062 x.add_row([
"Adelaide", 1295, 1158259, 600.5])
1063 x.add_row([
"Brisbane", 5905, 1857594, 1146.4])
1064 x.add_row([
"Darwin", 112, 120900, 1714.7])
1065 x.add_row([
"Hobart", 1357, 205556, 619.5])
1066 x.add_row([
"Sydney", 2058, 4336374, 1214.8])
1067 x.add_row([
"Melbourne", 1566, 3806092, 646.9])
1068 x.add_row([
"Perth", 5386, 1554769, 869.4])
1071 if __name__ ==
"__main__":
xyzTriple< T > center(xyzTriple< T > const &a, xyzTriple< T > const &b)
Center of 2 xyzTriples.
Fstring::size_type len(Fstring const &s)
Length.
utility::vector1< std::string > split(const std::string &s)
split given std::string using ' ' symbol.
Fstring ljust(Fstring const &s)
Left-Justified Copy.
Fstring rjust(Fstring const &s)
Right-Justified Copy.