Statistics
| Branch: | Tag: | Revision:

root / kamaki / cli / utils.py @ 457cb69b

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
    """Transform keys of a dict from the form
59
        str1_str2_..._strN to the form strN
60
        where _ is the delimeter
61
    """
62
    new_d = {}
63
    for key, val in d.items():
64
        new_key = key.split(delim)[-1]
65
        if recurcive and isinstance(val, dict):
66
            new_val = pretty_keys(val, delim, recurcive)
67
        else:
68
            new_val = val
69
        new_d[new_key] = new_val
70
    return new_d
71

    
72

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

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

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

    
97

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

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

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

    
116

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

    
129

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

    
145

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

    
158

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

    
168
# Split input auxiliary
169

    
170

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

    
175

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

    
185

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