summaryrefslogtreecommitdiff
path: root/contrib/python/cmd/lib/report.py
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/python/cmd/lib/report.py')
-rw-r--r--contrib/python/cmd/lib/report.py67
1 files changed, 67 insertions, 0 deletions
diff --git a/contrib/python/cmd/lib/report.py b/contrib/python/cmd/lib/report.py
new file mode 100644
index 000000000..25fe2ae0d
--- /dev/null
+++ b/contrib/python/cmd/lib/report.py
@@ -0,0 +1,67 @@
+"""Report Manager."""
+import sys
+from collections import namedtuple
+
+from .future_abstract import AbstractContextManager
+
+
+class ReportColumn(namedtuple('ReportColumn', 'key display width default')):
+ """Hold attributes of output column."""
+
+ __slots__ = ()
+
+ def __new__(cls, key, display, width, default=None):
+ """Add defaults for attributes."""
+ return super(ReportColumn, cls).__new__(cls, key, display, width,
+ default)
+
+
+class Report(AbstractContextManager):
+ """Report Manager."""
+
+ def __init__(self, columns, heading=True, epilog=None, file=sys.stdout):
+ """Construct Report.
+
+ columns is a mapping for named fields to column headings.
+ headers True prints headers on table.
+ epilog will be printed when the report context is closed.
+ """
+ self._columns = columns
+ self._file = file
+ self._heading = heading
+ self.epilog = epilog
+ self._format = None
+
+ def row(self, **fields):
+ """Print row for report."""
+ if self._heading:
+ hdrs = {k: v.display for (k, v) in self._columns.items()}
+ print(self._format.format(**hdrs), flush=True, file=self._file)
+ self._heading = False
+ fields = {k: str(v) for k, v in fields.items()}
+ print(self._format.format(**fields))
+
+ def __exit__(self, exc_type, exc_value, traceback):
+ """Leave Report context and print epilog if provided."""
+ if self.epilog:
+ print(self.epilog, flush=True, file=self._file)
+
+ def layout(self, iterable, keys, truncate=True):
+ """Use data and headings build format for table to fit."""
+ format = []
+
+ for key in keys:
+ value = max(map(lambda x: len(str(x.get(key, ''))), iterable))
+ # print('key', key, 'value', value)
+
+ if truncate:
+ row = self._columns.get(
+ key, ReportColumn(key, key.upper(), len(key)))
+ if value < row.width:
+ step = row.width if value == 0 else value
+ value = max(len(key), step)
+ elif value > row.width:
+ value = row.width if row.width != 0 else value
+
+ format.append('{{{0}:{1}.{1}}}'.format(key, value))
+ self._format = ' '.join(format)