Statistics
| Branch: | Tag: | Revision:

root / kamaki / cli / utils / __init__.py @ c49188b7

History | View | Annotate | Download (14.2 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 fa9c0c38 Stavros Sachtouris
from sys import stdout, stdin
35 efbcdc41 Stavros Sachtouris
from re import compile as regex_compile
36 14b25e00 Stavros Sachtouris
from os import walk, path
37 0399ac7e Stavros Sachtouris
from json import dumps
38 fa9c0c38 Stavros Sachtouris
from pydoc import pager
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 69691087 Stavros Sachtouris
def suggest_missing(miss=None, exclude=[]):
61 6fb4af77 Stavros Sachtouris
    global suggest
62 69691087 Stavros Sachtouris
    sgs = dict(suggest)
63 69691087 Stavros Sachtouris
    for exc in exclude:
64 69691087 Stavros Sachtouris
        try:
65 69691087 Stavros Sachtouris
            sgs.pop(exc)
66 69691087 Stavros Sachtouris
        except KeyError:
67 69691087 Stavros Sachtouris
            pass
68 6fb4af77 Stavros Sachtouris
    kamaki_docs = 'http://www.synnefo.org/docs/kamaki/latest'
69 69691087 Stavros Sachtouris
    for k, v in (miss, sgs[miss]) if miss else sgs.items():
70 6fb4af77 Stavros Sachtouris
        if v['active'] and stdout.isatty():
71 6fb4af77 Stavros Sachtouris
            print('Suggestion: for better user experience install %s' % k)
72 6fb4af77 Stavros Sachtouris
            print('\t%s' % v['description'])
73 6fb4af77 Stavros Sachtouris
            print('\tIt is easy, here are the instructions:')
74 6fb4af77 Stavros Sachtouris
            print('\t%s/installation.html%s' % (kamaki_docs, v['url']))
75 6fb4af77 Stavros Sachtouris
            print('')
76 f997679d Stavros Sachtouris
77 fd5db045 Stavros Sachtouris
78 f8426b5c Stavros Sachtouris
def guess_mime_type(
79 f8426b5c Stavros Sachtouris
        filename,
80 f8426b5c Stavros Sachtouris
        default_content_type='application/octet-stream',
81 f8426b5c Stavros Sachtouris
        default_encoding=None):
82 f8426b5c Stavros Sachtouris
    assert filename, 'Cannot guess mimetype for empty filename'
83 f8426b5c Stavros Sachtouris
    try:
84 f8426b5c Stavros Sachtouris
        from mimetypes import guess_type
85 f8426b5c Stavros Sachtouris
        ctype, cenc = guess_type(filename)
86 f8426b5c Stavros Sachtouris
        return ctype or default_content_type, cenc or default_encoding
87 f8426b5c Stavros Sachtouris
    except ImportError:
88 f8426b5c Stavros Sachtouris
        print 'WARNING: Cannot import mimetypes, using defaults'
89 f8426b5c Stavros Sachtouris
        return (default_content_type, default_encoding)
90 f8426b5c Stavros Sachtouris
91 f8426b5c Stavros Sachtouris
92 67cea04c Stavros Sachtouris
def remove_colors():
93 67cea04c Stavros Sachtouris
    global bold
94 3dabe5d2 Stavros Sachtouris
    global red
95 3dabe5d2 Stavros Sachtouris
    global yellow
96 3dabe5d2 Stavros Sachtouris
    global magenta
97 fd5db045 Stavros Sachtouris
98 67cea04c Stavros Sachtouris
    def dummy(val):
99 67cea04c Stavros Sachtouris
        return val
100 3dabe5d2 Stavros Sachtouris
    red = yellow = magenta = bold = dummy
101 7493ccb6 Stavros Sachtouris
102 fd5db045 Stavros Sachtouris
103 cdeadadc Stavros Sachtouris
def pretty_keys(d, delim='_', recursive=False):
104 cdeadadc Stavros Sachtouris
    """<term>delim<term> to <term> <term> transformation"""
105 cdeadadc Stavros Sachtouris
    new_d = dict(d)
106 cdeadadc Stavros Sachtouris
    for k, v in d.items():
107 cdeadadc Stavros Sachtouris
        new_v = new_d.pop(k)
108 cdeadadc Stavros Sachtouris
        new_d[k.replace(delim, ' ').strip()] = pretty_keys(
109 cdeadadc Stavros Sachtouris
            new_v, delim, True) if (
110 cdeadadc Stavros Sachtouris
                recursive and isinstance(v, dict)) else new_v
111 7493ccb6 Stavros Sachtouris
    return new_d
112 7493ccb6 Stavros Sachtouris
113 fd5db045 Stavros Sachtouris
114 fa9c0c38 Stavros Sachtouris
def print_json(data, out=stdout):
115 0399ac7e Stavros Sachtouris
    """Print a list or dict as json in console
116 0399ac7e Stavros Sachtouris

117 0399ac7e Stavros Sachtouris
    :param data: json-dumpable data
118 0399ac7e Stavros Sachtouris

119 fa9c0c38 Stavros Sachtouris
    :param out: Input/Output stream to dump values into
120 fa9c0c38 Stavros Sachtouris
    """
121 fa9c0c38 Stavros Sachtouris
    out.writelines(unicode(dumps(data, indent=INDENT_TAB) + '\n'))
122 545c6c29 Stavros Sachtouris
123 545c6c29 Stavros Sachtouris
124 de73876b Stavros Sachtouris
def print_dict(
125 f55d3a15 Stavros Sachtouris
        d,
126 f55d3a15 Stavros Sachtouris
        exclude=(), indent=0,
127 fa9c0c38 Stavros Sachtouris
        with_enumeration=False, recursive_enumeration=False, out=stdout):
128 f55d3a15 Stavros Sachtouris
    """Pretty-print a dictionary object
129 f55d3a15 Stavros Sachtouris
    <indent>key: <non iterable item>
130 f55d3a15 Stavros Sachtouris
    <indent>key:
131 a0608786 Stavros Sachtouris
    <indent + INDENT_TAB><pretty-print iterable>
132 f8681ec8 Stavros Sachtouris

133 f55d3a15 Stavros Sachtouris
    :param d: (dict)
134 f8681ec8 Stavros Sachtouris

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

137 f55d3a15 Stavros Sachtouris
    :param indent: (int) initial indentation (recursive)
138 f8681ec8 Stavros Sachtouris

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

141 f55d3a15 Stavros Sachtouris
    :param recursive_enumeration: (bool) recursively enumerate iterables (does
142 f55d3a15 Stavros Sachtouris
        not enumerate 1st level keys)
143 f8681ec8 Stavros Sachtouris

144 fa9c0c38 Stavros Sachtouris
    :param out: Input/Output stream to dump values into
145 fa9c0c38 Stavros Sachtouris

146 f55d3a15 Stavros Sachtouris
    :raises CLIError: if preconditions fail
147 f8681ec8 Stavros Sachtouris
    """
148 f55d3a15 Stavros Sachtouris
    assert isinstance(d, dict), 'print_dict input must be a dict'
149 f55d3a15 Stavros Sachtouris
    assert indent >= 0, 'print_dict indent must be >= 0'
150 7493ccb6 Stavros Sachtouris
151 f55d3a15 Stavros Sachtouris
    for i, (k, v) in enumerate(d.items()):
152 f55d3a15 Stavros Sachtouris
        k = ('%s' % k).strip()
153 f55d3a15 Stavros Sachtouris
        if k in exclude:
154 7493ccb6 Stavros Sachtouris
            continue
155 fa9c0c38 Stavros Sachtouris
        print_str = u' ' * indent
156 fa9c0c38 Stavros Sachtouris
        print_str += u'%s.' % (i + 1) if with_enumeration else u''
157 fa9c0c38 Stavros Sachtouris
        print_str += u'%s:' % k
158 f55d3a15 Stavros Sachtouris
        if isinstance(v, dict):
159 fa9c0c38 Stavros Sachtouris
            out.writelines(print_str + '\n')
160 de73876b Stavros Sachtouris
            print_dict(
161 a0608786 Stavros Sachtouris
                v, exclude, indent + INDENT_TAB,
162 fa9c0c38 Stavros Sachtouris
                recursive_enumeration, recursive_enumeration, out)
163 f55d3a15 Stavros Sachtouris
        elif isinstance(v, list) or isinstance(v, tuple):
164 fa9c0c38 Stavros Sachtouris
            out.writelines(print_str + '\n')
165 de73876b Stavros Sachtouris
            print_list(
166 a0608786 Stavros Sachtouris
                v, exclude, indent + INDENT_TAB,
167 fa9c0c38 Stavros Sachtouris
                recursive_enumeration, recursive_enumeration, out)
168 7493ccb6 Stavros Sachtouris
        else:
169 fa9c0c38 Stavros Sachtouris
            out.writelines(u'%s %s\n' % (print_str, v))
170 fd5db045 Stavros Sachtouris
171 7493ccb6 Stavros Sachtouris
172 de73876b Stavros Sachtouris
def print_list(
173 f55d3a15 Stavros Sachtouris
        l,
174 f55d3a15 Stavros Sachtouris
        exclude=(), indent=0,
175 fa9c0c38 Stavros Sachtouris
        with_enumeration=False, recursive_enumeration=False, out=stdout):
176 f55d3a15 Stavros Sachtouris
    """Pretty-print a list of items
177 f55d3a15 Stavros Sachtouris
    <indent>key: <non iterable item>
178 f55d3a15 Stavros Sachtouris
    <indent>key:
179 a0608786 Stavros Sachtouris
    <indent + INDENT_TAB><pretty-print iterable>
180 f8681ec8 Stavros Sachtouris

181 f55d3a15 Stavros Sachtouris
    :param l: (list)
182 f8681ec8 Stavros Sachtouris

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

185 f55d3a15 Stavros Sachtouris
    :param indent: (int) initial indentation (recursive)
186 f8681ec8 Stavros Sachtouris

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

189 f55d3a15 Stavros Sachtouris
    :param recursive_enumeration: (bool) recursively enumerate iterables (does
190 f55d3a15 Stavros Sachtouris
        not enumerate 1st level keys)
191 f8681ec8 Stavros Sachtouris

192 fa9c0c38 Stavros Sachtouris
    :param out: Input/Output stream to dump values into
193 fa9c0c38 Stavros Sachtouris

194 f55d3a15 Stavros Sachtouris
    :raises CLIError: if preconditions fail
195 f8681ec8 Stavros Sachtouris
    """
196 f55d3a15 Stavros Sachtouris
    assert isinstance(l, list) or isinstance(l, tuple), (
197 f55d3a15 Stavros Sachtouris
        'print_list prinbts a list or tuple')
198 f55d3a15 Stavros Sachtouris
    assert indent >= 0, 'print_list indent must be >= 0'
199 f551841a Stavros Sachtouris
200 f55d3a15 Stavros Sachtouris
    for i, item in enumerate(l):
201 fa9c0c38 Stavros Sachtouris
        print_str = u' ' * indent
202 fa9c0c38 Stavros Sachtouris
        print_str += u'%s.' % (i + 1) if with_enumeration else u''
203 7493ccb6 Stavros Sachtouris
        if isinstance(item, dict):
204 c17b8bc0 Stavros Sachtouris
            if with_enumeration:
205 fa9c0c38 Stavros Sachtouris
                out.writelines(print_str + '\n')
206 0f383dcc Stavros Sachtouris
            elif i and i < len(l):
207 fa9c0c38 Stavros Sachtouris
                out.writelines(u'\n')
208 de73876b Stavros Sachtouris
            print_dict(
209 a0608786 Stavros Sachtouris
                item, exclude,
210 a0608786 Stavros Sachtouris
                indent + (INDENT_TAB if with_enumeration else 0),
211 fa9c0c38 Stavros Sachtouris
                recursive_enumeration, recursive_enumeration, out)
212 f55d3a15 Stavros Sachtouris
        elif isinstance(item, list) or isinstance(item, tuple):
213 c17b8bc0 Stavros Sachtouris
            if with_enumeration:
214 fa9c0c38 Stavros Sachtouris
                out.writelines(print_str + '\n')
215 0f383dcc Stavros Sachtouris
            elif i and i < len(l):
216 fa9c0c38 Stavros Sachtouris
                out.writelines(u'\n')
217 de73876b Stavros Sachtouris
            print_list(
218 a0608786 Stavros Sachtouris
                item, exclude, indent + INDENT_TAB,
219 fa9c0c38 Stavros Sachtouris
                recursive_enumeration, recursive_enumeration, out)
220 7493ccb6 Stavros Sachtouris
        else:
221 f55d3a15 Stavros Sachtouris
            item = ('%s' % item).strip()
222 f55d3a15 Stavros Sachtouris
            if item in exclude:
223 f55d3a15 Stavros Sachtouris
                continue
224 c49188b7 Stavros Sachtouris
            out.write(u'%s%s\n' % (print_str, item))
225 c49188b7 Stavros Sachtouris
            out.flush()
226 439826ec Stavros Sachtouris
227 439826ec Stavros Sachtouris
228 de73876b Stavros Sachtouris
def print_items(
229 24ff0a35 Stavros Sachtouris
        items, title=('id', 'name'),
230 fa9c0c38 Stavros Sachtouris
        with_enumeration=False, with_redundancy=False, out=stdout):
231 a494a741 Stavros Sachtouris
    """print dict or list items in a list, using some values as title
232 a494a741 Stavros Sachtouris
    Objects of next level don't inherit enumeration (default: off) or titles
233 a494a741 Stavros Sachtouris

234 a494a741 Stavros Sachtouris
    :param items: (list) items are lists or dict
235 f55d3a15 Stavros Sachtouris

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

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

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

242 fa9c0c38 Stavros Sachtouris
    :param out: Input/Output stream to dump values into
243 a494a741 Stavros Sachtouris
    """
244 daedfe3c Stavros Sachtouris
    if not items:
245 daedfe3c Stavros Sachtouris
        return
246 46d130c9 Stavros Sachtouris
    if not (isinstance(items, dict) or isinstance(items, list) or isinstance(
247 46d130c9 Stavros Sachtouris
                items, tuple)):
248 fa9c0c38 Stavros Sachtouris
        out.writelines(u'%s\n' % items)
249 31618e2a Stavros Sachtouris
        return
250 31618e2a Stavros Sachtouris
251 54d800e8 Stavros Sachtouris
    for i, item in enumerate(items):
252 a494a741 Stavros Sachtouris
        if with_enumeration:
253 fa9c0c38 Stavros Sachtouris
            out.write(u'%s. ' % (i + 1))
254 7493ccb6 Stavros Sachtouris
        if isinstance(item, dict):
255 46d130c9 Stavros Sachtouris
            item = dict(item)
256 46d130c9 Stavros Sachtouris
            title = sorted(set(title).intersection(item))
257 46d130c9 Stavros Sachtouris
            pick = item.get if with_redundancy else item.pop
258 fa9c0c38 Stavros Sachtouris
            header = u' '.join(u'%s' % pick(key) for key in title)
259 6430d3a0 Stavros Sachtouris
            out.writelines((unicode(bold(header) if header else '') + '\n'))
260 fa9c0c38 Stavros Sachtouris
            print_dict(item, indent=INDENT_TAB, out=out)
261 46d130c9 Stavros Sachtouris
        elif isinstance(item, list) or isinstance(item, tuple):
262 fa9c0c38 Stavros Sachtouris
            print_list(item, indent=INDENT_TAB, out=out)
263 a494a741 Stavros Sachtouris
        else:
264 fa9c0c38 Stavros Sachtouris
            out.writelines(u' %s\n' % item)
265 7493ccb6 Stavros Sachtouris
266 fd5db045 Stavros Sachtouris
267 23963422 Stavros Sachtouris
def format_size(size, decimal_factors=False):
268 23963422 Stavros Sachtouris
    units = ('B', 'KB', 'MB', 'GB', 'TB') if decimal_factors else (
269 23963422 Stavros Sachtouris
        'B', 'KiB', 'MiB', 'GiB', 'TiB')
270 23963422 Stavros Sachtouris
    step = 1000 if decimal_factors else 1024
271 23963422 Stavros Sachtouris
    fstep = float(step)
272 7493ccb6 Stavros Sachtouris
    try:
273 7493ccb6 Stavros Sachtouris
        size = float(size)
274 23963422 Stavros Sachtouris
    except (ValueError, TypeError) as err:
275 23963422 Stavros Sachtouris
        raiseCLIError(err, 'Cannot format %s in bytes' % (
276 23963422 Stavros Sachtouris
            ','.join(size) if isinstance(size, tuple) else size))
277 23963422 Stavros Sachtouris
    for i, unit in enumerate(units):
278 23963422 Stavros Sachtouris
        if size < step or i + 1 == len(units):
279 7493ccb6 Stavros Sachtouris
            break
280 23963422 Stavros Sachtouris
        size /= fstep
281 001200c3 Stavros Sachtouris
    s = ('%.2f' % size)
282 23963422 Stavros Sachtouris
    s = s.replace('%s' % step, '%s.99' % (step - 1)) if size <= fstep else s
283 001200c3 Stavros Sachtouris
    while '.' in s and s[-1] in ('0', '.'):
284 001200c3 Stavros Sachtouris
        s = s[:-1]
285 7493ccb6 Stavros Sachtouris
    return s + unit
286 7493ccb6 Stavros Sachtouris
287 fd5db045 Stavros Sachtouris
288 001200c3 Stavros Sachtouris
def to_bytes(size, format):
289 001200c3 Stavros Sachtouris
    """
290 001200c3 Stavros Sachtouris
    :param size: (float) the size in the given format
291 001200c3 Stavros Sachtouris
    :param format: (case insensitive) KiB, KB, MiB, MB, GiB, GB, TiB, TB
292 001200c3 Stavros Sachtouris

293 001200c3 Stavros Sachtouris
    :returns: (int) the size in bytes
294 23963422 Stavros Sachtouris
    :raises ValueError: if invalid size or format
295 23963422 Stavros Sachtouris
    :raises AttributeError: if format is not str
296 23963422 Stavros Sachtouris
    :raises TypeError: if size is not arithmetic or convertible to arithmetic
297 001200c3 Stavros Sachtouris
    """
298 001200c3 Stavros Sachtouris
    format = format.upper()
299 001200c3 Stavros Sachtouris
    if format == 'B':
300 001200c3 Stavros Sachtouris
        return int(size)
301 001200c3 Stavros Sachtouris
    size = float(size)
302 001200c3 Stavros Sachtouris
    units_dc = ('KB', 'MB', 'GB', 'TB')
303 001200c3 Stavros Sachtouris
    units_bi = ('KIB', 'MIB', 'GIB', 'TIB')
304 001200c3 Stavros Sachtouris
305 001200c3 Stavros Sachtouris
    factor = 1024 if format in units_bi else 1000 if format in units_dc else 0
306 001200c3 Stavros Sachtouris
    if not factor:
307 001200c3 Stavros Sachtouris
        raise ValueError('Invalid data size format %s' % format)
308 001200c3 Stavros Sachtouris
    for prefix in ('K', 'M', 'G', 'T'):
309 001200c3 Stavros Sachtouris
        size *= factor
310 001200c3 Stavros Sachtouris
        if format.startswith(prefix):
311 001200c3 Stavros Sachtouris
            break
312 001200c3 Stavros Sachtouris
    return int(size)
313 001200c3 Stavros Sachtouris
314 001200c3 Stavros Sachtouris
315 fd5db045 Stavros Sachtouris
def dict2file(d, f, depth=0):
316 7493ccb6 Stavros Sachtouris
    for k, v in d.items():
317 23963422 Stavros Sachtouris
        f.write('%s%s: ' % (' ' * INDENT_TAB * depth, k))
318 fd5db045 Stavros Sachtouris
        if isinstance(v, dict):
319 7493ccb6 Stavros Sachtouris
            f.write('\n')
320 fd5db045 Stavros Sachtouris
            dict2file(v, f, depth + 1)
321 23963422 Stavros Sachtouris
        elif isinstance(v, list) or isinstance(v, tuple):
322 7493ccb6 Stavros Sachtouris
            f.write('\n')
323 fd5db045 Stavros Sachtouris
            list2file(v, f, depth + 1)
324 7493ccb6 Stavros Sachtouris
        else:
325 23963422 Stavros Sachtouris
            f.write('%s\n' % v)
326 fd5db045 Stavros Sachtouris
327 7493ccb6 Stavros Sachtouris
328 fd5db045 Stavros Sachtouris
def list2file(l, f, depth=1):
329 7493ccb6 Stavros Sachtouris
    for item in l:
330 fd5db045 Stavros Sachtouris
        if isinstance(item, dict):
331 fd5db045 Stavros Sachtouris
            dict2file(item, f, depth + 1)
332 23963422 Stavros Sachtouris
        elif isinstance(item, list) or isinstance(item, tuple):
333 fd5db045 Stavros Sachtouris
            list2file(item, f, depth + 1)
334 7493ccb6 Stavros Sachtouris
        else:
335 23963422 Stavros Sachtouris
            f.write('%s%s\n' % (' ' * INDENT_TAB * depth, item))
336 efbcdc41 Stavros Sachtouris
337 efbcdc41 Stavros Sachtouris
# Split input auxiliary
338 efbcdc41 Stavros Sachtouris
339 efbcdc41 Stavros Sachtouris
340 efbcdc41 Stavros Sachtouris
def _parse_with_regex(line, regex):
341 efbcdc41 Stavros Sachtouris
    re_parser = regex_compile(regex)
342 efbcdc41 Stavros Sachtouris
    return (re_parser.split(line), re_parser.findall(line))
343 efbcdc41 Stavros Sachtouris
344 efbcdc41 Stavros Sachtouris
345 0ba7b031 Stavros Sachtouris
def _get_from_parsed(parsed_str):
346 0ba7b031 Stavros Sachtouris
    try:
347 0ba7b031 Stavros Sachtouris
        parsed_str = parsed_str.strip()
348 0ba7b031 Stavros Sachtouris
    except:
349 0ba7b031 Stavros Sachtouris
        return None
350 23963422 Stavros Sachtouris
    return ([parsed_str[1:-1]] if (
351 23963422 Stavros Sachtouris
        parsed_str[0] == parsed_str[-1] and parsed_str[0] in ("'", '"')) else (
352 23963422 Stavros Sachtouris
            parsed_str.split(' '))) if parsed_str else None
353 0ba7b031 Stavros Sachtouris
354 0ba7b031 Stavros Sachtouris
355 0ba7b031 Stavros Sachtouris
def split_input(line):
356 0ba7b031 Stavros Sachtouris
    if not line:
357 0ba7b031 Stavros Sachtouris
        return []
358 0ba7b031 Stavros Sachtouris
    reg_expr = '\'.*?\'|".*?"|^[\S]*$'
359 0ba7b031 Stavros Sachtouris
    (trivial_parts, interesting_parts) = _parse_with_regex(line, reg_expr)
360 0ba7b031 Stavros Sachtouris
    assert(len(trivial_parts) == 1 + len(interesting_parts))
361 0ba7b031 Stavros Sachtouris
    terms = []
362 0ba7b031 Stavros Sachtouris
    for i, tpart in enumerate(trivial_parts):
363 0ba7b031 Stavros Sachtouris
        part = _get_from_parsed(tpart)
364 0ba7b031 Stavros Sachtouris
        if part:
365 0ba7b031 Stavros Sachtouris
            terms += part
366 0ba7b031 Stavros Sachtouris
        try:
367 0ba7b031 Stavros Sachtouris
            part = _get_from_parsed(interesting_parts[i])
368 0ba7b031 Stavros Sachtouris
        except IndexError:
369 0ba7b031 Stavros Sachtouris
            break
370 0ba7b031 Stavros Sachtouris
        if part:
371 b9eebf2a Stavros Sachtouris
            if tpart and not tpart[-1].endswith(' '):
372 b9eebf2a Stavros Sachtouris
                terms[-1] += ' '.join(part)
373 b9eebf2a Stavros Sachtouris
            else:
374 b9eebf2a Stavros Sachtouris
                terms += part
375 0ba7b031 Stavros Sachtouris
    return terms
376 0ba7b031 Stavros Sachtouris
377 0ba7b031 Stavros Sachtouris
378 fa9c0c38 Stavros Sachtouris
def ask_user(msg, true_resp=('y', ), out=stdout, user_in=stdin):
379 7147e1ca Stavros Sachtouris
    """Print msg and read user response
380 7147e1ca Stavros Sachtouris

381 001200c3 Stavros Sachtouris
    :param true_resp: (tuple of chars)
382 7147e1ca Stavros Sachtouris

383 7147e1ca Stavros Sachtouris
    :returns: (bool) True if reponse in true responses, False otherwise
384 7147e1ca Stavros Sachtouris
    """
385 fa9c0c38 Stavros Sachtouris
    yep = ', '.join(true_resp)
386 fa9c0c38 Stavros Sachtouris
    nope = '<not %s>' % yep if 'n' in true_resp or 'N' in true_resp else 'N'
387 fa9c0c38 Stavros Sachtouris
    out.write(u'%s [%s/%s]: ' % (msg, yep, nope))
388 fa9c0c38 Stavros Sachtouris
    out.flush()
389 fa9c0c38 Stavros Sachtouris
    user_response = user_in.readline()
390 fa9c0c38 Stavros Sachtouris
    return user_response[0].lower() in [s.lower() for s in true_resp]
391 b482315a Stavros Sachtouris
392 14b25e00 Stavros Sachtouris
393 14b25e00 Stavros Sachtouris
def get_path_size(testpath):
394 14b25e00 Stavros Sachtouris
    if path.isfile(testpath):
395 14b25e00 Stavros Sachtouris
        return path.getsize(testpath)
396 14b25e00 Stavros Sachtouris
    total_size = 0
397 14b25e00 Stavros Sachtouris
    for top, dirs, files in walk(path.abspath(testpath)):
398 14b25e00 Stavros Sachtouris
        for f in files:
399 14b25e00 Stavros Sachtouris
            f = path.join(top, f)
400 14b25e00 Stavros Sachtouris
            if path.isfile(f):
401 14b25e00 Stavros Sachtouris
                total_size += path.getsize(f)
402 14b25e00 Stavros Sachtouris
    return total_size
403 7ba195e5 Stavros Sachtouris
404 7ba195e5 Stavros Sachtouris
405 7ba195e5 Stavros Sachtouris
def remove_from_items(list_of_dicts, key_to_remove):
406 7ba195e5 Stavros Sachtouris
    for item in list_of_dicts:
407 7ba195e5 Stavros Sachtouris
        assert isinstance(item, dict), 'Item %s not a dict' % item
408 7ba195e5 Stavros Sachtouris
        item.pop(key_to_remove, None)
409 1716a15d Stavros Sachtouris
410 1716a15d Stavros Sachtouris
411 1716a15d Stavros Sachtouris
def filter_dicts_by_dict(
412 1716a15d Stavros Sachtouris
    list_of_dicts, filters,
413 1716a15d Stavros Sachtouris
    exact_match=True, case_sensitive=False):
414 1716a15d Stavros Sachtouris
    """
415 1716a15d Stavros Sachtouris
    :param list_of_dicts: (list) each dict contains "raw" key-value pairs
416 1716a15d Stavros Sachtouris

417 1716a15d Stavros Sachtouris
    :param filters: (dict) filters in key-value form
418 1716a15d Stavros Sachtouris

419 1716a15d Stavros Sachtouris
    :param exact_match: (bool) if false, check if the filter value is part of
420 1716a15d Stavros Sachtouris
        the actual value
421 1716a15d Stavros Sachtouris

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

424 1716a15d Stavros Sachtouris
    :returns: (list) only the dicts that match all filters
425 1716a15d Stavros Sachtouris
    """
426 1716a15d Stavros Sachtouris
    new_dicts = []
427 1716a15d Stavros Sachtouris
    for d in list_of_dicts:
428 1716a15d Stavros Sachtouris
        if set(filters).difference(d):
429 1716a15d Stavros Sachtouris
            continue
430 1716a15d Stavros Sachtouris
        match = True
431 1716a15d Stavros Sachtouris
        for k, v in filters.items():
432 1716a15d Stavros Sachtouris
            dv, v = ('%s' % d[k]), ('%s' % v)
433 1716a15d Stavros Sachtouris
            if not case_sensitive:
434 1716a15d Stavros Sachtouris
                dv, v = dv.lower(), v.lower()
435 1716a15d Stavros Sachtouris
            if not ((
436 1716a15d Stavros Sachtouris
                    exact_match and v == dv) or (
437 1716a15d Stavros Sachtouris
                    (not exact_match) and v in dv)):
438 1716a15d Stavros Sachtouris
                match = False
439 1716a15d Stavros Sachtouris
                break
440 1716a15d Stavros Sachtouris
        if match:
441 1716a15d Stavros Sachtouris
            new_dicts.append(d)
442 1716a15d Stavros Sachtouris
    return new_dicts