2022-08-19 17:53:59 +00:00
|
|
|
class OutFormat:
|
|
|
|
def __init__(self, data):
|
2022-08-20 01:54:49 +00:00
|
|
|
self.data = data
|
2022-08-19 17:53:59 +00:00
|
|
|
self.spans = { }
|
|
|
|
self.rows = [ ]
|
2022-08-19 11:02:37 +00:00
|
|
|
|
2022-08-19 17:53:59 +00:00
|
|
|
for row in data:
|
|
|
|
vals = { }
|
2022-08-19 11:02:37 +00:00
|
|
|
|
2022-08-19 17:53:59 +00:00
|
|
|
for field in row:
|
|
|
|
vals[field] = self.normalize(row[field])
|
2022-08-19 11:02:37 +00:00
|
|
|
|
2022-08-19 17:53:59 +00:00
|
|
|
if field in self.spans:
|
|
|
|
self.spans[field] = max(self.spans[field], len(vals[field]))
|
|
|
|
else:
|
|
|
|
self.spans[field] = max(len(field), len(vals[field]))
|
2022-08-19 11:02:37 +00:00
|
|
|
|
2022-08-19 17:53:59 +00:00
|
|
|
self.rows.append(vals)
|
2022-08-19 11:02:37 +00:00
|
|
|
|
2022-08-19 17:53:59 +00:00
|
|
|
self.cols = list(self.spans.keys())
|
2022-08-19 11:02:37 +00:00
|
|
|
|
2022-08-19 17:53:59 +00:00
|
|
|
def normalize(self, field):
|
|
|
|
if type(field) == list:
|
|
|
|
return ", ".join(field)
|
2022-08-19 11:02:37 +00:00
|
|
|
else:
|
2022-08-19 17:53:59 +00:00
|
|
|
return str(field)
|
|
|
|
|
|
|
|
def render(self):
|
2022-08-20 01:54:49 +00:00
|
|
|
return self.data
|
2022-08-19 17:53:59 +00:00
|
|
|
|
|
|
|
class Basic(OutFormat):
|
|
|
|
def __init__(self, data):
|
|
|
|
super().__init__(data)
|
|
|
|
|
|
|
|
self.top = {
|
|
|
|
"left": "+", "right": "+",
|
|
|
|
"divide": "+", "fill": "-"
|
|
|
|
}
|
|
|
|
|
|
|
|
self.base = {
|
|
|
|
"left": "+", "right": "+",
|
|
|
|
"divide": "+", "fill": "-"
|
|
|
|
}
|
|
|
|
|
|
|
|
self.sep = {
|
|
|
|
"left": "|", "right": "|",
|
|
|
|
"divide": "+", "fill": "-"
|
|
|
|
}
|
|
|
|
|
|
|
|
self.row = {
|
|
|
|
"left": "|", "right": "|",
|
|
|
|
"divide": "|", "fill": " "
|
|
|
|
}
|
|
|
|
|
|
|
|
def render(self):
|
|
|
|
sep = ""
|
|
|
|
top = ""
|
|
|
|
hdr = ""
|
|
|
|
base = ""
|
|
|
|
fill = self.row["fill"]
|
|
|
|
|
|
|
|
for col in self.cols:
|
|
|
|
width = self.spans[col] + 2
|
|
|
|
sep += self.sep["divide"] + self.sep["fill"] * width
|
|
|
|
top += self.top["divide"] + self.top["fill"] * width
|
|
|
|
hdr += self.row["divide"] + fill + col.ljust(width - 1, fill)
|
|
|
|
base += self.base["divide"] + self.base["fill"] * width
|
|
|
|
|
|
|
|
sep = self.sep["left"] + sep[1:] + self.sep["right"] + "\n"
|
|
|
|
top = self.top["left"] + top[1:] + self.top["right"] + "\n"
|
|
|
|
hdr = self.row["left"] + hdr[1:] + self.row["right"] + "\n"
|
|
|
|
base = self.base["left"] + base[1:] + self.base["right"]
|
|
|
|
lines = [ ]
|
|
|
|
|
|
|
|
for row in self.rows:
|
|
|
|
line = ""
|
|
|
|
|
|
|
|
for col in self.cols:
|
|
|
|
width = self.spans[col] + 2
|
|
|
|
|
|
|
|
if col in row:
|
|
|
|
line += self.row["divide"] + fill + row[col].ljust(width - 1, fill)
|
|
|
|
else:
|
|
|
|
line += slef.row["divide"] + fill * width
|
|
|
|
|
|
|
|
lines.append(self.row["left"] + line[1:] + self.row["right"] + "\n")
|
|
|
|
|
|
|
|
return top + sep.join([hdr, *lines]) + base
|
|
|
|
|
|
|
|
class Table(Basic):
|
|
|
|
def __init__(self, data):
|
|
|
|
super().__init__(data)
|
|
|
|
|
|
|
|
self.top = {
|
|
|
|
"left": "\u250F", "right": "\u2513",
|
|
|
|
"divide": "\u2533", "fill": "\u2501"
|
|
|
|
}
|
|
|
|
|
|
|
|
self.base = {
|
|
|
|
"left": "\u2517", "right": "\u251B",
|
|
|
|
"divide": "\u253B", "fill": "\u2501"
|
|
|
|
}
|
|
|
|
|
|
|
|
self.sep = {
|
|
|
|
"left": "\u2523", "right": "\u252B",
|
|
|
|
"divide": "\u254B", "fill": "\u2501"
|
|
|
|
}
|
|
|
|
|
|
|
|
self.row = {
|
|
|
|
"left": "\u2503", "right": "\u2503",
|
|
|
|
"divide": "\u2503", "fill": " "
|
|
|
|
}
|
|
|
|
|
|
|
|
class Json(OutFormat):
|
|
|
|
pass
|
|
|
|
|
|
|
|
class Csv(OutFormat):
|
|
|
|
pass
|
|
|
|
|
|
|
|
FORMATS = {
|
|
|
|
"basic": Basic,
|
|
|
|
"table": Table,
|
|
|
|
"json": Json,
|
|
|
|
"csv": Csv
|
|
|
|
}
|