Statistics
| Branch: | Tag: | Revision:

root / kamaki / cli / utils.py @ bd40efdf

History | View | Annotate | Download (9.7 kB)

1 7493ccb6 Stavros Sachtouris
# Copyright 2011 GRNET S.A. All rights reserved.
2 7493ccb6 Stavros Sachtouris
#
3 7493ccb6 Stavros Sachtouris
# Redistribution and use in source and binary forms, with or
4 7493ccb6 Stavros Sachtouris
# without modification, are permitted provided that the following
5 7493ccb6 Stavros Sachtouris
# conditions are met:
6 7493ccb6 Stavros Sachtouris
#
7 7493ccb6 Stavros Sachtouris
#   1. Redistributions of source code must retain the above
8 7493ccb6 Stavros Sachtouris
#      copyright notice, this list of conditions and the following
9 7493ccb6 Stavros Sachtouris
#      disclaimer.
10 7493ccb6 Stavros Sachtouris
#
11 7493ccb6 Stavros Sachtouris
#   2. Redistributions in binary form must reproduce the above
12 7493ccb6 Stavros Sachtouris
#      copyright notice, this list of conditions and the following
13 7493ccb6 Stavros Sachtouris
#      disclaimer in the documentation and/or other materials
14 7493ccb6 Stavros Sachtouris
#      provided with the distribution.
15 7493ccb6 Stavros Sachtouris
#
16 7493ccb6 Stavros Sachtouris
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 7493ccb6 Stavros Sachtouris
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 7493ccb6 Stavros Sachtouris
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 7493ccb6 Stavros Sachtouris
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 7493ccb6 Stavros Sachtouris
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 7493ccb6 Stavros Sachtouris
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 7493ccb6 Stavros Sachtouris
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 7493ccb6 Stavros Sachtouris
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 7493ccb6 Stavros Sachtouris
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 7493ccb6 Stavros Sachtouris
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 7493ccb6 Stavros Sachtouris
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 7493ccb6 Stavros Sachtouris
# POSSIBILITY OF SUCH DAMAGE.
28 7493ccb6 Stavros Sachtouris
#
29 7493ccb6 Stavros Sachtouris
# The views and conclusions contained in the software and
30 7493ccb6 Stavros Sachtouris
# documentation are those of the authors and should not be
31 7493ccb6 Stavros Sachtouris
# interpreted as representing official policies, either expressed
32 7493ccb6 Stavros Sachtouris
# or implied, of GRNET S.A.
33 3dabe5d2 Stavros Sachtouris
34 bd40efdf Stavros Sachtouris
from sys import stdout, stdin
35 efbcdc41 Stavros Sachtouris
from re import compile as regex_compile
36 2ff0b7bd Stavros Sachtouris
from kamaki.cli.errors import raiseCLIError
37 3dabe5d2 Stavros Sachtouris
38 dfee2caf Stavros Sachtouris
try:
39 dfee2caf Stavros Sachtouris
    from colors import magenta, red, yellow, bold
40 dfee2caf Stavros Sachtouris
except ImportError:
41 3dabe5d2 Stavros Sachtouris
    # No colours? No worries, use dummy foo instead
42 f93854ae Stavros Sachtouris
    def dummy(val):
43 dfee2caf Stavros Sachtouris
        return val
44 f93854ae Stavros Sachtouris
    red = yellow = magenta = bold = dummy
45 f997679d Stavros Sachtouris
46 fd5db045 Stavros Sachtouris
47 67cea04c Stavros Sachtouris
def remove_colors():
48 67cea04c Stavros Sachtouris
    global bold
49 3dabe5d2 Stavros Sachtouris
    global red
50 3dabe5d2 Stavros Sachtouris
    global yellow
51 3dabe5d2 Stavros Sachtouris
    global magenta
52 fd5db045 Stavros Sachtouris
53 67cea04c Stavros Sachtouris
    def dummy(val):
54 67cea04c Stavros Sachtouris
        return val
55 3dabe5d2 Stavros Sachtouris
    red = yellow = magenta = bold = dummy
56 7493ccb6 Stavros Sachtouris
57 fd5db045 Stavros Sachtouris
58 7493ccb6 Stavros Sachtouris
def pretty_keys(d, delim='_', recurcive=False):
59 f23a5cdb Stavros Sachtouris
    """<term>delim<term> to <term> <term> transformation
60 7493ccb6 Stavros Sachtouris
    """
61 7493ccb6 Stavros Sachtouris
    new_d = {}
62 7493ccb6 Stavros Sachtouris
    for key, val in d.items():
63 7493ccb6 Stavros Sachtouris
        new_key = key.split(delim)[-1]
64 7493ccb6 Stavros Sachtouris
        if recurcive and isinstance(val, dict):
65 fd5db045 Stavros Sachtouris
            new_val = pretty_keys(val, delim, recurcive)
66 7493ccb6 Stavros Sachtouris
        else:
67 7493ccb6 Stavros Sachtouris
            new_val = val
68 7493ccb6 Stavros Sachtouris
        new_d[new_key] = new_val
69 7493ccb6 Stavros Sachtouris
    return new_d
70 7493ccb6 Stavros Sachtouris
71 fd5db045 Stavros Sachtouris
72 f8681ec8 Stavros Sachtouris
def print_dict(d,
73 f8681ec8 Stavros Sachtouris
    exclude=(),
74 f8681ec8 Stavros Sachtouris
    ident=0,
75 f8681ec8 Stavros Sachtouris
    with_enumeration=False,
76 f8681ec8 Stavros Sachtouris
    recursive_enumeration=False):
77 f8681ec8 Stavros Sachtouris
    """
78 f8681ec8 Stavros Sachtouris
    Pretty-print a dictionary object
79 f8681ec8 Stavros Sachtouris

80 f8681ec8 Stavros Sachtouris
    :param d: (dict) the input
81 f8681ec8 Stavros Sachtouris

82 f8681ec8 Stavros Sachtouris
    :param excelude: (set or list) keys to exclude from printing
83 f8681ec8 Stavros Sachtouris

84 f8681ec8 Stavros Sachtouris
    :param ident: (int) initial indentation (recursive)
85 f8681ec8 Stavros Sachtouris

86 f8681ec8 Stavros Sachtouris
    :param with_enumeration: (bool) enumerate each 1st level key if true
87 f8681ec8 Stavros Sachtouris

88 f8681ec8 Stavros Sachtouris
    :recursive_enumeration: (bool) recursively enumerate dicts and lists of
89 f8681ec8 Stavros Sachtouris
        2nd level or deeper
90 f8681ec8 Stavros Sachtouris

91 f8681ec8 Stavros Sachtouris
    :raises CLIError: (TypeError wrapper) non-dict input
92 f8681ec8 Stavros Sachtouris
    """
93 7493ccb6 Stavros Sachtouris
    if not isinstance(d, dict):
94 2ff0b7bd Stavros Sachtouris
        raiseCLIError(TypeError('Cannot dict_print a non-dict object'))
95 f551841a Stavros Sachtouris
96 db950b10 Stavros Sachtouris
    if d:
97 db950b10 Stavros Sachtouris
        margin = max(len(unicode(key).strip())\
98 db950b10 Stavros Sachtouris
            for key in d.keys() if key not in exclude)
99 7493ccb6 Stavros Sachtouris
100 f8681ec8 Stavros Sachtouris
    counter = 1
101 7493ccb6 Stavros Sachtouris
    for key, val in sorted(d.items()):
102 7493ccb6 Stavros Sachtouris
        if key in exclude:
103 7493ccb6 Stavros Sachtouris
            continue
104 f8681ec8 Stavros Sachtouris
        print_str = ''
105 f8681ec8 Stavros Sachtouris
        if with_enumeration:
106 f8681ec8 Stavros Sachtouris
            print_str = '%s. ' % counter
107 f8681ec8 Stavros Sachtouris
            counter += 1
108 f8681ec8 Stavros Sachtouris
        print_str = '%s%s' % (' ' * (ident - len(print_str)), print_str)
109 f551841a Stavros Sachtouris
        print_str += ('%s' % key).strip()
110 f551841a Stavros Sachtouris
        print_str += ' ' * (margin - len(unicode(key).strip()))
111 f551841a Stavros Sachtouris
        print_str += ': '
112 7493ccb6 Stavros Sachtouris
        if isinstance(val, dict):
113 f551841a Stavros Sachtouris
            print(print_str)
114 f8681ec8 Stavros Sachtouris
            print_dict(val,
115 f8681ec8 Stavros Sachtouris
                exclude=exclude,
116 f8681ec8 Stavros Sachtouris
                ident=margin + ident,
117 f8681ec8 Stavros Sachtouris
                with_enumeration=recursive_enumeration,
118 f8681ec8 Stavros Sachtouris
                recursive_enumeration=recursive_enumeration)
119 7493ccb6 Stavros Sachtouris
        elif isinstance(val, list):
120 f551841a Stavros Sachtouris
            print(print_str)
121 f8681ec8 Stavros Sachtouris
            print_list(val,
122 f8681ec8 Stavros Sachtouris
                exclude=exclude,
123 f8681ec8 Stavros Sachtouris
                ident=margin + ident,
124 f8681ec8 Stavros Sachtouris
                with_enumeration=recursive_enumeration,
125 f8681ec8 Stavros Sachtouris
                recursive_enumeration=recursive_enumeration)
126 7493ccb6 Stavros Sachtouris
        else:
127 0d249b3e Stavros Sachtouris
            print print_str + ' ' + unicode(val).strip()
128 fd5db045 Stavros Sachtouris
129 7493ccb6 Stavros Sachtouris
130 f8681ec8 Stavros Sachtouris
def print_list(l,
131 f8681ec8 Stavros Sachtouris
    exclude=(),
132 f8681ec8 Stavros Sachtouris
    ident=0,
133 f8681ec8 Stavros Sachtouris
    with_enumeration=False,
134 f8681ec8 Stavros Sachtouris
    recursive_enumeration=False):
135 f8681ec8 Stavros Sachtouris
    """
136 f8681ec8 Stavros Sachtouris
    Pretty-print a list object
137 f8681ec8 Stavros Sachtouris

138 f8681ec8 Stavros Sachtouris
    :param l: (list) the input
139 f8681ec8 Stavros Sachtouris

140 f8681ec8 Stavros Sachtouris
    :param excelude: (object - anytype) values to exclude from printing
141 f8681ec8 Stavros Sachtouris

142 f8681ec8 Stavros Sachtouris
    :param ident: (int) initial indentation (recursive)
143 f8681ec8 Stavros Sachtouris

144 f8681ec8 Stavros Sachtouris
    :param with_enumeration: (bool) enumerate each 1st level value if true
145 f8681ec8 Stavros Sachtouris

146 f8681ec8 Stavros Sachtouris
    :recursive_enumeration: (bool) recursively enumerate dicts and lists of
147 f8681ec8 Stavros Sachtouris
        2nd level or deeper
148 f8681ec8 Stavros Sachtouris

149 f8681ec8 Stavros Sachtouris
    :raises CLIError: (TypeError wrapper) non-list input
150 f8681ec8 Stavros Sachtouris
    """
151 7493ccb6 Stavros Sachtouris
    if not isinstance(l, list):
152 2ff0b7bd Stavros Sachtouris
        raiseCLIError(TypeError('Cannot list_print a non-list object'))
153 f551841a Stavros Sachtouris
154 db950b10 Stavros Sachtouris
    if l:
155 f91bc6b1 Stavros Sachtouris
        try:
156 f91bc6b1 Stavros Sachtouris
            margin = max(len(unicode(item).strip()) for item in l\
157 f91bc6b1 Stavros Sachtouris
                if not (isinstance(item, dict)\
158 f91bc6b1 Stavros Sachtouris
                or isinstance(item, list)\
159 f91bc6b1 Stavros Sachtouris
                or item in exclude))
160 f91bc6b1 Stavros Sachtouris
        except ValueError:
161 d4abd11c Stavros Sachtouris
            margin = (2 + len(unicode(len(l)))) if enumerate else 1
162 7493ccb6 Stavros Sachtouris
163 d4abd11c Stavros Sachtouris
    counter = 1
164 d4abd11c Stavros Sachtouris
    prefix = ''
165 7493ccb6 Stavros Sachtouris
    for item in sorted(l):
166 7493ccb6 Stavros Sachtouris
        if item in exclude:
167 7493ccb6 Stavros Sachtouris
            continue
168 f8681ec8 Stavros Sachtouris
        elif with_enumeration:
169 d4abd11c Stavros Sachtouris
            prefix = '%s. ' % counter
170 d4abd11c Stavros Sachtouris
            counter += 1
171 d4abd11c Stavros Sachtouris
            prefix = '%s%s' % (' ' * (ident - len(prefix)), prefix)
172 d4abd11c Stavros Sachtouris
        else:
173 d4abd11c Stavros Sachtouris
            prefix = ' ' * ident
174 7493ccb6 Stavros Sachtouris
        if isinstance(item, dict):
175 c17b8bc0 Stavros Sachtouris
            if with_enumeration:
176 c17b8bc0 Stavros Sachtouris
                print(prefix)
177 f8681ec8 Stavros Sachtouris
            print_dict(item,
178 f8681ec8 Stavros Sachtouris
                exclude=exclude,
179 f8681ec8 Stavros Sachtouris
                ident=margin + ident,
180 f8681ec8 Stavros Sachtouris
                with_enumeration=recursive_enumeration,
181 f8681ec8 Stavros Sachtouris
                recursive_enumeration=recursive_enumeration)
182 7493ccb6 Stavros Sachtouris
        elif isinstance(item, list):
183 c17b8bc0 Stavros Sachtouris
            if with_enumeration:
184 c17b8bc0 Stavros Sachtouris
                print(prefix)
185 f8681ec8 Stavros Sachtouris
            print_list(item,
186 f8681ec8 Stavros Sachtouris
                exclude=exclude,
187 f8681ec8 Stavros Sachtouris
                ident=margin + ident,
188 f8681ec8 Stavros Sachtouris
                with_enumeration=recursive_enumeration,
189 f8681ec8 Stavros Sachtouris
                recursive_enumeration=recursive_enumeration)
190 7493ccb6 Stavros Sachtouris
        else:
191 d4abd11c Stavros Sachtouris
            print('%s%s' % (prefix, item))
192 7493ccb6 Stavros Sachtouris
193 fd5db045 Stavros Sachtouris
194 a494a741 Stavros Sachtouris
def print_items(items,
195 a494a741 Stavros Sachtouris
    title=('id', 'name'),
196 a494a741 Stavros Sachtouris
    with_enumeration=False,
197 bd40efdf Stavros Sachtouris
    with_redundancy=False,
198 bd40efdf Stavros Sachtouris
    page_size=0):
199 a494a741 Stavros Sachtouris
    """print dict or list items in a list, using some values as title
200 a494a741 Stavros Sachtouris
    Objects of next level don't inherit enumeration (default: off) or titles
201 a494a741 Stavros Sachtouris

202 a494a741 Stavros Sachtouris
    :param items: (list) items are lists or dict
203 a494a741 Stavros Sachtouris
    :param title: (tuple) keys to use their values as title
204 a494a741 Stavros Sachtouris
    :param with_enumeration: (boolean) enumerate items (order id on title)
205 a494a741 Stavros Sachtouris
    :param with_redundancy: (boolean) values in title also appear on body
206 bd40efdf Stavros Sachtouris
    :param page_size: (int) show results in pages of page_size items, enter to
207 bd40efdf Stavros Sachtouris
        continue
208 a494a741 Stavros Sachtouris
    """
209 bd40efdf Stavros Sachtouris
    try:
210 bd40efdf Stavros Sachtouris
        page_size = int(page_size) if int(page_size) > 0 else len(items)
211 bd40efdf Stavros Sachtouris
    except:
212 bd40efdf Stavros Sachtouris
        page_size = len(items)
213 bd40efdf Stavros Sachtouris
    num_of_pages = len(items) // page_size
214 bd40efdf Stavros Sachtouris
    num_of_pages += 1 if len(items) % page_size else 0
215 54d800e8 Stavros Sachtouris
    for i, item in enumerate(items):
216 a494a741 Stavros Sachtouris
        if with_enumeration:
217 a494a741 Stavros Sachtouris
            stdout.write('%s. ' % (i + 1))
218 a494a741 Stavros Sachtouris
        if isinstance(item, dict):
219 a494a741 Stavros Sachtouris
            title = sorted(set(title).intersection(item.keys()))
220 a494a741 Stavros Sachtouris
            if with_redundancy:
221 a494a741 Stavros Sachtouris
                header = ' '.join(unicode(item[key]) for key in title)
222 a494a741 Stavros Sachtouris
            else:
223 a494a741 Stavros Sachtouris
                header = ' '.join(unicode(item.pop(key)) for key in title)
224 aa25346e Stavros Sachtouris
            print(bold(header))
225 a494a741 Stavros Sachtouris
        else:
226 a494a741 Stavros Sachtouris
            print('- - -')
227 7493ccb6 Stavros Sachtouris
        if isinstance(item, dict):
228 08c63ef5 Stavros Sachtouris
            print_dict(item, ident=1)
229 aa25346e Stavros Sachtouris
        elif isinstance(item, list):
230 08c63ef5 Stavros Sachtouris
            print_list(item, ident=1)
231 a494a741 Stavros Sachtouris
        else:
232 a494a741 Stavros Sachtouris
            print(' %s' % item)
233 bd40efdf Stavros Sachtouris
        if num_of_pages and len(items) > (i + 1) and 0 == (i + 1) % page_size:
234 bd40efdf Stavros Sachtouris
            num_of_pages -= 1
235 bd40efdf Stavros Sachtouris
            print('(%s listed - %s more - "enter" to continue)' % (
236 bd40efdf Stavros Sachtouris
                i + 1,
237 bd40efdf Stavros Sachtouris
                len(items) - (i + 1)))
238 bd40efdf Stavros Sachtouris
            stdin.read(1)
239 7493ccb6 Stavros Sachtouris
240 fd5db045 Stavros Sachtouris
241 7493ccb6 Stavros Sachtouris
def format_size(size):
242 7493ccb6 Stavros Sachtouris
    units = ('B', 'K', 'M', 'G', 'T')
243 7493ccb6 Stavros Sachtouris
    try:
244 7493ccb6 Stavros Sachtouris
        size = float(size)
245 2ff0b7bd Stavros Sachtouris
    except ValueError as err:
246 2ff0b7bd Stavros Sachtouris
        raiseCLIError(err, 'Cannot format %s in bytes' % size)
247 7493ccb6 Stavros Sachtouris
    for unit in units:
248 7493ccb6 Stavros Sachtouris
        if size < 1024:
249 7493ccb6 Stavros Sachtouris
            break
250 7493ccb6 Stavros Sachtouris
        size /= 1024
251 7493ccb6 Stavros Sachtouris
    s = ('%.1f' % size)
252 7493ccb6 Stavros Sachtouris
    if '.0' == s[-2:]:
253 7493ccb6 Stavros Sachtouris
        s = s[:-2]
254 7493ccb6 Stavros Sachtouris
    return s + unit
255 7493ccb6 Stavros Sachtouris
256 fd5db045 Stavros Sachtouris
257 fd5db045 Stavros Sachtouris
def dict2file(d, f, depth=0):
258 7493ccb6 Stavros Sachtouris
    for k, v in d.items():
259 fd5db045 Stavros Sachtouris
        f.write('%s%s: ' % ('\t' * depth, k))
260 fd5db045 Stavros Sachtouris
        if isinstance(v, dict):
261 7493ccb6 Stavros Sachtouris
            f.write('\n')
262 fd5db045 Stavros Sachtouris
            dict2file(v, f, depth + 1)
263 fd5db045 Stavros Sachtouris
        elif isinstance(v, list):
264 7493ccb6 Stavros Sachtouris
            f.write('\n')
265 fd5db045 Stavros Sachtouris
            list2file(v, f, depth + 1)
266 7493ccb6 Stavros Sachtouris
        else:
267 fd5db045 Stavros Sachtouris
            f.write(' %s\n' % unicode(v))
268 fd5db045 Stavros Sachtouris
269 7493ccb6 Stavros Sachtouris
270 fd5db045 Stavros Sachtouris
def list2file(l, f, depth=1):
271 7493ccb6 Stavros Sachtouris
    for item in l:
272 fd5db045 Stavros Sachtouris
        if isinstance(item, dict):
273 fd5db045 Stavros Sachtouris
            dict2file(item, f, depth + 1)
274 fd5db045 Stavros Sachtouris
        elif isinstance(item, list):
275 fd5db045 Stavros Sachtouris
            list2file(item, f, depth + 1)
276 7493ccb6 Stavros Sachtouris
        else:
277 fd5db045 Stavros Sachtouris
            f.write('%s%s\n' % ('\t' * depth, unicode(item)))
278 efbcdc41 Stavros Sachtouris
279 efbcdc41 Stavros Sachtouris
# Split input auxiliary
280 efbcdc41 Stavros Sachtouris
281 efbcdc41 Stavros Sachtouris
282 efbcdc41 Stavros Sachtouris
def _parse_with_regex(line, regex):
283 efbcdc41 Stavros Sachtouris
    re_parser = regex_compile(regex)
284 efbcdc41 Stavros Sachtouris
    return (re_parser.split(line), re_parser.findall(line))
285 efbcdc41 Stavros Sachtouris
286 efbcdc41 Stavros Sachtouris
287 efbcdc41 Stavros Sachtouris
def _sub_split(line):
288 efbcdc41 Stavros Sachtouris
    terms = []
289 efbcdc41 Stavros Sachtouris
    (sub_trivials, sub_interesting) = _parse_with_regex(line, ' ".*?" ')
290 efbcdc41 Stavros Sachtouris
    for subi, subipart in enumerate(sub_interesting):
291 efbcdc41 Stavros Sachtouris
        terms += sub_trivials[subi].split()
292 efbcdc41 Stavros Sachtouris
        terms.append(subipart[2:-2])
293 efbcdc41 Stavros Sachtouris
    terms += sub_trivials[-1].split()
294 efbcdc41 Stavros Sachtouris
    return terms
295 efbcdc41 Stavros Sachtouris
296 efbcdc41 Stavros Sachtouris
297 efbcdc41 Stavros Sachtouris
def split_input(line):
298 efbcdc41 Stavros Sachtouris
    """Use regular expressions to split a line correctly
299 efbcdc41 Stavros Sachtouris
    """
300 efbcdc41 Stavros Sachtouris
    line = ' %s ' % line
301 efbcdc41 Stavros Sachtouris
    (trivial_parts, interesting_parts) = _parse_with_regex(line, ' \'.*?\' ')
302 efbcdc41 Stavros Sachtouris
    terms = []
303 efbcdc41 Stavros Sachtouris
    for i, ipart in enumerate(interesting_parts):
304 efbcdc41 Stavros Sachtouris
        terms += _sub_split(trivial_parts[i])
305 efbcdc41 Stavros Sachtouris
        terms.append(ipart[2:-2])
306 efbcdc41 Stavros Sachtouris
    terms += _sub_split(trivial_parts[-1])
307 efbcdc41 Stavros Sachtouris
    return terms