Source code for taurus.console.table

#!/usr/bin/env python

#############################################################################
##
# This file is part of Taurus
##
# http://taurus-scada.org
##
# Copyright 2011 CELLS / ALBA Synchrotron, Bellaterra, Spain
##
# Taurus is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
##
# Taurus is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
##
# You should have received a copy of the GNU Lesser General Public License
# along with Taurus.  If not, see <http://www.gnu.org/licenses/>.
##
#############################################################################

""" """
from __future__ import division
from builtins import map
from builtins import range
from builtins import object
from past.utils import old_div
from functools import reduce

__all__ = ["Table"]

__docformat__ = "restructuredtext"


[docs]class Table(object): DefTermWidth = 80 PrettyOpts = {'col_sep': ' |', 'col_head_sep': '-', 'border': '='} def __init__(self, elem_list, elem_fmt=None, term_width=None, row_head_str=None, row_head_fmt='%-*s', row_head_width=None, col_head_str=None, col_head_fmt='%*s', col_head_width=None, col_sep=' ', row_sep=' ', col_head_sep=None, border=None): self.nr_col = len(elem_list) self.nr_row = len(elem_list[0]) self.elem_list = elem_list if elem_fmt is None: elem_fmt = self.nr_row * ['%*s'] if len(elem_fmt) == 1: elem_fmt *= self.nr_row self.elem_fmt = elem_fmt self.term_width = term_width or Table.DefTermWidth self.col_sep = col_sep self.row_sep = row_sep self.col_head_sep = col_head_sep self.border = border max_len_fn = lambda x: reduce(max, list(map(len, x))) self.row_head_str = row_head_str self.row_head_fmt = row_head_fmt if row_head_str is not None and len(row_head_str) != self.nr_row: msg = 'RowHeadStr nr (%d) and RowNr (%d) mistmatch' % \ (len(row_head_str), self.nr_row) raise ValueError(msg) if row_head_width is None: if row_head_str is not None: row_head_width = max_len_fn(row_head_str) else: row_head_width = 0 self.row_head_width = row_head_width self.col_head_str = col_head_str self.col_head_fmt = col_head_fmt if col_head_str is not None and len(col_head_str) != self.nr_col: msg = 'ColHeadStr nr (%d) and ColNr (%d) mistmatch' % ( len(col_head_str), self.nr_col) raise ValueError(msg) if col_head_width is None: if col_head_str is not None: col_head_width = reduce(max, list(map(max_len_fn, col_head_str))) else: col_head_width = 10 self.col_head_width = col_head_width if col_head_str is not None: self.col_head_lines = len(col_head_str[0]) else: self.col_head_lines = 0
[docs] def updateElem(self, elem_list): new_col, new_row = len(elem_list), len(elem_list[0]) if new_col != self.nr_col or new_row != self.nr_row: raise 'Invalid new elem list size %dx%d, was %dx%d' % \ (new_col, new_row, self.nr_col, self.nr_row) self.elem_list = elem_list
[docs] def genOutput(self, term_width=None): if term_width is None: term_width = self.term_width rhw, chw = self.row_head_width, self.col_head_width chl = self.col_head_lines lcs = len(self.col_sep) width = term_width - chw # At least one disp column! if rhw > 0: width -= rhw + lcs disp_cols = old_div(width, (chw + lcs)) + 1 tot_width = chw + (disp_cols - 1) * (chw + lcs) tot_rows = chl + self.nr_row if rhw > 0: tot_width += rhw + lcs output = [] if self.row_head_str is not None: row_head = [] fmt = self.row_head_fmt for head in [''] * chl + self.row_head_str: head = fmt % (rhw, head) row_head.append(head + self.col_sep) else: row_head = [''] * tot_rows for i in range(0, self.nr_col, disp_cols): if i > 0: nr_sep = old_div(tot_width, len(self.row_sep)) output.append(self.row_sep * nr_sep) row_end = min(i + disp_cols, self.nr_col) line = list(row_head) for j in range(i, row_end): elem = self.elem_list[j] if chl: col_head = self.col_head_str[j] if j > i: for k in range(tot_rows): line[k] += self.col_sep fmt = self.col_head_fmt for k in range(chl): line[k] += fmt % (chw, col_head[k]) for k in range(self.nr_row): fmt = self.elem_fmt[k] line[chl + k] += fmt % (chw, elem[k]) max_width = reduce(max, list(map(len, line))) if self.border is not None: nr_border = old_div(max_width, len(self.border)) output.append(self.border * nr_border) for l in line[:chl]: output.append(l) if self.col_head_sep is not None: nr_sep = old_div(max_width, len(self.col_head_sep)) output.append(self.col_head_sep * nr_sep) for l in line[chl:]: output.append(l) if self.border is not None: output.append(self.border * nr_border) return output