Statistics
| Branch: | Tag: | Revision:

root / kamaki / cli / utils / __init__.py @ 89ea97e1

History | View | Annotate | Download (15.1 kB)

1 e3f01d64 Stavros Sachtouris
# Copyright 2011-2013 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 1716a15d Stavros Sachtouris
from sys import stdout
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 f55d3a15 Stavros Sachtouris
43 a0608786 Stavros Sachtouris
INDENT_TAB = 4
44 f55d3a15 Stavros Sachtouris
45 f55d3a15 Stavros Sachtouris
46 362adf50 Stavros Sachtouris
suggest = dict(ansicolors=dict(
47 6fb4af77 Stavros Sachtouris
        active=False,
48 6fb4af77 Stavros Sachtouris
        url='#install-ansicolors-progress',
49 362adf50 Stavros Sachtouris
        description='Add colors to console responses'))
50 6fb4af77 Stavros Sachtouris
51 dfee2caf Stavros Sachtouris
try:
52 dfee2caf Stavros Sachtouris
    from colors import magenta, red, yellow, bold
53 dfee2caf Stavros Sachtouris
except ImportError:
54 f93854ae Stavros Sachtouris
    def dummy(val):
55 dfee2caf Stavros Sachtouris
        return val
56 f93854ae Stavros Sachtouris
    red = yellow = magenta = bold = dummy
57 6fb4af77 Stavros Sachtouris
    suggest['ansicolors']['active'] = True
58 6fb4af77 Stavros Sachtouris
59 6fb4af77 Stavros Sachtouris
60 0f383dcc Stavros Sachtouris
def _print(w):
61 0f383dcc Stavros Sachtouris
    """Print wrapper is used to help unittests check what is printed"""
62 0f383dcc Stavros Sachtouris
    print w
63 0f383dcc Stavros Sachtouris
64 0f383dcc Stavros Sachtouris
65 46d130c9 Stavros Sachtouris
def _write(w):
66 46d130c9 Stavros Sachtouris
    """stdout.write wrapper is used to help unittests check what is printed"""
67 46d130c9 Stavros Sachtouris
    stdout.write(w)
68 46d130c9 Stavros Sachtouris
69 46d130c9 Stavros Sachtouris
70 23963422 Stavros Sachtouris
def _flush():
71 23963422 Stavros Sachtouris
    """stdout.flush wrapper is used to help unittests check what is called"""
72 23963422 Stavros Sachtouris
    stdout.flush()
73 23963422 Stavros Sachtouris
74 23963422 Stavros Sachtouris
75 23963422 Stavros Sachtouris
def _readline():
76 89ea97e1 Stavros Sachtouris
    """raw_input wrapper is used to help unittests"""
77 89ea97e1 Stavros Sachtouris
    return raw_input()
78 23963422 Stavros Sachtouris
79 23963422 Stavros Sachtouris
80 69691087 Stavros Sachtouris
def suggest_missing(miss=None, exclude=[]):
81 6fb4af77 Stavros Sachtouris
    global suggest
82 69691087 Stavros Sachtouris
    sgs = dict(suggest)
83 69691087 Stavros Sachtouris
    for exc in exclude:
84 69691087 Stavros Sachtouris
        try:
85 69691087 Stavros Sachtouris
            sgs.pop(exc)
86 69691087 Stavros Sachtouris
        except KeyError:
87 69691087 Stavros Sachtouris
            pass
88 6fb4af77 Stavros Sachtouris
    kamaki_docs = 'http://www.synnefo.org/docs/kamaki/latest'
89 69691087 Stavros Sachtouris
    for k, v in (miss, sgs[miss]) if miss else sgs.items():
90 6fb4af77 Stavros Sachtouris
        if v['active'] and stdout.isatty():
91 6fb4af77 Stavros Sachtouris
            print('Suggestion: for better user experience install %s' % k)
92 6fb4af77 Stavros Sachtouris
            print('\t%s' % v['description'])
93 6fb4af77 Stavros Sachtouris
            print('\tIt is easy, here are the instructions:')
94 6fb4af77 Stavros Sachtouris
            print('\t%s/installation.html%s' % (kamaki_docs, v['url']))
95 6fb4af77 Stavros Sachtouris
            print('')
96 f997679d Stavros Sachtouris
97 fd5db045 Stavros Sachtouris
98 f8426b5c Stavros Sachtouris
def guess_mime_type(
99 f8426b5c Stavros Sachtouris
        filename,
100 f8426b5c Stavros Sachtouris
        default_content_type='application/octet-stream',
101 f8426b5c Stavros Sachtouris
        default_encoding=None):
102 f8426b5c Stavros Sachtouris
    assert filename, 'Cannot guess mimetype for empty filename'
103 f8426b5c Stavros Sachtouris
    try:
104 f8426b5c Stavros Sachtouris
        from mimetypes import guess_type
105 f8426b5c Stavros Sachtouris
        ctype, cenc = guess_type(filename)
106 f8426b5c Stavros Sachtouris
        return ctype or default_content_type, cenc or default_encoding
107 f8426b5c Stavros Sachtouris
    except ImportError:
108 f8426b5c Stavros Sachtouris
        print 'WARNING: Cannot import mimetypes, using defaults'
109 f8426b5c Stavros Sachtouris
        return (default_content_type, default_encoding)
110 f8426b5c Stavros Sachtouris
111 f8426b5c Stavros Sachtouris
112 67cea04c Stavros Sachtouris
def remove_colors():
113 67cea04c Stavros Sachtouris
    global bold
114 3dabe5d2 Stavros Sachtouris
    global red
115 3dabe5d2 Stavros Sachtouris
    global yellow
116 3dabe5d2 Stavros Sachtouris
    global magenta
117 fd5db045 Stavros Sachtouris
118 67cea04c Stavros Sachtouris
    def dummy(val):
119 67cea04c Stavros Sachtouris
        return val
120 3dabe5d2 Stavros Sachtouris
    red = yellow = magenta = bold = dummy
121 7493ccb6 Stavros Sachtouris
122 fd5db045 Stavros Sachtouris
123 cdeadadc Stavros Sachtouris
def pretty_keys(d, delim='_', recursive=False):
124 cdeadadc Stavros Sachtouris
    """<term>delim<term> to <term> <term> transformation"""
125 cdeadadc Stavros Sachtouris
    new_d = dict(d)
126 cdeadadc Stavros Sachtouris
    for k, v in d.items():
127 cdeadadc Stavros Sachtouris
        new_v = new_d.pop(k)
128 cdeadadc Stavros Sachtouris
        new_d[k.replace(delim, ' ').strip()] = pretty_keys(
129 cdeadadc Stavros Sachtouris
            new_v, delim, True) if (
130 cdeadadc Stavros Sachtouris
                recursive and isinstance(v, dict)) else new_v
131 7493ccb6 Stavros Sachtouris
    return new_d
132 7493ccb6 Stavros Sachtouris
133 fd5db045 Stavros Sachtouris
134 0399ac7e Stavros Sachtouris
def print_json(data):
135 0399ac7e Stavros Sachtouris
    """Print a list or dict as json in console
136 0399ac7e Stavros Sachtouris

137 0399ac7e Stavros Sachtouris
    :param data: json-dumpable data
138 0399ac7e Stavros Sachtouris
    """
139 0f383dcc Stavros Sachtouris
    _print(dumps(data, indent=INDENT_TAB))
140 0399ac7e Stavros Sachtouris
141 0399ac7e Stavros Sachtouris
142 545c6c29 Stavros Sachtouris
def pretty_dict(d, *args, **kwargs):
143 545c6c29 Stavros Sachtouris
    print_dict(pretty_keys(d, *args, **kwargs))
144 545c6c29 Stavros Sachtouris
145 545c6c29 Stavros Sachtouris
146 de73876b Stavros Sachtouris
def print_dict(
147 f55d3a15 Stavros Sachtouris
        d,
148 f55d3a15 Stavros Sachtouris
        exclude=(), indent=0,
149 24ff0a35 Stavros Sachtouris
        with_enumeration=False, recursive_enumeration=False):
150 f55d3a15 Stavros Sachtouris
    """Pretty-print a dictionary object
151 f55d3a15 Stavros Sachtouris
    <indent>key: <non iterable item>
152 f55d3a15 Stavros Sachtouris
    <indent>key:
153 a0608786 Stavros Sachtouris
    <indent + INDENT_TAB><pretty-print iterable>
154 f8681ec8 Stavros Sachtouris

155 f55d3a15 Stavros Sachtouris
    :param d: (dict)
156 f8681ec8 Stavros Sachtouris

157 f55d3a15 Stavros Sachtouris
    :param exclude: (iterable of strings) keys to exclude from printing
158 f8681ec8 Stavros Sachtouris

159 f55d3a15 Stavros Sachtouris
    :param indent: (int) initial indentation (recursive)
160 f8681ec8 Stavros Sachtouris

161 f55d3a15 Stavros Sachtouris
    :param with_enumeration: (bool) enumerate 1st-level keys
162 f8681ec8 Stavros Sachtouris

163 f55d3a15 Stavros Sachtouris
    :param recursive_enumeration: (bool) recursively enumerate iterables (does
164 f55d3a15 Stavros Sachtouris
        not enumerate 1st level keys)
165 f8681ec8 Stavros Sachtouris

166 f55d3a15 Stavros Sachtouris
    :raises CLIError: if preconditions fail
167 f8681ec8 Stavros Sachtouris
    """
168 f55d3a15 Stavros Sachtouris
    assert isinstance(d, dict), 'print_dict input must be a dict'
169 f55d3a15 Stavros Sachtouris
    assert indent >= 0, 'print_dict indent must be >= 0'
170 7493ccb6 Stavros Sachtouris
171 f55d3a15 Stavros Sachtouris
    for i, (k, v) in enumerate(d.items()):
172 f55d3a15 Stavros Sachtouris
        k = ('%s' % k).strip()
173 f55d3a15 Stavros Sachtouris
        if k in exclude:
174 7493ccb6 Stavros Sachtouris
            continue
175 f55d3a15 Stavros Sachtouris
        print_str = ' ' * indent
176 f55d3a15 Stavros Sachtouris
        print_str += '%s.' % (i + 1) if with_enumeration else ''
177 f55d3a15 Stavros Sachtouris
        print_str += '%s:' % k
178 f55d3a15 Stavros Sachtouris
        if isinstance(v, dict):
179 0f383dcc Stavros Sachtouris
            _print(print_str)
180 de73876b Stavros Sachtouris
            print_dict(
181 a0608786 Stavros Sachtouris
                v, exclude, indent + INDENT_TAB,
182 f55d3a15 Stavros Sachtouris
                recursive_enumeration, recursive_enumeration)
183 f55d3a15 Stavros Sachtouris
        elif isinstance(v, list) or isinstance(v, tuple):
184 0f383dcc Stavros Sachtouris
            _print(print_str)
185 de73876b Stavros Sachtouris
            print_list(
186 a0608786 Stavros Sachtouris
                v, exclude, indent + INDENT_TAB,
187 f55d3a15 Stavros Sachtouris
                recursive_enumeration, recursive_enumeration)
188 7493ccb6 Stavros Sachtouris
        else:
189 0f383dcc Stavros Sachtouris
            _print('%s %s' % (print_str, v))
190 fd5db045 Stavros Sachtouris
191 7493ccb6 Stavros Sachtouris
192 de73876b Stavros Sachtouris
def print_list(
193 f55d3a15 Stavros Sachtouris
        l,
194 f55d3a15 Stavros Sachtouris
        exclude=(), indent=0,
195 24ff0a35 Stavros Sachtouris
        with_enumeration=False, recursive_enumeration=False):
196 f55d3a15 Stavros Sachtouris
    """Pretty-print a list of items
197 f55d3a15 Stavros Sachtouris
    <indent>key: <non iterable item>
198 f55d3a15 Stavros Sachtouris
    <indent>key:
199 a0608786 Stavros Sachtouris
    <indent + INDENT_TAB><pretty-print iterable>
200 f8681ec8 Stavros Sachtouris

201 f55d3a15 Stavros Sachtouris
    :param l: (list)
202 f8681ec8 Stavros Sachtouris

203 f55d3a15 Stavros Sachtouris
    :param exclude: (iterable of strings) items to exclude from printing
204 f8681ec8 Stavros Sachtouris

205 f55d3a15 Stavros Sachtouris
    :param indent: (int) initial indentation (recursive)
206 f8681ec8 Stavros Sachtouris

207 f55d3a15 Stavros Sachtouris
    :param with_enumeration: (bool) enumerate 1st-level items
208 f8681ec8 Stavros Sachtouris

209 f55d3a15 Stavros Sachtouris
    :param recursive_enumeration: (bool) recursively enumerate iterables (does
210 f55d3a15 Stavros Sachtouris
        not enumerate 1st level keys)
211 f8681ec8 Stavros Sachtouris

212 f55d3a15 Stavros Sachtouris
    :raises CLIError: if preconditions fail
213 f8681ec8 Stavros Sachtouris
    """
214 f55d3a15 Stavros Sachtouris
    assert isinstance(l, list) or isinstance(l, tuple), (
215 f55d3a15 Stavros Sachtouris
        'print_list prinbts a list or tuple')
216 f55d3a15 Stavros Sachtouris
    assert indent >= 0, 'print_list indent must be >= 0'
217 f551841a Stavros Sachtouris
218 f55d3a15 Stavros Sachtouris
    for i, item in enumerate(l):
219 f55d3a15 Stavros Sachtouris
        print_str = ' ' * indent
220 f55d3a15 Stavros Sachtouris
        print_str += '%s.' % (i + 1) if with_enumeration else ''
221 7493ccb6 Stavros Sachtouris
        if isinstance(item, dict):
222 c17b8bc0 Stavros Sachtouris
            if with_enumeration:
223 0f383dcc Stavros Sachtouris
                _print(print_str)
224 0f383dcc Stavros Sachtouris
            elif i and i < len(l):
225 0f383dcc Stavros Sachtouris
                _print('')
226 de73876b Stavros Sachtouris
            print_dict(
227 a0608786 Stavros Sachtouris
                item, exclude,
228 a0608786 Stavros Sachtouris
                indent + (INDENT_TAB if with_enumeration else 0),
229 f55d3a15 Stavros Sachtouris
                recursive_enumeration, recursive_enumeration)
230 f55d3a15 Stavros Sachtouris
        elif isinstance(item, list) or isinstance(item, tuple):
231 c17b8bc0 Stavros Sachtouris
            if with_enumeration:
232 0f383dcc Stavros Sachtouris
                _print(print_str)
233 0f383dcc Stavros Sachtouris
            elif i and i < len(l):
234 0f383dcc Stavros Sachtouris
                _print()
235 de73876b Stavros Sachtouris
            print_list(
236 a0608786 Stavros Sachtouris
                item, exclude, indent + INDENT_TAB,
237 f55d3a15 Stavros Sachtouris
                recursive_enumeration, recursive_enumeration)
238 7493ccb6 Stavros Sachtouris
        else:
239 f55d3a15 Stavros Sachtouris
            item = ('%s' % item).strip()
240 f55d3a15 Stavros Sachtouris
            if item in exclude:
241 f55d3a15 Stavros Sachtouris
                continue
242 0f383dcc Stavros Sachtouris
            _print('%s%s' % (print_str, item))
243 7493ccb6 Stavros Sachtouris
244 fd5db045 Stavros Sachtouris
245 439826ec Stavros Sachtouris
def page_hold(index, limit, maxlen):
246 439826ec Stavros Sachtouris
    """Check if there are results to show, and hold the page when needed
247 46d130c9 Stavros Sachtouris
    :param index: (int) > 0, index of current element
248 439826ec Stavros Sachtouris
    :param limit: (int) 0 < limit <= max, page hold if limit mod index == 0
249 439826ec Stavros Sachtouris
    :param maxlen: (int) Don't hold if index reaches maxlen
250 439826ec Stavros Sachtouris

251 439826ec Stavros Sachtouris
    :returns: True if there are more to show, False if all results are shown
252 439826ec Stavros Sachtouris
    """
253 46d130c9 Stavros Sachtouris
    if index >= maxlen:
254 46d130c9 Stavros Sachtouris
        return False
255 46d130c9 Stavros Sachtouris
    if index and index % limit == 0:
256 46d130c9 Stavros Sachtouris
        raw_input('(%s listed - %s more - "enter" to continue)' % (
257 46d130c9 Stavros Sachtouris
            index, maxlen - index))
258 439826ec Stavros Sachtouris
    return True
259 439826ec Stavros Sachtouris
260 439826ec Stavros Sachtouris
261 de73876b Stavros Sachtouris
def print_items(
262 24ff0a35 Stavros Sachtouris
        items, title=('id', 'name'),
263 24ff0a35 Stavros Sachtouris
        with_enumeration=False, with_redundancy=False,
264 24ff0a35 Stavros Sachtouris
        page_size=0):
265 a494a741 Stavros Sachtouris
    """print dict or list items in a list, using some values as title
266 a494a741 Stavros Sachtouris
    Objects of next level don't inherit enumeration (default: off) or titles
267 a494a741 Stavros Sachtouris

268 a494a741 Stavros Sachtouris
    :param items: (list) items are lists or dict
269 f55d3a15 Stavros Sachtouris

270 a494a741 Stavros Sachtouris
    :param title: (tuple) keys to use their values as title
271 f55d3a15 Stavros Sachtouris

272 a494a741 Stavros Sachtouris
    :param with_enumeration: (boolean) enumerate items (order id on title)
273 f55d3a15 Stavros Sachtouris

274 a494a741 Stavros Sachtouris
    :param with_redundancy: (boolean) values in title also appear on body
275 f55d3a15 Stavros Sachtouris

276 bd40efdf Stavros Sachtouris
    :param page_size: (int) show results in pages of page_size items, enter to
277 bd40efdf Stavros Sachtouris
        continue
278 a494a741 Stavros Sachtouris
    """
279 daedfe3c Stavros Sachtouris
    if not items:
280 daedfe3c Stavros Sachtouris
        return
281 46d130c9 Stavros Sachtouris
    if not (isinstance(items, dict) or isinstance(items, list) or isinstance(
282 46d130c9 Stavros Sachtouris
                items, tuple)):
283 daedfe3c Stavros Sachtouris
        _print('%s' % items)
284 31618e2a Stavros Sachtouris
        return
285 31618e2a Stavros Sachtouris
286 89ea97e1 Stavros Sachtouris
    page_size = int(page_size or 0)
287 bd40efdf Stavros Sachtouris
    try:
288 46d130c9 Stavros Sachtouris
        page_size = page_size if page_size > 0 else len(items)
289 bd40efdf Stavros Sachtouris
    except:
290 bd40efdf Stavros Sachtouris
        page_size = len(items)
291 bd40efdf Stavros Sachtouris
    num_of_pages = len(items) // page_size
292 bd40efdf Stavros Sachtouris
    num_of_pages += 1 if len(items) % page_size else 0
293 54d800e8 Stavros Sachtouris
    for i, item in enumerate(items):
294 a494a741 Stavros Sachtouris
        if with_enumeration:
295 46d130c9 Stavros Sachtouris
            _write('%s. ' % (i + 1))
296 7493ccb6 Stavros Sachtouris
        if isinstance(item, dict):
297 46d130c9 Stavros Sachtouris
            item = dict(item)
298 46d130c9 Stavros Sachtouris
            title = sorted(set(title).intersection(item))
299 46d130c9 Stavros Sachtouris
            pick = item.get if with_redundancy else item.pop
300 46d130c9 Stavros Sachtouris
            header = ' '.join('%s' % pick(key) for key in title)
301 46d130c9 Stavros Sachtouris
            _print(bold(header))
302 a0608786 Stavros Sachtouris
            print_dict(item, indent=INDENT_TAB)
303 46d130c9 Stavros Sachtouris
        elif isinstance(item, list) or isinstance(item, tuple):
304 a0608786 Stavros Sachtouris
            print_list(item, indent=INDENT_TAB)
305 a494a741 Stavros Sachtouris
        else:
306 46d130c9 Stavros Sachtouris
            _print(' %s' % item)
307 439826ec Stavros Sachtouris
        page_hold(i + 1, page_size, len(items))
308 7493ccb6 Stavros Sachtouris
309 fd5db045 Stavros Sachtouris
310 23963422 Stavros Sachtouris
def format_size(size, decimal_factors=False):
311 23963422 Stavros Sachtouris
    units = ('B', 'KB', 'MB', 'GB', 'TB') if decimal_factors else (
312 23963422 Stavros Sachtouris
        'B', 'KiB', 'MiB', 'GiB', 'TiB')
313 23963422 Stavros Sachtouris
    step = 1000 if decimal_factors else 1024
314 23963422 Stavros Sachtouris
    fstep = float(step)
315 7493ccb6 Stavros Sachtouris
    try:
316 7493ccb6 Stavros Sachtouris
        size = float(size)
317 23963422 Stavros Sachtouris
    except (ValueError, TypeError) as err:
318 23963422 Stavros Sachtouris
        raiseCLIError(err, 'Cannot format %s in bytes' % (
319 23963422 Stavros Sachtouris
            ','.join(size) if isinstance(size, tuple) else size))
320 23963422 Stavros Sachtouris
    for i, unit in enumerate(units):
321 23963422 Stavros Sachtouris
        if size < step or i + 1 == len(units):
322 7493ccb6 Stavros Sachtouris
            break
323 23963422 Stavros Sachtouris
        size /= fstep
324 001200c3 Stavros Sachtouris
    s = ('%.2f' % size)
325 23963422 Stavros Sachtouris
    s = s.replace('%s' % step, '%s.99' % (step - 1)) if size <= fstep else s
326 001200c3 Stavros Sachtouris
    while '.' in s and s[-1] in ('0', '.'):
327 001200c3 Stavros Sachtouris
        s = s[:-1]
328 7493ccb6 Stavros Sachtouris
    return s + unit
329 7493ccb6 Stavros Sachtouris
330 fd5db045 Stavros Sachtouris
331 001200c3 Stavros Sachtouris
def to_bytes(size, format):
332 001200c3 Stavros Sachtouris
    """
333 001200c3 Stavros Sachtouris
    :param size: (float) the size in the given format
334 001200c3 Stavros Sachtouris
    :param format: (case insensitive) KiB, KB, MiB, MB, GiB, GB, TiB, TB
335 001200c3 Stavros Sachtouris

336 001200c3 Stavros Sachtouris
    :returns: (int) the size in bytes
337 23963422 Stavros Sachtouris
    :raises ValueError: if invalid size or format
338 23963422 Stavros Sachtouris
    :raises AttributeError: if format is not str
339 23963422 Stavros Sachtouris
    :raises TypeError: if size is not arithmetic or convertible to arithmetic
340 001200c3 Stavros Sachtouris
    """
341 001200c3 Stavros Sachtouris
    format = format.upper()
342 001200c3 Stavros Sachtouris
    if format == 'B':
343 001200c3 Stavros Sachtouris
        return int(size)
344 001200c3 Stavros Sachtouris
    size = float(size)
345 001200c3 Stavros Sachtouris
    units_dc = ('KB', 'MB', 'GB', 'TB')
346 001200c3 Stavros Sachtouris
    units_bi = ('KIB', 'MIB', 'GIB', 'TIB')
347 001200c3 Stavros Sachtouris
348 001200c3 Stavros Sachtouris
    factor = 1024 if format in units_bi else 1000 if format in units_dc else 0
349 001200c3 Stavros Sachtouris
    if not factor:
350 001200c3 Stavros Sachtouris
        raise ValueError('Invalid data size format %s' % format)
351 001200c3 Stavros Sachtouris
    for prefix in ('K', 'M', 'G', 'T'):
352 001200c3 Stavros Sachtouris
        size *= factor
353 001200c3 Stavros Sachtouris
        if format.startswith(prefix):
354 001200c3 Stavros Sachtouris
            break
355 001200c3 Stavros Sachtouris
    return int(size)
356 001200c3 Stavros Sachtouris
357 001200c3 Stavros Sachtouris
358 fd5db045 Stavros Sachtouris
def dict2file(d, f, depth=0):
359 7493ccb6 Stavros Sachtouris
    for k, v in d.items():
360 23963422 Stavros Sachtouris
        f.write('%s%s: ' % (' ' * INDENT_TAB * depth, k))
361 fd5db045 Stavros Sachtouris
        if isinstance(v, dict):
362 7493ccb6 Stavros Sachtouris
            f.write('\n')
363 fd5db045 Stavros Sachtouris
            dict2file(v, f, depth + 1)
364 23963422 Stavros Sachtouris
        elif isinstance(v, list) or isinstance(v, tuple):
365 7493ccb6 Stavros Sachtouris
            f.write('\n')
366 fd5db045 Stavros Sachtouris
            list2file(v, f, depth + 1)
367 7493ccb6 Stavros Sachtouris
        else:
368 23963422 Stavros Sachtouris
            f.write('%s\n' % v)
369 fd5db045 Stavros Sachtouris
370 7493ccb6 Stavros Sachtouris
371 fd5db045 Stavros Sachtouris
def list2file(l, f, depth=1):
372 7493ccb6 Stavros Sachtouris
    for item in l:
373 fd5db045 Stavros Sachtouris
        if isinstance(item, dict):
374 fd5db045 Stavros Sachtouris
            dict2file(item, f, depth + 1)
375 23963422 Stavros Sachtouris
        elif isinstance(item, list) or isinstance(item, tuple):
376 fd5db045 Stavros Sachtouris
            list2file(item, f, depth + 1)
377 7493ccb6 Stavros Sachtouris
        else:
378 23963422 Stavros Sachtouris
            f.write('%s%s\n' % (' ' * INDENT_TAB * depth, item))
379 efbcdc41 Stavros Sachtouris
380 efbcdc41 Stavros Sachtouris
# Split input auxiliary
381 efbcdc41 Stavros Sachtouris
382 efbcdc41 Stavros Sachtouris
383 efbcdc41 Stavros Sachtouris
def _parse_with_regex(line, regex):
384 efbcdc41 Stavros Sachtouris
    re_parser = regex_compile(regex)
385 efbcdc41 Stavros Sachtouris
    return (re_parser.split(line), re_parser.findall(line))
386 efbcdc41 Stavros Sachtouris
387 efbcdc41 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 23963422 Stavros Sachtouris
    return ([parsed_str[1:-1]] if (
394 23963422 Stavros Sachtouris
        parsed_str[0] == parsed_str[-1] and parsed_str[0] in ("'", '"')) else (
395 23963422 Stavros Sachtouris
            parsed_str.split(' '))) if parsed_str else None
396 0ba7b031 Stavros Sachtouris
397 0ba7b031 Stavros Sachtouris
398 0ba7b031 Stavros Sachtouris
def split_input(line):
399 0ba7b031 Stavros Sachtouris
    if not line:
400 0ba7b031 Stavros Sachtouris
        return []
401 0ba7b031 Stavros Sachtouris
    reg_expr = '\'.*?\'|".*?"|^[\S]*$'
402 0ba7b031 Stavros Sachtouris
    (trivial_parts, interesting_parts) = _parse_with_regex(line, reg_expr)
403 0ba7b031 Stavros Sachtouris
    assert(len(trivial_parts) == 1 + len(interesting_parts))
404 0ba7b031 Stavros Sachtouris
    terms = []
405 0ba7b031 Stavros Sachtouris
    for i, tpart in enumerate(trivial_parts):
406 0ba7b031 Stavros Sachtouris
        part = _get_from_parsed(tpart)
407 0ba7b031 Stavros Sachtouris
        if part:
408 0ba7b031 Stavros Sachtouris
            terms += part
409 0ba7b031 Stavros Sachtouris
        try:
410 0ba7b031 Stavros Sachtouris
            part = _get_from_parsed(interesting_parts[i])
411 0ba7b031 Stavros Sachtouris
        except IndexError:
412 0ba7b031 Stavros Sachtouris
            break
413 0ba7b031 Stavros Sachtouris
        if part:
414 0ba7b031 Stavros Sachtouris
            terms += part
415 0ba7b031 Stavros Sachtouris
    return terms
416 0ba7b031 Stavros Sachtouris
417 0ba7b031 Stavros Sachtouris
418 f55d3a15 Stavros Sachtouris
def ask_user(msg, true_resp=('y', )):
419 7147e1ca Stavros Sachtouris
    """Print msg and read user response
420 7147e1ca Stavros Sachtouris

421 001200c3 Stavros Sachtouris
    :param true_resp: (tuple of chars)
422 7147e1ca Stavros Sachtouris

423 7147e1ca Stavros Sachtouris
    :returns: (bool) True if reponse in true responses, False otherwise
424 7147e1ca Stavros Sachtouris
    """
425 23963422 Stavros Sachtouris
    _write('%s [%s/N]: ' % (msg, ', '.join(true_resp)))
426 23963422 Stavros Sachtouris
    _flush()
427 23963422 Stavros Sachtouris
    user_response = _readline()
428 f55d3a15 Stavros Sachtouris
    return user_response[0].lower() in true_resp
429 0ba7b031 Stavros Sachtouris
430 0ba7b031 Stavros Sachtouris
431 02846a75 Stavros Sachtouris
def spiner(size=None):
432 b482315a Stavros Sachtouris
    spins = ('/', '-', '\\', '|')
433 23963422 Stavros Sachtouris
    _write(' ')
434 02846a75 Stavros Sachtouris
    size = size or -1
435 02846a75 Stavros Sachtouris
    i = 0
436 02846a75 Stavros Sachtouris
    while size - i:
437 23963422 Stavros Sachtouris
        _write('\b%s' % spins[i % len(spins)])
438 23963422 Stavros Sachtouris
        _flush()
439 b482315a Stavros Sachtouris
        i += 1
440 02846a75 Stavros Sachtouris
        sleep(0.1)
441 b482315a Stavros Sachtouris
        yield
442 b58c1078 Stavros Sachtouris
    yield
443 b482315a Stavros Sachtouris
444 14b25e00 Stavros Sachtouris
445 14b25e00 Stavros Sachtouris
def get_path_size(testpath):
446 14b25e00 Stavros Sachtouris
    if path.isfile(testpath):
447 14b25e00 Stavros Sachtouris
        return path.getsize(testpath)
448 14b25e00 Stavros Sachtouris
    total_size = 0
449 14b25e00 Stavros Sachtouris
    for top, dirs, files in walk(path.abspath(testpath)):
450 14b25e00 Stavros Sachtouris
        for f in files:
451 14b25e00 Stavros Sachtouris
            f = path.join(top, f)
452 14b25e00 Stavros Sachtouris
            if path.isfile(f):
453 14b25e00 Stavros Sachtouris
                total_size += path.getsize(f)
454 14b25e00 Stavros Sachtouris
    return total_size
455 7ba195e5 Stavros Sachtouris
456 7ba195e5 Stavros Sachtouris
457 7ba195e5 Stavros Sachtouris
def remove_from_items(list_of_dicts, key_to_remove):
458 7ba195e5 Stavros Sachtouris
    for item in list_of_dicts:
459 7ba195e5 Stavros Sachtouris
        assert isinstance(item, dict), 'Item %s not a dict' % item
460 7ba195e5 Stavros Sachtouris
        item.pop(key_to_remove, None)
461 1716a15d Stavros Sachtouris
462 1716a15d Stavros Sachtouris
463 1716a15d Stavros Sachtouris
def filter_dicts_by_dict(
464 1716a15d Stavros Sachtouris
    list_of_dicts, filters,
465 1716a15d Stavros Sachtouris
    exact_match=True, case_sensitive=False):
466 1716a15d Stavros Sachtouris
    """
467 1716a15d Stavros Sachtouris
    :param list_of_dicts: (list) each dict contains "raw" key-value pairs
468 1716a15d Stavros Sachtouris

469 1716a15d Stavros Sachtouris
    :param filters: (dict) filters in key-value form
470 1716a15d Stavros Sachtouris

471 1716a15d Stavros Sachtouris
    :param exact_match: (bool) if false, check if the filter value is part of
472 1716a15d Stavros Sachtouris
        the actual value
473 1716a15d Stavros Sachtouris

474 1716a15d Stavros Sachtouris
    :param case_sensitive: (bool) revers to values only (not keys)
475 1716a15d Stavros Sachtouris

476 1716a15d Stavros Sachtouris
    :returns: (list) only the dicts that match all filters
477 1716a15d Stavros Sachtouris
    """
478 1716a15d Stavros Sachtouris
    new_dicts = []
479 1716a15d Stavros Sachtouris
    for d in list_of_dicts:
480 1716a15d Stavros Sachtouris
        if set(filters).difference(d):
481 1716a15d Stavros Sachtouris
            continue
482 1716a15d Stavros Sachtouris
        match = True
483 1716a15d Stavros Sachtouris
        for k, v in filters.items():
484 1716a15d Stavros Sachtouris
            dv, v = ('%s' % d[k]), ('%s' % v)
485 1716a15d Stavros Sachtouris
            if not case_sensitive:
486 1716a15d Stavros Sachtouris
                dv, v = dv.lower(), v.lower()
487 1716a15d Stavros Sachtouris
            if not ((
488 1716a15d Stavros Sachtouris
                    exact_match and v == dv) or (
489 1716a15d Stavros Sachtouris
                    (not exact_match) and v in dv)):
490 1716a15d Stavros Sachtouris
                match = False
491 1716a15d Stavros Sachtouris
                break
492 1716a15d Stavros Sachtouris
        if match:
493 1716a15d Stavros Sachtouris
            new_dicts.append(d)
494 1716a15d Stavros Sachtouris
    return new_dicts