blob: 3eb828a9eb9885449c86bd1b5c59e5520486b5b5 [file] [log] [blame]
Zsolt Haraszti80175202016-12-24 00:17:51 -08001#
2# Copyright 2016 the original author or authors.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15#
16import sys
17
18from google.protobuf.message import Message
19from termcolor import colored
20
21_printfn = lambda l: sys.stdout.write(l + '\n')
22
23
24class TablePrinter(object):
25 """Simple tabular data printer utility. For usage, see bottom of file"""
26
27 def __init__(self):
28 self.max_field_lengths = {}
29 self.field_names = {}
30 self.cell_values = {}
31
32 def add_cell(self, row_number, field_key, field_name, value):
33 if not isinstance(value, str):
34 value = str(value)
35 self._add_field_type(field_key, field_name)
36 row = self.cell_values.setdefault(row_number, {})
37 row[field_key] = value
38 self._update_max_length(field_key, value)
39
40 def print_table(self, header=None, printfn=_printfn, dividers=10):
41
42 if header is not None:
43 printfn(header)
44
45 field_keys = sorted(self.field_names.keys())
46
47 if not field_keys:
48 printfn('table empty')
49 return
50
51 def p_sep():
52 printfn('+' + '+'.join(
53 [(self.max_field_lengths[k] + 2) * '-'
54 for k in field_keys]) + '+')
55
56 p_sep()
57
58 printfn('| ' + ' | '.join(
59 '%%%ds' % self.max_field_lengths[k] % self.field_names[k]
60 for k in field_keys) + ' |')
61 p_sep()
62
63 for i in range(len(self.cell_values)):
64 row = self.cell_values[i]
65 printfn(colored('| ' + ' | '.join(
66 '%%%ds' % self.max_field_lengths[k] % row.get(k, '')
67 for k in field_keys
68 ) + ' |'))
69 if not ((i + 1) % dividers):
70 p_sep()
71
72 if (i + 1) % dividers:
73 p_sep()
74
75 def _update_max_length(self, field_key, string):
76 length = len(string)
77 if length > self.max_field_lengths.get(field_key, 0):
78 self.max_field_lengths[field_key] = length
79
80 def _add_field_type(self, field_key, field_name):
81 if field_key not in self.field_names:
82 self.field_names[field_key] = field_name
83 self._update_max_length(field_key, field_name)
84 else:
85 assert self.field_names[field_key] == field_name
86
87
88def print_pb_table(header, items, fields_to_omit=None, printfn=_printfn):
89 from cli.utils import pb2dict
90
91 t = TablePrinter()
92 for row, obj in enumerate(items):
93 assert isinstance(obj, Message)
94
95 def add(_row, pb, prefix='', number=0):
96 d = pb2dict(pb)
97 for field in pb._fields:
98 fname = prefix + field.name
99 if fname in fields_to_omit:
100 continue
101 value = getattr(pb, field.name)
102 if isinstance(value, Message):
103 add(_row, value, fname + '.',
104 100 * (number + field.number))
105 else:
106 t.add_cell(_row, number + field.number, fname,
107 d.get(field.name))
108
109 add(row, obj)
110
111 t.print_table(header, printfn)
112
113
114if __name__ == '__main__':
115 import random
116 t = TablePrinter()
117 for row in range(10):
118 t.add_cell(row, 0, 'id', row + 100)
119 t.add_cell(row, 1, 'name', 'Joe Somebody')
120 t.add_cell(row, 2, 'ows', '${}'.format(random.randint(10, 100000)))
121 t.print_table()