# -*- coding: utf-8 -*-
# mitschreiben
# ------------
# Python library supplying a tool to record values during calculations
#
# Author: sonntagsgesicht, based on a fork of Deutsche Postbank [pbrisk]
# Version: 0.3, copyright Wednesday, 18 September 2019
# Website: https://github.com/sonntagsgesicht/mitschreiben
# License: Apache License 2.0 (see LICENSE file)
[docs]class Table(object):
"""
A table consist of columns and rows. Each entry has a row and a column key.
"""
def __init__(self, default_value=None, name=None, left_upper=None):
self.row_keys = []
self.col_keys = []
self._values = {}
self._default_value = default_value
self.name = name
self.left_upper = left_upper
@property
def rows_count(self):
return len(self.row_keys)
@property
def cols_count(self):
return len(self.col_keys)
[docs] def is_empty(self):
return len(self.row_keys) == 0 or len(self.col_keys) == 0
[docs] def transpose(self):
ret = Table(name=self.name, left_upper=self.left_upper, default_value=self._default_value)
for row_key in self.row_keys:
for col_key in self.col_keys:
ret.append(col_key, row_key, self.get(row_key, col_key))
return ret
[docs] def append(self, row_key, col_key, value):
col_dict = self._values.get(row_key, None)
if col_dict is None:
self._values[row_key] = {col_key: value}
self.row_keys.append(row_key)
else:
col_dict[col_key] = value
if col_key not in self.col_keys:
self.col_keys.append(col_key)
[docs] def append_row(self, row_key, row):
for col_key, value in list(row.items()):
self.append(row_key, col_key, value)
[docs] def get(self, row_key, col_key):
row_dict = self._values.get(row_key, None)
if row_dict is None:
return self._default_value
ret = row_dict.get(col_key, self._default_value)
return ret
def __call__(self, row_key, col_key):
return self.get(row_key, col_key)
[docs] def get_row(self, row_key):
ret = {}
for col_key in self.col_keys:
ret[col_key] = self.get(row_key, col_key)
return ret
[docs] def get_row_list(self, row_key, col_keys):
"""
returns the values of the row:row_key for all col_keys.
"""
return [self(row_key, col_key) for col_key in col_keys]
[docs] def get_column(self, col_key):
ret = {}
for row_key in self.row_keys:
ret[row_key] = self.get(row_key, col_key)
return ret
[docs] def get_default(self):
return self._default_value
[docs] def sort(self, row_compare=None, column_compare=None):
ret = Table(name=self.name, left_upper=self.left_upper, default_value=self._default_value)
sortrow_keys = sorted(self.row_keys, key=row_compare)
sortcol_keys = sorted(self.col_keys, key=column_compare)
for row_key in sortrow_keys:
for col_key in sortcol_keys:
ret.append(row_key, col_key, self.get(row_key, col_key))
return ret
[docs] def to_csv(self, leftUpper=None, tabName=None, separator=';'):
repr = list()
col_keys = sorted(self.col_keys)
repr.append(""+separator+separator.join(col_keys))
for key in self.row_keys:
elements = [key]+self.get_row_list(key, col_keys)
elements = list(map(str, elements))
repr.append(separator.join(elements))
return "\n".join(repr)
[docs] def pretty_string(self, leftUpper=None, tabName=None, separator=" | "):
representation = []
name = tabName if tabName is not None else self.name
if name is not None:
representation.append(name)
if len(self.row_keys) == 0 or len(self.col_keys) == 0:
return '\n'.join(representation + ['Empty Table'])
tab = self
line = leftUpper if leftUpper is not None else (self.left_upper if self.left_upper is not None else '')
max_row_key_width = max(list(map(len, list(map(str,tab.row_keys)) + [line])))
line = "{text:>{len}}".format(text=line, len=max_row_key_width)
max_colkey_width = dict()
for col_key in tab.col_keys:
max_colkey_width[col_key] = max([len(str(x)) for x in list(tab.get_column(col_key).values()) + [col_key]])
for col_key in tab.col_keys:
line += "{sep}{col:>{width}}".format(sep=separator, col=col_key, width=max_colkey_width[col_key])
representation.append(line)
for row_key in tab.row_keys:
line = "{ROW:>{len}}".format(ROW=row_key, len=max_row_key_width)
for col_key in tab.col_keys:
element = str(tab.get(row_key, col_key))
line += "{sep}{ELEMENT:>{width}}".format(ELEMENT=element, sep = separator, width = max_colkey_width[col_key])
representation.append(line)
return '\n'.join(representation)
[docs] def to_html(self):
rows = self.to_nested_list()
s = "<table>\n"
s += "<tr class='headrow'>\n"
s += "<th colspan='{number}'>{tabname}</th>\n".format(number=len(rows[0]), tabname = self.name)
s += "</tr>\n"
header = rows[0]
s += "<tr class='bodyrow'>\n"
for cell in header:
s += "<th>{}</th>\n".format(cell)
s += "</tr>\n"
for row in rows[1:]:
s += "<tr class='bodyrow'>\n"
s += "<th>{}</th>\n".format(row[0])
for cell in row[1:]:
s += "<td>{}</td>\n".format(cell)
s +="</tr>"
s+="</table>"
return s
[docs] def to_nested_list(self):
"""returns the table as a nested list rows"""
header = [k for k in self.col_keys]
header.insert(0, " ")
rows = [header]
for row_key in self.row_keys:
row = self.get_row_list(row_key, self.col_keys)
row.insert(0, row_key)
rows.append(row)
return rows
[docs] @staticmethod
def create_from_json_dict(json_dict):
ret = Table(name=json_dict['TableName'], left_upper=json_dict['LeftUpper'])
table_rows = json_dict['Table']
header = table_rows[0][1:]
first_col = [row[0] for row in table_rows][1:]
for r in range(len(first_col)):
row = table_rows[r + 1]
for c in range(len(header)):
ret.append(first_col[r], header[c], row[c + 1])
return ret