Remove obsolete convert_size function
[deliverable/lttng-analyses.git] / lttnganalyses / ascii_graph / __init__.py
CommitLineData
846cf979 1#!/usr/bin/env python
2150109a
JD
2#
3# Copyright (c) 2012 Pierre-Francois Carpentier <carpentier.pf@gmail.com>
4#
5# https://github.com/kakwa/py-ascii-graph/
6#
7# Permission is hereby granted, free of charge, to any person obtaining
8# a copy of this software and associated documentation files (the
9# "Software"), to deal in the Software without restriction, including
10# without limitation the rights to use, copy, modify, merge, publish,
11# distribute, sublicense, and/or sell copies of the Software, and to
12# permit persons to whom the Software is furnished to do so, subject to
13# the following conditions:
14#
15# The above copyright notice and this permission notice shall be
16# included in all copies or substantial portions of the Software.
17#
18# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
846cf979
JD
25
26from __future__ import unicode_literals
27import sys
17818137 28import os
846cf979 29
846cf979 30
8054fc4c
SG
31class Pyasciigraph:
32 def __init__(self, line_length=79, min_graph_length=50,
33 separator_length=2):
846cf979 34 """Constructor of Pyasciigraph
8054fc4c 35
846cf979 36 :param int line_length: the max number of char on a line
8054fc4c 37 if any line cannot be shorter,
846cf979
JD
38 it will go over this limit
39 :param int min_graph_length: the min number of char used by the graph
40 :param int separator_length: the length of field separator
41 """
42 self.line_length = line_length
43 self.separator_length = separator_length
44 self.min_graph_length = min_graph_length
45
46 def _u(self, x):
47 if sys.version < '3':
48 import codecs
49 return codecs.unicode_escape_decode(x)[0]
50 else:
51 return x
52
53 def _get_maximum(self, data):
54 all_max = {}
55 all_max['value_max_length'] = 0
56 all_max['info_max_length'] = 0
57 all_max['max_value'] = 0
58
59 for (info, value) in data:
60 if value > all_max['max_value']:
61 all_max['max_value'] = value
62
63 if len(info) > all_max['info_max_length']:
64 all_max['info_max_length'] = len(info)
8054fc4c 65
846cf979
JD
66 if len(str(value)) > all_max['value_max_length']:
67 all_max['value_max_length'] = len(str(value))
68 return all_max
69
70 def _gen_graph_string(self, value, max_value, graph_length, start_value):
40fbd9cc
JD
71 if max_value == 0:
72 number_of_square = int(value * graph_length)
73 else:
74 number_of_square = int(value * graph_length / max_value)
846cf979
JD
75 number_of_space = int(start_value - number_of_square)
76 return '█' * number_of_square + self._u(' ') * number_of_space
77
17818137
JD
78 def _console_size(self):
79 TERMSIZE = 80
80 return int(os.environ.get('COLUMNS', TERMSIZE)) - 1
81
952b1e1f 82 def _gen_info_string(self, info, start_info, line_length, info_before):
846cf979 83 number_of_space = (line_length - start_info - len(info))
952b1e1f
JD
84 if info_before:
85 return self._u(' ') * number_of_space + info
86 else:
87 return info + self._u(' ') * number_of_space
846cf979 88
09071fb9
JD
89 def _gen_value_string(self, value, start_value, start_info, unit, count):
90 if not count:
91 v = str("%0.02f" % value)
92 else:
93 # we don't want to add .00 to count values (only integers)
94 v = str(value)
846cf979 95 number_space = start_info -\
8054fc4c 96 start_value -\
8e05871d 97 len(v) -\
8054fc4c 98 self.separator_length
846cf979 99
8054fc4c 100 return ' ' * number_space +\
8e05871d 101 v + str(unit) +\
8054fc4c 102 ' ' * self.separator_length
846cf979
JD
103
104 def _sanitize_string(self, string):
8054fc4c 105 # get the type of a unicode string
846cf979
JD
106 unicode_type = type(self._u('t'))
107 input_type = type(string)
108 if input_type is str:
ddefe9a6 109 if sys.version_info.major < 3: # pragma: no cover
db1cc4db 110 info = string
8054fc4c 111 else:
846cf979
JD
112 info = string
113 elif input_type is unicode_type:
114 info = string
115 elif input_type is int or input_type is float:
ddefe9a6 116 if sys.version_info.major < 3: # pragma: no cover
db1cc4db 117 info = string
846cf979
JD
118 else:
119 info = str(string)
120 return info
121
122 def _sanitize_data(self, data):
123 ret = []
124 for item in data:
125 ret.append((self._sanitize_string(item[0]), item[1]))
126 return ret
127
952b1e1f 128 def graph(self, label, data, sort=0, with_value=True, unit="",
09071fb9 129 info_before=False, count=False):
846cf979 130 """function generating the graph
8054fc4c 131
846cf979
JD
132 :param string label: the label of the graph
133 :param iterable data: the data (list of tuple (info, value))
134 info must be "castable" to a unicode string
135 value must be an int or a float
136 :param int sort: flag sorted
137 0: not sorted (same order as given) (default)
138 1: increasing order
139 2: decreasing order
140 :param boolean with_value: flag printing value
141 True: print the numeric value (default)
142 False: don't print the numeric value
143 :rtype: a list of strings (each lines)
144
145 """
146 result = []
147 san_data = self._sanitize_data(data)
148 san_label = self._sanitize_string(label)
149
150 if sort == 1:
8054fc4c
SG
151 san_data = sorted(san_data, key=lambda value: value[1],
152 reverse=False)
846cf979 153 elif sort == 2:
8054fc4c
SG
154 san_data = sorted(san_data, key=lambda value: value[1],
155 reverse=True)
846cf979
JD
156
157 all_max = self._get_maximum(san_data)
8054fc4c 158
846cf979 159 real_line_length = max(self.line_length, len(label))
8054fc4c 160
846cf979 161 min_line_length = self.min_graph_length +\
8054fc4c
SG
162 2 * self.separator_length +\
163 all_max['value_max_length'] +\
164 all_max['info_max_length']
846cf979
JD
165
166 if min_line_length < real_line_length:
8054fc4c 167 # calcul of where to start info
846cf979 168 start_info = self.line_length -\
8054fc4c
SG
169 all_max['info_max_length']
170 # calcul of where to start value
846cf979 171 start_value = start_info -\
8054fc4c
SG
172 self.separator_length -\
173 all_max['value_max_length']
174 # calcul of where to end graph
846cf979 175 graph_length = start_value -\
8054fc4c 176 self.separator_length
846cf979 177 else:
8054fc4c 178 # calcul of where to start value
846cf979 179 start_value = self.min_graph_length +\
8054fc4c
SG
180 self.separator_length
181 # calcul of where to start info
846cf979 182 start_info = start_value +\
8054fc4c
SG
183 all_max['value_max_length'] +\
184 self.separator_length
185 # calcul of where to end graph
846cf979 186 graph_length = self.min_graph_length
8054fc4c 187 # calcul of the real line length
846cf979
JD
188 real_line_length = min_line_length
189
17818137 190 real_line_length = min(real_line_length, self._console_size())
846cf979 191 result.append(san_label)
8054fc4c 192 result.append(self._u('#') * real_line_length)
846cf979
JD
193
194 for item in san_data:
195 info = item[0]
196 value = item[1]
197
198 graph_string = self._gen_graph_string(
8054fc4c
SG
199 value,
200 all_max['max_value'],
201 graph_length,
202 start_value)
846cf979 203
452b4312
JD
204 if with_value:
205 value_string = self._gen_value_string(
206 value,
207 start_value,
09071fb9 208 start_info, unit, count)
452b4312
JD
209 else:
210 value_string = ""
846cf979
JD
211
212 info_string = self._gen_info_string(
8054fc4c
SG
213 info,
214 start_info,
952b1e1f
JD
215 real_line_length, info_before)
216 if info_before:
217 new_line = info_string + " " + graph_string + value_string
218 else:
219 new_line = graph_string + value_string + info_string
846cf979
JD
220 result.append(new_line)
221
222 return result
223
224if __name__ == '__main__':
8054fc4c
SG
225 test = [('long_label', 423), ('sl', 1234), ('line3', 531),
226 ('line4', 200), ('line5', 834)]
846cf979 227 graph = Pyasciigraph()
8054fc4c 228 for line in graph.graph('test print', test):
846cf979 229 print(line)
This page took 0.035092 seconds and 5 git commands to generate.