Statistics
| Branch: | Tag: | Revision:

root / kamaki / cli / utils.py @ f23a5cdb

History | View | Annotate | Download (6 kB)

1
# Copyright 2011 GRNET S.A. All rights reserved.
2
#
3
# Redistribution and use in source and binary forms, with or
4
# without modification, are permitted provided that the following
5
# conditions are met:
6
#
7
#   1. Redistributions of source code must retain the above
8
#      copyright notice, this list of conditions and the following
9
#      disclaimer.
10
#
11
#   2. Redistributions in binary form must reproduce the above
12
#      copyright notice, this list of conditions and the following
13
#      disclaimer in the documentation and/or other materials
14
#      provided with the distribution.
15
#
16
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
# POSSIBILITY OF SUCH DAMAGE.
28
#
29
# The views and conclusions contained in the software and
30
# documentation are those of the authors and should not be
31
# interpreted as representing official policies, either expressed
32
# or implied, of GRNET S.A.
33

    
34
from re import compile as regex_compile
35
from .errors import CLIError
36

    
37
try:
38
    from colors import magenta, red, yellow, bold
39
except ImportError:
40
    # No colours? No worries, use dummy foo instead
41
    def dummy(val):
42
        return val
43
    red = yellow = magenta = bold = dummy
44

    
45

    
46
def remove_colors():
47
    global bold
48
    global red
49
    global yellow
50
    global magenta
51

    
52
    def dummy(val):
53
        return val
54
    red = yellow = magenta = bold = dummy
55

    
56

    
57
def pretty_keys(d, delim='_', recurcive=False):
58
    """<term>delim<term> to <term> <term> transformation
59
    """
60
    new_d = {}
61
    for key, val in d.items():
62
        new_key = key.split(delim)[-1]
63
        if recurcive and isinstance(val, dict):
64
            new_val = pretty_keys(val, delim, recurcive)
65
        else:
66
            new_val = val
67
        new_d[new_key] = new_val
68
    return new_d
69

    
70

    
71
def print_dict(d, exclude=(), ident=0):
72
    if not isinstance(d, dict):
73
        raise CLIError(message='Cannot dict_print a non-dict object')
74

    
75
    if d:
76
        margin = max(len(unicode(key).strip())\
77
            for key in d.keys() if key not in exclude)
78

    
79
    for key, val in sorted(d.items()):
80
        if key in exclude:
81
            continue
82
        print_str = ' ' * ident
83
        print_str += ('%s' % key).strip()
84
        print_str += ' ' * (margin - len(unicode(key).strip()))
85
        print_str += ': '
86
        if isinstance(val, dict):
87
            print(print_str)
88
            print_dict(val, exclude=exclude, ident=margin + ident)
89
        elif isinstance(val, list):
90
            print(print_str)
91
            print_list(val, exclude=exclude, ident=margin + ident)
92
        else:
93
            print print_str + ' ' + unicode(val).strip()
94

    
95

    
96
def print_list(l, exclude=(), ident=0):
97
    if not isinstance(l, list):
98
        raise CLIError(message='Cannot list_print a non-list object')
99

    
100
    if l:
101
        margin = max(len(unicode(item).strip())\
102
            for item in l if item not in exclude)
103

    
104
    for item in sorted(l):
105
        if item in exclude:
106
            continue
107
        if isinstance(item, dict):
108
            print_dict(item, exclude=exclude, ident=margin + ident)
109
        elif isinstance(item, list):
110
            print_list(item, exclude=exclude, ident=margin + ident)
111
        else:
112
            print ' ' * ident + unicode(item)
113

    
114

    
115
def print_items(items, title=('id', 'name')):
116
    for item in items:
117
        if isinstance(item, dict) or isinstance(item, list):
118
            header = ' '.join(unicode(item.pop(key))\
119
                for key in title if key in item)
120
            print(' ')
121
            print(bold(header))
122
        if isinstance(item, dict):
123
            print_dict(item, ident=2)
124
        elif isinstance(item, list):
125
            print_list(item, ident=2)
126

    
127

    
128
def format_size(size):
129
    units = ('B', 'K', 'M', 'G', 'T')
130
    try:
131
        size = float(size)
132
    except ValueError:
133
        raise CLIError(message='Cannot format %s in bytes' % size)
134
    for unit in units:
135
        if size < 1024:
136
            break
137
        size /= 1024
138
    s = ('%.1f' % size)
139
    if '.0' == s[-2:]:
140
        s = s[:-2]
141
    return s + unit
142

    
143

    
144
def dict2file(d, f, depth=0):
145
    for k, v in d.items():
146
        f.write('%s%s: ' % ('\t' * depth, k))
147
        if isinstance(v, dict):
148
            f.write('\n')
149
            dict2file(v, f, depth + 1)
150
        elif isinstance(v, list):
151
            f.write('\n')
152
            list2file(v, f, depth + 1)
153
        else:
154
            f.write(' %s\n' % unicode(v))
155

    
156

    
157
def list2file(l, f, depth=1):
158
    for item in l:
159
        if isinstance(item, dict):
160
            dict2file(item, f, depth + 1)
161
        elif isinstance(item, list):
162
            list2file(item, f, depth + 1)
163
        else:
164
            f.write('%s%s\n' % ('\t' * depth, unicode(item)))
165

    
166
# Split input auxiliary
167

    
168

    
169
def _parse_with_regex(line, regex):
170
    re_parser = regex_compile(regex)
171
    return (re_parser.split(line), re_parser.findall(line))
172

    
173

    
174
def _sub_split(line):
175
    terms = []
176
    (sub_trivials, sub_interesting) = _parse_with_regex(line, ' ".*?" ')
177
    for subi, subipart in enumerate(sub_interesting):
178
        terms += sub_trivials[subi].split()
179
        terms.append(subipart[2:-2])
180
    terms += sub_trivials[-1].split()
181
    return terms
182

    
183

    
184
def split_input(line):
185
    """Use regular expressions to split a line correctly
186
    """
187
    line = ' %s ' % line
188
    (trivial_parts, interesting_parts) = _parse_with_regex(line, ' \'.*?\' ')
189
    terms = []
190
    for i, ipart in enumerate(interesting_parts):
191
        terms += _sub_split(trivial_parts[i])
192
        terms.append(ipart[2:-2])
193
    terms += _sub_split(trivial_parts[-1])
194
    return terms