Statistics
| Branch: | Tag: | Revision:

root / kamaki / cli / utils.py @ 362adf50

History | View | Annotate | Download (14.9 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 02846a75 Stavros Sachtouris
from time import sleep
37 14b25e00 Stavros Sachtouris
from os import walk, path
38 0399ac7e Stavros Sachtouris
from json import dumps
39 02846a75 Stavros Sachtouris
40 2ff0b7bd Stavros Sachtouris
from kamaki.cli.errors import raiseCLIError
41 3dabe5d2 Stavros Sachtouris
42 362adf50 Stavros Sachtouris
suggest = dict(ansicolors=dict(
43 6fb4af77 Stavros Sachtouris
        active=False,
44 6fb4af77 Stavros Sachtouris
        url='#install-ansicolors-progress',
45 362adf50 Stavros Sachtouris
        description='Add colors to console responses'))
46 6fb4af77 Stavros Sachtouris
47 dfee2caf Stavros Sachtouris
try:
48 dfee2caf Stavros Sachtouris
    from colors import magenta, red, yellow, bold
49 dfee2caf Stavros Sachtouris
except ImportError:
50 3dabe5d2 Stavros Sachtouris
    # No colours? No worries, use dummy foo instead
51 f93854ae Stavros Sachtouris
    def dummy(val):
52 dfee2caf Stavros Sachtouris
        return val
53 f93854ae Stavros Sachtouris
    red = yellow = magenta = bold = dummy
54 6fb4af77 Stavros Sachtouris
    suggest['ansicolors']['active'] = True
55 6fb4af77 Stavros Sachtouris
56 6fb4af77 Stavros Sachtouris
try:
57 6fb4af77 Stavros Sachtouris
    from progress.bar import ShadyBar
58 6fb4af77 Stavros Sachtouris
except ImportError:
59 6fb4af77 Stavros Sachtouris
    suggest['progress']['active'] = True
60 6fb4af77 Stavros Sachtouris
61 6fb4af77 Stavros Sachtouris
62 6fb4af77 Stavros Sachtouris
def suggest_missing(miss=None):
63 6fb4af77 Stavros Sachtouris
    global suggest
64 6fb4af77 Stavros Sachtouris
    kamaki_docs = 'http://www.synnefo.org/docs/kamaki/latest'
65 6fb4af77 Stavros Sachtouris
    for k, v in (miss, suggest[miss]) if miss else suggest.items():
66 6fb4af77 Stavros Sachtouris
        if v['active'] and stdout.isatty():
67 6fb4af77 Stavros Sachtouris
            print('Suggestion: for better user experience install %s' % k)
68 6fb4af77 Stavros Sachtouris
            print('\t%s' % v['description'])
69 6fb4af77 Stavros Sachtouris
            print('\tIt is easy, here are the instructions:')
70 6fb4af77 Stavros Sachtouris
            print('\t%s/installation.html%s' % (kamaki_docs, v['url']))
71 6fb4af77 Stavros Sachtouris
            print('')
72 f997679d Stavros Sachtouris
73 fd5db045 Stavros Sachtouris
74 67cea04c Stavros Sachtouris
def remove_colors():
75 67cea04c Stavros Sachtouris
    global bold
76 3dabe5d2 Stavros Sachtouris
    global red
77 3dabe5d2 Stavros Sachtouris
    global yellow
78 3dabe5d2 Stavros Sachtouris
    global magenta
79 fd5db045 Stavros Sachtouris
80 67cea04c Stavros Sachtouris
    def dummy(val):
81 67cea04c Stavros Sachtouris
        return val
82 3dabe5d2 Stavros Sachtouris
    red = yellow = magenta = bold = dummy
83 7493ccb6 Stavros Sachtouris
84 fd5db045 Stavros Sachtouris
85 7493ccb6 Stavros Sachtouris
def pretty_keys(d, delim='_', recurcive=False):
86 f23a5cdb Stavros Sachtouris
    """<term>delim<term> to <term> <term> transformation
87 7493ccb6 Stavros Sachtouris
    """
88 7493ccb6 Stavros Sachtouris
    new_d = {}
89 7493ccb6 Stavros Sachtouris
    for key, val in d.items():
90 7493ccb6 Stavros Sachtouris
        new_key = key.split(delim)[-1]
91 7493ccb6 Stavros Sachtouris
        if recurcive and isinstance(val, dict):
92 fd5db045 Stavros Sachtouris
            new_val = pretty_keys(val, delim, recurcive)
93 7493ccb6 Stavros Sachtouris
        else:
94 7493ccb6 Stavros Sachtouris
            new_val = val
95 7493ccb6 Stavros Sachtouris
        new_d[new_key] = new_val
96 7493ccb6 Stavros Sachtouris
    return new_d
97 7493ccb6 Stavros Sachtouris
98 fd5db045 Stavros Sachtouris
99 0399ac7e Stavros Sachtouris
def print_json(data):
100 0399ac7e Stavros Sachtouris
    """Print a list or dict as json in console
101 0399ac7e Stavros Sachtouris

102 0399ac7e Stavros Sachtouris
    :param data: json-dumpable data
103 0399ac7e Stavros Sachtouris
    """
104 0399ac7e Stavros Sachtouris
    print(dumps(data, indent=2))
105 0399ac7e Stavros Sachtouris
106 0399ac7e Stavros Sachtouris
107 545c6c29 Stavros Sachtouris
def pretty_dict(d, *args, **kwargs):
108 545c6c29 Stavros Sachtouris
    print_dict(pretty_keys(d, *args, **kwargs))
109 545c6c29 Stavros Sachtouris
110 545c6c29 Stavros Sachtouris
111 de73876b Stavros Sachtouris
def print_dict(
112 24ff0a35 Stavros Sachtouris
        d, exclude=(), ident=0,
113 24ff0a35 Stavros Sachtouris
        with_enumeration=False, recursive_enumeration=False):
114 f8681ec8 Stavros Sachtouris
    """
115 f8681ec8 Stavros Sachtouris
    Pretty-print a dictionary object
116 f8681ec8 Stavros Sachtouris

117 f8681ec8 Stavros Sachtouris
    :param d: (dict) the input
118 f8681ec8 Stavros Sachtouris

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

121 f8681ec8 Stavros Sachtouris
    :param ident: (int) initial indentation (recursive)
122 f8681ec8 Stavros Sachtouris

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

125 f8681ec8 Stavros Sachtouris
    :recursive_enumeration: (bool) recursively enumerate dicts and lists of
126 f8681ec8 Stavros Sachtouris
        2nd level or deeper
127 f8681ec8 Stavros Sachtouris

128 f8681ec8 Stavros Sachtouris
    :raises CLIError: (TypeError wrapper) non-dict input
129 f8681ec8 Stavros Sachtouris
    """
130 7493ccb6 Stavros Sachtouris
    if not isinstance(d, dict):
131 2ff0b7bd Stavros Sachtouris
        raiseCLIError(TypeError('Cannot dict_print a non-dict object'))
132 f551841a Stavros Sachtouris
133 db950b10 Stavros Sachtouris
    if d:
134 24ff0a35 Stavros Sachtouris
        margin = max(len(('%s' % key).strip()) for key in d.keys() if (
135 24ff0a35 Stavros Sachtouris
            key not in exclude))
136 7493ccb6 Stavros Sachtouris
137 f8681ec8 Stavros Sachtouris
    counter = 1
138 7493ccb6 Stavros Sachtouris
    for key, val in sorted(d.items()):
139 a517ff50 Stavros Sachtouris
        key = '%s' % key
140 7493ccb6 Stavros Sachtouris
        if key in exclude:
141 7493ccb6 Stavros Sachtouris
            continue
142 f8681ec8 Stavros Sachtouris
        print_str = ''
143 f8681ec8 Stavros Sachtouris
        if with_enumeration:
144 f8681ec8 Stavros Sachtouris
            print_str = '%s. ' % counter
145 f8681ec8 Stavros Sachtouris
            counter += 1
146 f8681ec8 Stavros Sachtouris
        print_str = '%s%s' % (' ' * (ident - len(print_str)), print_str)
147 a517ff50 Stavros Sachtouris
        print_str += key.strip()
148 a517ff50 Stavros Sachtouris
        print_str += ' ' * (margin - len(key.strip()))
149 f551841a Stavros Sachtouris
        print_str += ': '
150 7493ccb6 Stavros Sachtouris
        if isinstance(val, dict):
151 f551841a Stavros Sachtouris
            print(print_str)
152 de73876b Stavros Sachtouris
            print_dict(
153 de73876b Stavros Sachtouris
                val,
154 f8681ec8 Stavros Sachtouris
                exclude=exclude,
155 f8681ec8 Stavros Sachtouris
                ident=margin + ident,
156 f8681ec8 Stavros Sachtouris
                with_enumeration=recursive_enumeration,
157 f8681ec8 Stavros Sachtouris
                recursive_enumeration=recursive_enumeration)
158 7493ccb6 Stavros Sachtouris
        elif isinstance(val, list):
159 f551841a Stavros Sachtouris
            print(print_str)
160 de73876b Stavros Sachtouris
            print_list(
161 de73876b Stavros Sachtouris
                val,
162 f8681ec8 Stavros Sachtouris
                exclude=exclude,
163 f8681ec8 Stavros Sachtouris
                ident=margin + ident,
164 f8681ec8 Stavros Sachtouris
                with_enumeration=recursive_enumeration,
165 f8681ec8 Stavros Sachtouris
                recursive_enumeration=recursive_enumeration)
166 7493ccb6 Stavros Sachtouris
        else:
167 a517ff50 Stavros Sachtouris
            print print_str + ' ' + ('%s' % val).strip()
168 fd5db045 Stavros Sachtouris
169 7493ccb6 Stavros Sachtouris
170 de73876b Stavros Sachtouris
def print_list(
171 24ff0a35 Stavros Sachtouris
        l, exclude=(), ident=0,
172 24ff0a35 Stavros Sachtouris
        with_enumeration=False, recursive_enumeration=False):
173 f8681ec8 Stavros Sachtouris
    """
174 f8681ec8 Stavros Sachtouris
    Pretty-print a list object
175 f8681ec8 Stavros Sachtouris

176 f8681ec8 Stavros Sachtouris
    :param l: (list) the input
177 f8681ec8 Stavros Sachtouris

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

180 f8681ec8 Stavros Sachtouris
    :param ident: (int) initial indentation (recursive)
181 f8681ec8 Stavros Sachtouris

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

184 f8681ec8 Stavros Sachtouris
    :recursive_enumeration: (bool) recursively enumerate dicts and lists of
185 f8681ec8 Stavros Sachtouris
        2nd level or deeper
186 f8681ec8 Stavros Sachtouris

187 f8681ec8 Stavros Sachtouris
    :raises CLIError: (TypeError wrapper) non-list input
188 f8681ec8 Stavros Sachtouris
    """
189 7493ccb6 Stavros Sachtouris
    if not isinstance(l, list):
190 2ff0b7bd Stavros Sachtouris
        raiseCLIError(TypeError('Cannot list_print a non-list object'))
191 f551841a Stavros Sachtouris
192 db950b10 Stavros Sachtouris
    if l:
193 f91bc6b1 Stavros Sachtouris
        try:
194 24ff0a35 Stavros Sachtouris
            margin = max(len(('%s' % item).strip()) for item in l if not (
195 24ff0a35 Stavros Sachtouris
                isinstance(item, dict) or
196 24ff0a35 Stavros Sachtouris
                isinstance(item, list) or
197 24ff0a35 Stavros Sachtouris
                item in exclude))
198 f91bc6b1 Stavros Sachtouris
        except ValueError:
199 a517ff50 Stavros Sachtouris
            margin = (2 + len(('%s' % len(l)))) if enumerate else 1
200 7493ccb6 Stavros Sachtouris
201 d4abd11c Stavros Sachtouris
    counter = 1
202 d4abd11c Stavros Sachtouris
    prefix = ''
203 7493ccb6 Stavros Sachtouris
    for item in sorted(l):
204 7493ccb6 Stavros Sachtouris
        if item in exclude:
205 7493ccb6 Stavros Sachtouris
            continue
206 f8681ec8 Stavros Sachtouris
        elif with_enumeration:
207 d4abd11c Stavros Sachtouris
            prefix = '%s. ' % counter
208 d4abd11c Stavros Sachtouris
            counter += 1
209 d4abd11c Stavros Sachtouris
            prefix = '%s%s' % (' ' * (ident - len(prefix)), prefix)
210 d4abd11c Stavros Sachtouris
        else:
211 d4abd11c Stavros Sachtouris
            prefix = ' ' * ident
212 7493ccb6 Stavros Sachtouris
        if isinstance(item, dict):
213 c17b8bc0 Stavros Sachtouris
            if with_enumeration:
214 c17b8bc0 Stavros Sachtouris
                print(prefix)
215 de73876b Stavros Sachtouris
            print_dict(
216 de73876b Stavros Sachtouris
                item,
217 f8681ec8 Stavros Sachtouris
                exclude=exclude,
218 f8681ec8 Stavros Sachtouris
                ident=margin + ident,
219 f8681ec8 Stavros Sachtouris
                with_enumeration=recursive_enumeration,
220 f8681ec8 Stavros Sachtouris
                recursive_enumeration=recursive_enumeration)
221 7493ccb6 Stavros Sachtouris
        elif isinstance(item, list):
222 c17b8bc0 Stavros Sachtouris
            if with_enumeration:
223 c17b8bc0 Stavros Sachtouris
                print(prefix)
224 de73876b Stavros Sachtouris
            print_list(
225 de73876b Stavros Sachtouris
                item,
226 f8681ec8 Stavros Sachtouris
                exclude=exclude,
227 f8681ec8 Stavros Sachtouris
                ident=margin + ident,
228 f8681ec8 Stavros Sachtouris
                with_enumeration=recursive_enumeration,
229 f8681ec8 Stavros Sachtouris
                recursive_enumeration=recursive_enumeration)
230 7493ccb6 Stavros Sachtouris
        else:
231 d4abd11c Stavros Sachtouris
            print('%s%s' % (prefix, item))
232 7493ccb6 Stavros Sachtouris
233 fd5db045 Stavros Sachtouris
234 439826ec Stavros Sachtouris
def page_hold(index, limit, maxlen):
235 439826ec Stavros Sachtouris
    """Check if there are results to show, and hold the page when needed
236 439826ec Stavros Sachtouris
    :param index: (int) > 0
237 439826ec Stavros Sachtouris
    :param limit: (int) 0 < limit <= max, page hold if limit mod index == 0
238 439826ec Stavros Sachtouris
    :param maxlen: (int) Don't hold if index reaches maxlen
239 439826ec Stavros Sachtouris

240 439826ec Stavros Sachtouris
    :returns: True if there are more to show, False if all results are shown
241 439826ec Stavros Sachtouris
    """
242 439826ec Stavros Sachtouris
    if index >= limit and index % limit == 0:
243 439826ec Stavros Sachtouris
        if index >= maxlen:
244 439826ec Stavros Sachtouris
            return False
245 439826ec Stavros Sachtouris
        else:
246 439826ec Stavros Sachtouris
            print('(%s listed - %s more - "enter" to continue)' % (
247 439826ec Stavros Sachtouris
                index,
248 439826ec Stavros Sachtouris
                maxlen - index))
249 439826ec Stavros Sachtouris
            c = ' '
250 439826ec Stavros Sachtouris
            while c != '\n':
251 439826ec Stavros Sachtouris
                c = stdin.read(1)
252 439826ec Stavros Sachtouris
    return True
253 439826ec Stavros Sachtouris
254 439826ec Stavros Sachtouris
255 de73876b Stavros Sachtouris
def print_items(
256 24ff0a35 Stavros Sachtouris
        items, title=('id', 'name'),
257 24ff0a35 Stavros Sachtouris
        with_enumeration=False, with_redundancy=False,
258 24ff0a35 Stavros Sachtouris
        page_size=0):
259 a494a741 Stavros Sachtouris
    """print dict or list items in a list, using some values as title
260 a494a741 Stavros Sachtouris
    Objects of next level don't inherit enumeration (default: off) or titles
261 a494a741 Stavros Sachtouris

262 a494a741 Stavros Sachtouris
    :param items: (list) items are lists or dict
263 a494a741 Stavros Sachtouris
    :param title: (tuple) keys to use their values as title
264 a494a741 Stavros Sachtouris
    :param with_enumeration: (boolean) enumerate items (order id on title)
265 a494a741 Stavros Sachtouris
    :param with_redundancy: (boolean) values in title also appear on body
266 bd40efdf Stavros Sachtouris
    :param page_size: (int) show results in pages of page_size items, enter to
267 bd40efdf Stavros Sachtouris
        continue
268 a494a741 Stavros Sachtouris
    """
269 0e806947 Stavros Sachtouris
    if not items:
270 0e806947 Stavros Sachtouris
        return
271 bd40efdf Stavros Sachtouris
    try:
272 bd40efdf Stavros Sachtouris
        page_size = int(page_size) if int(page_size) > 0 else len(items)
273 bd40efdf Stavros Sachtouris
    except:
274 bd40efdf Stavros Sachtouris
        page_size = len(items)
275 bd40efdf Stavros Sachtouris
    num_of_pages = len(items) // page_size
276 bd40efdf Stavros Sachtouris
    num_of_pages += 1 if len(items) % page_size else 0
277 54d800e8 Stavros Sachtouris
    for i, item in enumerate(items):
278 a494a741 Stavros Sachtouris
        if with_enumeration:
279 a494a741 Stavros Sachtouris
            stdout.write('%s. ' % (i + 1))
280 a494a741 Stavros Sachtouris
        if isinstance(item, dict):
281 a494a741 Stavros Sachtouris
            title = sorted(set(title).intersection(item.keys()))
282 a494a741 Stavros Sachtouris
            if with_redundancy:
283 a517ff50 Stavros Sachtouris
                header = ' '.join('%s' % item[key] for key in title)
284 a494a741 Stavros Sachtouris
            else:
285 a517ff50 Stavros Sachtouris
                header = ' '.join('%s' % item.pop(key) for key in title)
286 aa25346e Stavros Sachtouris
            print(bold(header))
287 7493ccb6 Stavros Sachtouris
        if isinstance(item, dict):
288 08c63ef5 Stavros Sachtouris
            print_dict(item, ident=1)
289 aa25346e Stavros Sachtouris
        elif isinstance(item, list):
290 08c63ef5 Stavros Sachtouris
            print_list(item, ident=1)
291 a494a741 Stavros Sachtouris
        else:
292 a494a741 Stavros Sachtouris
            print(' %s' % item)
293 439826ec Stavros Sachtouris
        page_hold(i + 1, page_size, len(items))
294 7493ccb6 Stavros Sachtouris
295 fd5db045 Stavros Sachtouris
296 7493ccb6 Stavros Sachtouris
def format_size(size):
297 001200c3 Stavros Sachtouris
    units = ('B', 'KiB', 'MiB', 'GiB', 'TiB')
298 7493ccb6 Stavros Sachtouris
    try:
299 7493ccb6 Stavros Sachtouris
        size = float(size)
300 2ff0b7bd Stavros Sachtouris
    except ValueError as err:
301 2ff0b7bd Stavros Sachtouris
        raiseCLIError(err, 'Cannot format %s in bytes' % size)
302 7493ccb6 Stavros Sachtouris
    for unit in units:
303 7493ccb6 Stavros Sachtouris
        if size < 1024:
304 7493ccb6 Stavros Sachtouris
            break
305 001200c3 Stavros Sachtouris
        size /= 1024.0
306 001200c3 Stavros Sachtouris
    s = ('%.2f' % size)
307 001200c3 Stavros Sachtouris
    while '.' in s and s[-1] in ('0', '.'):
308 001200c3 Stavros Sachtouris
        s = s[:-1]
309 7493ccb6 Stavros Sachtouris
    return s + unit
310 7493ccb6 Stavros Sachtouris
311 fd5db045 Stavros Sachtouris
312 001200c3 Stavros Sachtouris
def to_bytes(size, format):
313 001200c3 Stavros Sachtouris
    """
314 001200c3 Stavros Sachtouris
    :param size: (float) the size in the given format
315 001200c3 Stavros Sachtouris
    :param format: (case insensitive) KiB, KB, MiB, MB, GiB, GB, TiB, TB
316 001200c3 Stavros Sachtouris

317 001200c3 Stavros Sachtouris
    :returns: (int) the size in bytes
318 001200c3 Stavros Sachtouris
    """
319 001200c3 Stavros Sachtouris
    format = format.upper()
320 001200c3 Stavros Sachtouris
    if format == 'B':
321 001200c3 Stavros Sachtouris
        return int(size)
322 001200c3 Stavros Sachtouris
    size = float(size)
323 001200c3 Stavros Sachtouris
    units_dc = ('KB', 'MB', 'GB', 'TB')
324 001200c3 Stavros Sachtouris
    units_bi = ('KIB', 'MIB', 'GIB', 'TIB')
325 001200c3 Stavros Sachtouris
326 001200c3 Stavros Sachtouris
    factor = 1024 if format in units_bi else 1000 if format in units_dc else 0
327 001200c3 Stavros Sachtouris
    if not factor:
328 001200c3 Stavros Sachtouris
        raise ValueError('Invalid data size format %s' % format)
329 001200c3 Stavros Sachtouris
    for prefix in ('K', 'M', 'G', 'T'):
330 001200c3 Stavros Sachtouris
        size *= factor
331 001200c3 Stavros Sachtouris
        if format.startswith(prefix):
332 001200c3 Stavros Sachtouris
            break
333 001200c3 Stavros Sachtouris
    return int(size)
334 001200c3 Stavros Sachtouris
335 001200c3 Stavros Sachtouris
336 fd5db045 Stavros Sachtouris
def dict2file(d, f, depth=0):
337 7493ccb6 Stavros Sachtouris
    for k, v in d.items():
338 fd5db045 Stavros Sachtouris
        f.write('%s%s: ' % ('\t' * depth, k))
339 fd5db045 Stavros Sachtouris
        if isinstance(v, dict):
340 7493ccb6 Stavros Sachtouris
            f.write('\n')
341 fd5db045 Stavros Sachtouris
            dict2file(v, f, depth + 1)
342 fd5db045 Stavros Sachtouris
        elif isinstance(v, list):
343 7493ccb6 Stavros Sachtouris
            f.write('\n')
344 fd5db045 Stavros Sachtouris
            list2file(v, f, depth + 1)
345 7493ccb6 Stavros Sachtouris
        else:
346 a517ff50 Stavros Sachtouris
            f.write(' %s\n' % v)
347 fd5db045 Stavros Sachtouris
348 7493ccb6 Stavros Sachtouris
349 fd5db045 Stavros Sachtouris
def list2file(l, f, depth=1):
350 7493ccb6 Stavros Sachtouris
    for item in l:
351 fd5db045 Stavros Sachtouris
        if isinstance(item, dict):
352 fd5db045 Stavros Sachtouris
            dict2file(item, f, depth + 1)
353 fd5db045 Stavros Sachtouris
        elif isinstance(item, list):
354 fd5db045 Stavros Sachtouris
            list2file(item, f, depth + 1)
355 7493ccb6 Stavros Sachtouris
        else:
356 a517ff50 Stavros Sachtouris
            f.write('%s%s\n' % ('\t' * depth, item))
357 efbcdc41 Stavros Sachtouris
358 efbcdc41 Stavros Sachtouris
# Split input auxiliary
359 efbcdc41 Stavros Sachtouris
360 efbcdc41 Stavros Sachtouris
361 efbcdc41 Stavros Sachtouris
def _parse_with_regex(line, regex):
362 efbcdc41 Stavros Sachtouris
    re_parser = regex_compile(regex)
363 efbcdc41 Stavros Sachtouris
    return (re_parser.split(line), re_parser.findall(line))
364 efbcdc41 Stavros Sachtouris
365 efbcdc41 Stavros Sachtouris
366 efbcdc41 Stavros Sachtouris
def _sub_split(line):
367 efbcdc41 Stavros Sachtouris
    terms = []
368 efbcdc41 Stavros Sachtouris
    (sub_trivials, sub_interesting) = _parse_with_regex(line, ' ".*?" ')
369 efbcdc41 Stavros Sachtouris
    for subi, subipart in enumerate(sub_interesting):
370 efbcdc41 Stavros Sachtouris
        terms += sub_trivials[subi].split()
371 efbcdc41 Stavros Sachtouris
        terms.append(subipart[2:-2])
372 efbcdc41 Stavros Sachtouris
    terms += sub_trivials[-1].split()
373 efbcdc41 Stavros Sachtouris
    return terms
374 efbcdc41 Stavros Sachtouris
375 efbcdc41 Stavros Sachtouris
376 0ba7b031 Stavros Sachtouris
def old_split_input(line):
377 0ba7b031 Stavros Sachtouris
    """Use regular expressions to split a line correctly"""
378 efbcdc41 Stavros Sachtouris
    line = ' %s ' % line
379 efbcdc41 Stavros Sachtouris
    (trivial_parts, interesting_parts) = _parse_with_regex(line, ' \'.*?\' ')
380 efbcdc41 Stavros Sachtouris
    terms = []
381 efbcdc41 Stavros Sachtouris
    for i, ipart in enumerate(interesting_parts):
382 efbcdc41 Stavros Sachtouris
        terms += _sub_split(trivial_parts[i])
383 efbcdc41 Stavros Sachtouris
        terms.append(ipart[2:-2])
384 efbcdc41 Stavros Sachtouris
    terms += _sub_split(trivial_parts[-1])
385 efbcdc41 Stavros Sachtouris
    return terms
386 7147e1ca Stavros Sachtouris
387 7147e1ca Stavros Sachtouris
388 0ba7b031 Stavros Sachtouris
def _get_from_parsed(parsed_str):
389 0ba7b031 Stavros Sachtouris
    try:
390 0ba7b031 Stavros Sachtouris
        parsed_str = parsed_str.strip()
391 0ba7b031 Stavros Sachtouris
    except:
392 0ba7b031 Stavros Sachtouris
        return None
393 0ba7b031 Stavros Sachtouris
    if parsed_str:
394 0ba7b031 Stavros Sachtouris
        if parsed_str[0] == parsed_str[-1] and parsed_str[0] in ("'", '"'):
395 0ba7b031 Stavros Sachtouris
            return [parsed_str[1:-1]]
396 0ba7b031 Stavros Sachtouris
        return parsed_str.split(' ')
397 0ba7b031 Stavros Sachtouris
    return None
398 0ba7b031 Stavros Sachtouris
399 0ba7b031 Stavros Sachtouris
400 0ba7b031 Stavros Sachtouris
def split_input(line):
401 0ba7b031 Stavros Sachtouris
    if not line:
402 0ba7b031 Stavros Sachtouris
        return []
403 0ba7b031 Stavros Sachtouris
    reg_expr = '\'.*?\'|".*?"|^[\S]*$'
404 0ba7b031 Stavros Sachtouris
    (trivial_parts, interesting_parts) = _parse_with_regex(line, reg_expr)
405 0ba7b031 Stavros Sachtouris
    assert(len(trivial_parts) == 1 + len(interesting_parts))
406 0ba7b031 Stavros Sachtouris
    #print('  [split_input] trivial_parts %s are' % trivial_parts)
407 0ba7b031 Stavros Sachtouris
    #print('  [split_input] interesting_parts %s are' % interesting_parts)
408 0ba7b031 Stavros Sachtouris
    terms = []
409 0ba7b031 Stavros Sachtouris
    for i, tpart in enumerate(trivial_parts):
410 0ba7b031 Stavros Sachtouris
        part = _get_from_parsed(tpart)
411 0ba7b031 Stavros Sachtouris
        if part:
412 0ba7b031 Stavros Sachtouris
            terms += part
413 0ba7b031 Stavros Sachtouris
        try:
414 0ba7b031 Stavros Sachtouris
            part = _get_from_parsed(interesting_parts[i])
415 0ba7b031 Stavros Sachtouris
        except IndexError:
416 0ba7b031 Stavros Sachtouris
            break
417 0ba7b031 Stavros Sachtouris
        if part:
418 0ba7b031 Stavros Sachtouris
            terms += part
419 0ba7b031 Stavros Sachtouris
    return terms
420 0ba7b031 Stavros Sachtouris
421 0ba7b031 Stavros Sachtouris
422 001200c3 Stavros Sachtouris
def ask_user(msg, true_resp=['Y', 'y']):
423 7147e1ca Stavros Sachtouris
    """Print msg and read user response
424 7147e1ca Stavros Sachtouris

425 001200c3 Stavros Sachtouris
    :param true_resp: (tuple of chars)
426 7147e1ca Stavros Sachtouris

427 7147e1ca Stavros Sachtouris
    :returns: (bool) True if reponse in true responses, False otherwise
428 7147e1ca Stavros Sachtouris
    """
429 001200c3 Stavros Sachtouris
    stdout.write('%s (%s or enter for yes):' % (msg, ', '.join(true_resp)))
430 7147e1ca Stavros Sachtouris
    stdout.flush()
431 001200c3 Stavros Sachtouris
    user_response = stdin.readline()
432 001200c3 Stavros Sachtouris
    return user_response[0] in true_resp + ['\n']
433 0ba7b031 Stavros Sachtouris
434 0ba7b031 Stavros Sachtouris
435 02846a75 Stavros Sachtouris
def spiner(size=None):
436 b482315a Stavros Sachtouris
    spins = ('/', '-', '\\', '|')
437 b482315a Stavros Sachtouris
    stdout.write(' ')
438 02846a75 Stavros Sachtouris
    size = size or -1
439 02846a75 Stavros Sachtouris
    i = 0
440 02846a75 Stavros Sachtouris
    while size - i:
441 b482315a Stavros Sachtouris
        stdout.write('\b%s' % spins[i % len(spins)])
442 b482315a Stavros Sachtouris
        stdout.flush()
443 b482315a Stavros Sachtouris
        i += 1
444 02846a75 Stavros Sachtouris
        sleep(0.1)
445 b482315a Stavros Sachtouris
        yield
446 b58c1078 Stavros Sachtouris
    yield
447 b482315a Stavros Sachtouris
448 0ba7b031 Stavros Sachtouris
if __name__ == '__main__':
449 de73876b Stavros Sachtouris
    examples = [
450 de73876b Stavros Sachtouris
        'la_la le_le li_li',
451 0ba7b031 Stavros Sachtouris
        '\'la la\' \'le le\' \'li li\'',
452 0ba7b031 Stavros Sachtouris
        '\'la la\' le_le \'li li\'',
453 0ba7b031 Stavros Sachtouris
        'la_la \'le le\' li_li',
454 0ba7b031 Stavros Sachtouris
        'la_la \'le le\' \'li li\'',
455 0ba7b031 Stavros Sachtouris
        '"la la" "le le" "li li"',
456 0ba7b031 Stavros Sachtouris
        '"la la" le_le "li li"',
457 0ba7b031 Stavros Sachtouris
        'la_la "le le" li_li',
458 0ba7b031 Stavros Sachtouris
        '"la_la" "le le" "li li"',
459 0ba7b031 Stavros Sachtouris
        '\'la la\' "le le" \'li li\'',
460 0ba7b031 Stavros Sachtouris
        'la_la \'le le\' "li li"',
461 0ba7b031 Stavros Sachtouris
        'la_la \'le le\' li_li',
462 0ba7b031 Stavros Sachtouris
        '\'la la\' le_le "li li"',
463 0ba7b031 Stavros Sachtouris
        '"la la" le_le \'li li\'',
464 0ba7b031 Stavros Sachtouris
        '"la la" \'le le\' li_li',
465 0ba7b031 Stavros Sachtouris
        'la_la \'le\'le\' "li\'li"',
466 0ba7b031 Stavros Sachtouris
        '"la \'le le\' la"',
467 0ba7b031 Stavros Sachtouris
        '\'la "le le" la\'',
468 0ba7b031 Stavros Sachtouris
        '\'la "la" la\' "le \'le\' le" li_"li"_li',
469 de73876b Stavros Sachtouris
        '\'\' \'L\' "" "A"']
470 0ba7b031 Stavros Sachtouris
471 0ba7b031 Stavros Sachtouris
    for i, example in enumerate(examples):
472 0ba7b031 Stavros Sachtouris
        print('%s. Split this: (%s)' % (i + 1, example))
473 0ba7b031 Stavros Sachtouris
        ret = old_split_input(example)
474 0ba7b031 Stavros Sachtouris
        print('\t(%s) of size %s' % (ret, len(ret)))
475 14b25e00 Stavros Sachtouris
476 14b25e00 Stavros Sachtouris
477 14b25e00 Stavros Sachtouris
def get_path_size(testpath):
478 14b25e00 Stavros Sachtouris
    if path.isfile(testpath):
479 14b25e00 Stavros Sachtouris
        return path.getsize(testpath)
480 14b25e00 Stavros Sachtouris
    total_size = 0
481 14b25e00 Stavros Sachtouris
    for top, dirs, files in walk(path.abspath(testpath)):
482 14b25e00 Stavros Sachtouris
        for f in files:
483 14b25e00 Stavros Sachtouris
            f = path.join(top, f)
484 14b25e00 Stavros Sachtouris
            if path.isfile(f):
485 14b25e00 Stavros Sachtouris
                total_size += path.getsize(f)
486 14b25e00 Stavros Sachtouris
    return total_size