Markup, whitespace, and code cleanup

This commit is contained in:
BlauFeuer 2017-02-20 02:50:15 -05:00 committed by GitHub
parent 5b86cc9bf4
commit c2fa13107f

View file

@ -65,10 +65,7 @@ else:
from cgi import escape
# hrule styles
FRAME = 0
ALL = 1
NONE = 2
HEADER = 3
FRAME, ALL, NONE, HEADER = range(4)
# Table styles
DEFAULT = 10
@ -78,12 +75,13 @@ RANDOM = 20
_re = re.compile("\033\[[0-9;]*m")
def _ansi(method):
"decorator for converting ansi in input"
"""decorator for converting ansi in input"""
def wrapper(self, *args, **kwargs):
def convert(inp):
if isinstance(inp, basestring):
return parse_ansi("{n%s{n" % inp)
return parse_ansi("|n%s|n" % inp)
elif hasattr(inp, '__iter__'):
li = []
for element in inp:
@ -96,19 +94,20 @@ def _ansi(method):
return li
return inp
args = [convert(arg) for arg in args]
#kwargs = dict((key, convert(val)) for key, val in kwargs.items())
# kwargs = dict((key, convert(val)) for key, val in kwargs.items())
return method(self, *args, **kwargs)
return wrapper
def _get_size(text):
lines = text.split("\n")
height = len(lines)
width = max([_str_block_width(line) for line in lines])
return (width, height)
return width, height
class PrettyTable(object):
@_ansi
def __init__(self, field_names=None, **kwargs):
@ -153,9 +152,12 @@ class PrettyTable(object):
self._widths = []
# Options
self._options = "start end fields header border sortby reversesort sort_key attributes format hrules vrules".split()
self._options.extend("int_format float_format padding_width left_padding_width right_padding_width".split())
self._options.extend("vertical_char horizontal_char junction_char header_style valign xhtml print_empty".split())
self._options = "start end fields header border sortby reversesort" \
" sort_key attributes format hrules vrules".split()
self._options.extend("int_format float_format padding_width "
"left_padding_width right_padding_width".split())
self._options.extend("vertical_char horizontal_char junction_char"
" header_style valign xhtml print_empty".split())
for option in self._options:
if option in kwargs:
self._validate_option(option, kwargs[option])
@ -263,10 +265,10 @@ class PrettyTable(object):
if py3k:
def __str__(self):
return self.__unicode__()
return self.__unicode__()
else:
def __str__(self):
return self.__unicode__().encode(self.encoding)
return self.__unicode__().encode(self.encoding)
def __unicode__(self):
return self.get_string()
@ -283,31 +285,32 @@ 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 ("field_names"):
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"):
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"):
elif option in "sortby":
self._validate_field_name(option, val)
elif option in ("sort_key"):
elif option in "sort_key":
self._validate_function(option, val)
elif option in ("hrules"):
elif option in "hrules":
self._validate_hrules(option, val)
elif option in ("vrules"):
elif option in "vrules":
self._validate_vrules(option, val)
elif option in ("fields"):
elif option in "fields":
self._validate_all_field_names(option, val)
elif option in ("header", "border", "reversesort", "xhtml", "print_empty"):
self._validate_true_or_false(option, val)
elif option in ("header_style"):
elif option in "header_style":
self._validate_header_style(val)
elif option in ("int_format"):
elif option in "int_format":
self._validate_int_format(option, val)
elif option in ("float_format"):
elif option in "float_format":
self._validate_float_format(option, val)
elif option in ("vertical_char", "horizontal_char", "junction_char"):
self._validate_single_char(option, val)
elif option in ("attributes"):
elif option in "attributes":
self._validate_attributes(option, val)
else:
raise Exception("Unrecognised option: %s!" % option)
@ -316,14 +319,16 @@ class PrettyTable(object):
# Check for appropriate length
if self._field_names:
try:
assert len(val) == len(self._field_names)
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)))
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])
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])))
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))
@ -338,13 +343,13 @@ class PrettyTable(object):
def _validate_align(self, val):
try:
assert val in ["l","c","r"]
assert val in ["l", "c", "r"]
except AssertionError:
raise Exception("Alignment %s is invalid, use l, c or r!" % val)
def _validate_valign(self, val):
try:
assert val in ["t","m","b",None]
assert val in ["t", "m", "b", None]
except AssertionError:
raise Exception("Alignment %s is invalid, use t, m, b or None!" % val)
@ -436,6 +441,7 @@ class PrettyTable(object):
fields - list or tuple of field names"""
return self._field_names
def _set_field_names(self, val):
val = [self._unicode(x) for x in val]
self._validate_option("field_names", val)
@ -461,30 +467,37 @@ class PrettyTable(object):
else:
for field in self._field_names:
self._valign[field] = "t"
field_names = property(_get_field_names, _set_field_names)
def _get_align(self):
return self._align
def _set_align(self, val):
self._validate_align(val)
for field in self._field_names:
self._align[field] = val
align = property(_get_align, _set_align)
def _get_valign(self):
return self._valign
def _set_valign(self, val):
self._validate_valign(val)
for field in self._field_names:
self._valign[field] = val
valign = property(_get_valign, _set_valign)
def _get_max_width(self):
return self._max_width
def _set_max_width(self, val):
self._validate_option("max_width", val)
for field in self._field_names:
self._max_width[field] = val
max_width = property(_get_max_width, _set_max_width)
def _get_fields(self):
@ -494,9 +507,11 @@ class PrettyTable(object):
fields - list or tuple of field names to include in displays"""
return self._fields
def _set_fields(self, val):
self._validate_option("fields", val)
self._fields = val
fields = property(_get_fields, _set_fields)
def _get_start(self):
@ -510,6 +525,7 @@ class PrettyTable(object):
def _set_start(self, val):
self._validate_option("start", val)
self._start = val
start = property(_get_start, _set_start)
def _get_end(self):
@ -519,9 +535,11 @@ class PrettyTable(object):
end - index of last data row to include in output PLUS ONE (list slice style)"""
return self._end
def _set_end(self, val):
self._validate_option("end", val)
self._end = val
end = property(_get_end, _set_end)
def _get_sortby(self):
@ -531,9 +549,11 @@ class PrettyTable(object):
sortby - field name to sort by"""
return self._sortby
def _set_sortby(self, val):
self._validate_option("sortby", val)
self._sortby = val
sortby = property(_get_sortby, _set_sortby)
def _get_reversesort(self):
@ -543,9 +563,11 @@ class PrettyTable(object):
reveresort - set to True to sort by descending order, or False to sort by ascending order"""
return self._reversesort
def _set_reversesort(self, val):
self._validate_option("reversesort", val)
self._reversesort = val
reversesort = property(_get_reversesort, _set_reversesort)
def _get_sort_key(self):
@ -555,9 +577,11 @@ class PrettyTable(object):
sort_key - a function which takes one argument and returns something to be sorted"""
return self._sort_key
def _set_sort_key(self, val):
self._validate_option("sort_key", val)
self._sort_key = val
sort_key = property(_get_sort_key, _set_sort_key)
def _get_header(self):
@ -567,9 +591,11 @@ class PrettyTable(object):
header - print a header showing field names (True or False)"""
return self._header
def _set_header(self, val):
self._validate_option("header", val)
self._header = val
header = property(_get_header, _set_header)
def _get_header_style(self):
@ -579,9 +605,11 @@ class PrettyTable(object):
header_style - stylisation to apply to field names in header ("cap", "title", "upper", "lower" or None)"""
return self._header_style
def _set_header_style(self, val):
self._validate_header_style(val)
self._header_style = val
header_style = property(_get_header_style, _set_header_style)
def _get_border(self):
@ -591,9 +619,11 @@ class PrettyTable(object):
border - print a border around the table (True or False)"""
return self._border
def _set_border(self, val):
self._validate_option("border", val)
self._border = val
border = property(_get_border, _set_border)
def _get_hrules(self):
@ -603,9 +633,11 @@ class PrettyTable(object):
hrules - horizontal rules style. Allowed values: FRAME, ALL, HEADER, NONE"""
return self._hrules
def _set_hrules(self, val):
self._validate_option("hrules", val)
self._hrules = val
hrules = property(_get_hrules, _set_hrules)
def _get_vrules(self):
@ -615,9 +647,11 @@ class PrettyTable(object):
vrules - vertical rules style. Allowed values: FRAME, ALL, NONE"""
return self._vrules
def _set_vrules(self, val):
self._validate_option("vrules", val)
self._vrules = val
vrules = property(_get_vrules, _set_vrules)
def _get_int_format(self):
@ -626,10 +660,12 @@ class PrettyTable(object):
int_format - integer format string"""
return self._int_format
def _set_int_format(self, val):
# self._validate_option("int_format", val)
# self._validate_option("int_format", val)
for field in self._field_names:
self._int_format[field] = val
int_format = property(_get_int_format, _set_int_format)
def _get_float_format(self):
@ -638,10 +674,12 @@ class PrettyTable(object):
float_format - floating point format string"""
return self._float_format
def _set_float_format(self, val):
# self._validate_option("float_format", val)
# self._validate_option("float_format", val)
for field in self._field_names:
self._float_format[field] = val
float_format = property(_get_float_format, _set_float_format)
def _get_padding_width(self):
@ -651,9 +689,11 @@ class PrettyTable(object):
padding_width - number of spaces, must be a positive integer"""
return self._padding_width
def _set_padding_width(self, val):
self._validate_option("padding_width", val)
self._padding_width = val
padding_width = property(_get_padding_width, _set_padding_width)
def _get_left_padding_width(self):
@ -663,9 +703,11 @@ class PrettyTable(object):
left_padding - number of spaces, must be a positive integer"""
return self._left_padding_width
def _set_left_padding_width(self, val):
self._validate_option("left_padding_width", val)
self._left_padding_width = val
left_padding_width = property(_get_left_padding_width, _set_left_padding_width)
def _get_right_padding_width(self):
@ -675,9 +717,11 @@ class PrettyTable(object):
right_padding - number of spaces, must be a positive integer"""
return self._right_padding_width
def _set_right_padding_width(self, val):
self._validate_option("right_padding_width", val)
self._right_padding_width = val
right_padding_width = property(_get_right_padding_width, _set_right_padding_width)
def _get_vertical_char(self):
@ -687,10 +731,12 @@ class PrettyTable(object):
vertical_char - single character string used to draw vertical lines"""
return self._vertical_char
def _set_vertical_char(self, val):
val = self._unicode(val)
self._validate_option("vertical_char", val)
self._vertical_char = val
vertical_char = property(_get_vertical_char, _set_vertical_char)
def _get_horizontal_char(self):
@ -700,10 +746,12 @@ class PrettyTable(object):
horizontal_char - single character string used to draw horizontal lines"""
return self._horizontal_char
def _set_horizontal_char(self, val):
val = self._unicode(val)
self._validate_option("horizontal_char", val)
self._horizontal_char = val
horizontal_char = property(_get_horizontal_char, _set_horizontal_char)
def _get_junction_char(self):
@ -713,10 +761,12 @@ class PrettyTable(object):
junction_char - single character string used to draw line junctions"""
return self._junction_char
def _set_junction_char(self, val):
val = self._unicode(val)
self._validate_option("vertical_char", val)
self._junction_char = val
junction_char = property(_get_junction_char, _set_junction_char)
def _get_format(self):
@ -726,9 +776,11 @@ class PrettyTable(object):
format - True or False"""
return self._format
def _set_format(self, val):
self._validate_option("format", val)
self._format = val
format = property(_get_format, _set_format)
def _get_print_empty(self):
@ -738,9 +790,11 @@ class PrettyTable(object):
print_empty - True or False"""
return self._print_empty
def _set_print_empty(self, val):
self._validate_option("print_empty", val)
self._print_empty = val
print_empty = property(_get_print_empty, _set_print_empty)
def _get_attributes(self):
@ -750,9 +804,11 @@ class PrettyTable(object):
attributes - dictionary of attributes"""
return self._attributes
def _set_attributes(self, val):
self._validate_option("attributes", val)
self._attributes = val
attributes = property(_get_attributes, _set_attributes)
##############################
@ -825,8 +881,8 @@ class PrettyTable(object):
self.border = random.choice((True, False))
self._hrules = random.choice((ALL, FRAME, HEADER, NONE))
self._vrules = random.choice((ALL, FRAME, NONE))
self.left_padding_width = random.randint(0,5)
self.right_padding_width = random.randint(0,5)
self.left_padding_width = random.randint(0, 5)
self.right_padding_width = random.randint(0, 5)
self.vertical_char = random.choice("~!@#$%^&*()_+|-=\{}[];':\",./;<>?")
self.horizontal_char = random.choice("~!@#$%^&*()_+|-=\{}[];':\",./;<>?")
self.junction_char = random.choice("~!@#$%^&*()_+|-=\{}[];':\",./;<>?")
@ -846,9 +902,10 @@ class PrettyTable(object):
has fields"""
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)))
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.field_names = [("Field %d" % (n+1)) for n in range(0, len(row))]
self._rows.append(list(row))
def del_row(self, row_index):
@ -860,7 +917,7 @@ class PrettyTable(object):
row_index - The index of the row you want to delete. Indexing starts at 0."""
if row_index > len(self._rows)-1:
raise Exception("Cant delete row at index %d, table only has %d rows!" % (row_index, len(self._rows)))
raise Exception("Can't delete row at index %d, table only has %d rows!" % (row_index, len(self._rows)))
del self._rows[row_index]
@_ansi
@ -1113,7 +1170,7 @@ class PrettyTable(object):
def _stringify_row(self, row, options):
for index, field, value, width, in zip(range(0,len(row)), self._field_names, row, self._widths):
for index, field, value, width, in zip(range(0, len(row)), self._field_names, row, self._widths):
# Enforce max widths
lines = value.split("\n")
new_lines = []
@ -1145,14 +1202,14 @@ class PrettyTable(object):
valign = self._valign[field]
lines = value.split("\n")
dHeight = row_height - len(lines)
if dHeight:
dheight = row_height - len(lines)
if dheight:
if valign == "m":
lines = [""] * (dHeight // 2) + lines + [""] * (dHeight - (dHeight // 2))
lines = [""] * (dheight // 2) + lines + [""] * (dheight - (dheight // 2))
elif valign == "b":
lines = [""] * dHeight + lines
lines = [""] * dheight + lines
else:
lines = lines + [""] * dHeight
lines += [""] * dheight
y = 0
for l in lines:
@ -1174,7 +1231,7 @@ class PrettyTable(object):
bits[y].pop()
bits[y].append(options["vertical_char"])
if options["border"] and options["hrules"]== ALL:
if options["border"] and options["hrules"] == ALL:
bits[row_height-1].append("\n")
bits[row_height-1].append(self._hrule)
@ -1227,8 +1284,7 @@ class PrettyTable(object):
else:
linebreak = "<br>"
open_tag = []
open_tag.append("<table")
open_tag = ["<table"]
if options["attributes"]:
for attr_name in options["attributes"]:
open_tag.append(" %s=\"%s\"" % (attr_name, options["attributes"][attr_name]))
@ -1268,8 +1324,7 @@ class PrettyTable(object):
else:
linebreak = "<br>"
open_tag = []
open_tag.append("<table")
open_tag = ["<table"]
if options["border"]:
if options["hrules"] == ALL and options["vrules"] == ALL:
open_tag.append(" frame=\"box\" rules=\"all\"")
@ -1297,7 +1352,9 @@ class PrettyTable(object):
for field in self._field_names:
if options["fields"] and field not in options["fields"]:
continue
lines.append(" <th style=\"padding-left: %dem; padding-right: %dem; text-align: center\">%s</th>" % (lpad, rpad, escape(field).replace("\n", linebreak)))
lines.append(" <th style=\"padding-left: %dem; padding-right: "
"%dem; text-align: center\">%s</th>"
% (lpad, rpad, escape(field).replace("\n", linebreak)))
lines.append(" </tr>")
# Data
@ -1306,14 +1363,16 @@ class PrettyTable(object):
aligns = []
valigns = []
for field in self._field_names:
aligns.append({ "l" : "left", "r" : "right", "c" : "center" }[self._align[field]])
valigns.append({"t" : "top", "m" : "middle", "b" : "bottom"}[self._valign[field]])
aligns.append(dict(l="left", r="right", c="center")[self._align[field]])
valigns.append(dict(t="top", m="middle", b="bottom")[self._valign[field]])
for row in formatted_rows:
lines.append(" <tr>")
for field, datum, align, valign in zip(self._field_names, row, aligns, valigns):
if options["fields"] and field not in options["fields"]:
continue
lines.append(" <td style=\"padding-left: %dem; padding-right: %dem; text-align: %s; vertical-align: %s\">%s</td>" % (lpad, rpad, align, valign, escape(datum).replace("\n", linebreak)))
lines.append(" <td style=\"padding-left: %dem; padding-right: %dem; "
"text-align: %s; vertical-align: %s\">%s</td>"
% (lpad, rpad, align, valign, escape(datum).replace("\n", linebreak)))
lines.append(" </tr>")
lines.append("</table>")
@ -1323,10 +1382,11 @@ class PrettyTable(object):
# UNICODE WIDTH FUNCTIONS #
##############################
def _char_block_width(char):
# Basic Latin, which is probably the most common case
#if char in xrange(0x0021, 0x007e):
#if char >= 0x0021 and char <= 0x007e:
# if char in xrange(0x0021, 0x007e):
# if char >= 0x0021 and char <= 0x007e:
if 0x0021 <= char <= 0x007e:
return 1
# Chinese, Japanese, Korean (common)
@ -1356,6 +1416,7 @@ def _char_block_width(char):
# Take a guess
return 1
def _str_block_width(val):
return sum(itermap(_char_block_width, itermap(ord, _re.sub("", val))))
@ -1364,7 +1425,8 @@ def _str_block_width(val):
# TABLE FACTORIES #
##############################
def from_csv(fp, field_names = None, **kwargs):
def from_csv(fp, field_names=None, **kwargs):
dialect = csv.Sniffer().sniff(fp.read(1024))
fp.seek(0)
@ -1381,6 +1443,7 @@ def from_csv(fp, field_names = None, **kwargs):
return table
def from_db_cursor(cursor, **kwargs):
if cursor.description:
@ -1390,6 +1453,7 @@ def from_db_cursor(cursor, **kwargs):
table.add_row(row)
return table
class TableHandler(HTMLParser):
def __init__(self, **kwargs):
@ -1403,12 +1467,12 @@ class TableHandler(HTMLParser):
self.last_content = ""
self.is_last_row_header = False
def handle_starttag(self,tag, attrs):
def handle_starttag(self, tag, attrs):
self.active = tag
if tag == "th":
self.is_last_row_header = True
def handle_endtag(self,tag):
def handle_endtag(self, tag):
if tag in ["th", "td"]:
stripped_content = self.last_content.strip()
self.last_row.append(stripped_content)
@ -1425,7 +1489,6 @@ class TableHandler(HTMLParser):
self.last_content = " "
self.active = None
def handle_data(self, data):
self.last_content += data
@ -1437,10 +1500,10 @@ class TableHandler(HTMLParser):
for row in self.rows:
if len(row[0]) < self.max_row_width:
appends = self.max_row_width - len(row[0])
for i in range(1,appends):
for _ in range(1, appends):
row[0].append("-")
if row[1] == True:
if row[1] is True:
self.make_fields_unique(row[0])
table.field_names = row[0]
else:
@ -1456,6 +1519,7 @@ class TableHandler(HTMLParser):
if fields[i] == fields[j]:
fields[j] += "'"
def from_html(html_code, **kwargs):
"""
Generates a list of PrettyTables from a string of HTML code. Each <table> in
@ -1466,6 +1530,7 @@ def from_html(html_code, **kwargs):
parser.feed(html_code)
return parser.tables
def from_html_one(html_code, **kwargs):
"""
Generates a PrettyTables from a string of HTML code which contains only a
@ -1483,6 +1548,7 @@ def from_html_one(html_code, **kwargs):
# MAIN (TEST FUNCTION) #
##############################
def main():
x = PrettyTable(["City name", "Area", "Population", "Annual Rainfall"])
@ -1490,7 +1556,7 @@ def main():
x.reversesort = True
x.int_format["Area"] = "04d"
x.float_format = "6.1f"
x.align["City name"] = "l" # Left align city names
x.align["City name"] = "l" # Left align city names
x.add_row(["Adelaide", 1295, 1158259, 600.5])
x.add_row(["Brisbane", 5905, 1857594, 1146.4])
x.add_row(["Darwin", 112, 120900, 1714.7])