Revision f55d3a15 kamaki/cli/utils.py

b/kamaki/cli/utils.py
39 39

  
40 40
from kamaki.cli.errors import raiseCLIError
41 41

  
42

  
43
IDENT_TAB = 4
44

  
45

  
42 46
suggest = dict(ansicolors=dict(
43 47
        active=False,
44 48
        url='#install-ansicolors-progress',
......
109 113

  
110 114
    :param data: json-dumpable data
111 115
    """
112
    print(dumps(data, indent=2))
116
    print(dumps(data, indent=IDENT_TAB))
113 117

  
114 118

  
115 119
def pretty_dict(d, *args, **kwargs):
......
117 121

  
118 122

  
119 123
def print_dict(
120
        d, exclude=(), ident=0,
124
        d,
125
        exclude=(), indent=0,
121 126
        with_enumeration=False, recursive_enumeration=False):
122
    """
123
    Pretty-print a dictionary object
127
    """Pretty-print a dictionary object
128
    <indent>key: <non iterable item>
129
    <indent>key:
130
    <indent + IDENT_TAB><pretty-print iterable>
124 131

  
125
    :param d: (dict) the input
132
    :param d: (dict)
126 133

  
127
    :param excelude: (set or list) keys to exclude from printing
134
    :param exclude: (iterable of strings) keys to exclude from printing
128 135

  
129
    :param ident: (int) initial indentation (recursive)
136
    :param indent: (int) initial indentation (recursive)
130 137

  
131
    :param with_enumeration: (bool) enumerate each 1st level key if true
138
    :param with_enumeration: (bool) enumerate 1st-level keys
132 139

  
133
    :recursive_enumeration: (bool) recursively enumerate dicts and lists of
134
        2nd level or deeper
140
    :param recursive_enumeration: (bool) recursively enumerate iterables (does
141
        not enumerate 1st level keys)
135 142

  
136
    :raises CLIError: (TypeError wrapper) non-dict input
143
    :raises CLIError: if preconditions fail
137 144
    """
138
    if not isinstance(d, dict):
139
        raiseCLIError(TypeError('Cannot dict_print a non-dict object'))
140

  
141
    if d:
142
        margin = max(len(('%s' % key).strip()) for key in d.keys() if (
143
            key not in exclude))
145
    assert isinstance(d, dict), 'print_dict input must be a dict'
146
    assert indent >= 0, 'print_dict indent must be >= 0'
144 147

  
145
    counter = 1
146
    for key, val in sorted(d.items()):
147
        key = '%s' % key
148
        if key in exclude:
148
    for i, (k, v) in enumerate(d.items()):
149
        k = ('%s' % k).strip()
150
        if k in exclude:
149 151
            continue
150
        print_str = ''
151
        if with_enumeration:
152
            print_str = '%s. ' % counter
153
            counter += 1
154
        print_str = '%s%s' % (' ' * (ident - len(print_str)), print_str)
155
        print_str += key.strip()
156
        print_str += ':'
157
        print_str += ' ' * (margin - len(key.strip()))
158
        #print_str += ':'
159
        if isinstance(val, dict):
160
            print(print_str)
152
        print_str = ' ' * indent
153
        print_str += '%s.' % (i + 1) if with_enumeration else ''
154
        print_str += '%s:' % k
155
        if isinstance(v, dict):
156
            print print_str
161 157
            print_dict(
162
                val,
163
                exclude=exclude,
164
                ident=margin + ident,
165
                with_enumeration=recursive_enumeration,
166
                recursive_enumeration=recursive_enumeration)
167
        elif isinstance(val, list):
168
            print(print_str)
158
                v, exclude, indent + IDENT_TAB,
159
                recursive_enumeration, recursive_enumeration)
160
        elif isinstance(v, list) or isinstance(v, tuple):
161
            print print_str
169 162
            print_list(
170
                val,
171
                exclude=exclude,
172
                ident=margin + ident,
173
                with_enumeration=recursive_enumeration,
174
                recursive_enumeration=recursive_enumeration)
163
                v, exclude, indent + IDENT_TAB,
164
                recursive_enumeration, recursive_enumeration)
175 165
        else:
176
            print print_str + ' ' + ('%s' % val).strip()
166
            print '%s %s' % (print_str, v)
177 167

  
178 168

  
179 169
def print_list(
180
        l, exclude=(), ident=0,
170
        l,
171
        exclude=(), indent=0,
181 172
        with_enumeration=False, recursive_enumeration=False):
182
    """
183
    Pretty-print a list object
173
    """Pretty-print a list of items
174
    <indent>key: <non iterable item>
175
    <indent>key:
176
    <indent + IDENT_TAB><pretty-print iterable>
184 177

  
185
    :param l: (list) the input
178
    :param l: (list)
186 179

  
187
    :param excelude: (object - anytype) values to exclude from printing
180
    :param exclude: (iterable of strings) items to exclude from printing
188 181

  
189
    :param ident: (int) initial indentation (recursive)
182
    :param indent: (int) initial indentation (recursive)
190 183

  
191
    :param with_enumeration: (bool) enumerate each 1st level value if true
184
    :param with_enumeration: (bool) enumerate 1st-level items
192 185

  
193
    :recursive_enumeration: (bool) recursively enumerate dicts and lists of
194
        2nd level or deeper
186
    :param recursive_enumeration: (bool) recursively enumerate iterables (does
187
        not enumerate 1st level keys)
195 188

  
196
    :raises CLIError: (TypeError wrapper) non-list input
189
    :raises CLIError: if preconditions fail
197 190
    """
198
    if not isinstance(l, list):
199
        raiseCLIError(TypeError('Cannot list_print a non-list object'))
191
    assert isinstance(l, list) or isinstance(l, tuple), (
192
        'print_list prinbts a list or tuple')
193
    assert indent >= 0, 'print_list indent must be >= 0'
200 194

  
201
    if l:
202
        try:
203
            margin = max(len(('%s' % item).strip()) for item in l if not (
204
                isinstance(item, dict) or
205
                isinstance(item, list) or
206
                item in exclude))
207
        except ValueError:
208
            margin = (2 + len(('%s' % len(l)))) if enumerate else 1
209

  
210
    counter = 1
211
    prefix = ''
212
    item_sep = False
213
    for item in sorted(l):
214
        if ('%s' % item) in exclude:
215
            continue
216
        elif with_enumeration:
217
            prefix = '%s. ' % counter
218
            counter += 1
219
            prefix = '%s%s' % (' ' * (ident - len(prefix)), prefix)
220
        else:
221
            prefix = ' ' * ident
222
        if item_sep:
223
            print '%s. . . . . . .' % prefix
224
        else:
225
            item_sep = True
195
    for i, item in enumerate(l):
196
        print_str = ' ' * indent
197
        print_str += '%s.' % (i + 1) if with_enumeration else ''
226 198
        if isinstance(item, dict):
227 199
            if with_enumeration:
228
                print(prefix)
200
                print print_str
229 201
            print_dict(
230
                item,
231
                exclude=exclude,
232
                ident=margin + ident,
233
                with_enumeration=recursive_enumeration,
234
                recursive_enumeration=recursive_enumeration)
235
        elif isinstance(item, list):
202
                item, exclude, indent,
203
                recursive_enumeration, recursive_enumeration)
204
        elif isinstance(item, list) or isinstance(item, tuple):
236 205
            if with_enumeration:
237
                print(prefix)
206
                print print_str
238 207
            print_list(
239
                item,
240
                exclude=exclude,
241
                ident=margin + ident,
242
                with_enumeration=recursive_enumeration,
243
                recursive_enumeration=recursive_enumeration)
208
                item, exclude, indent + IDENT_TAB,
209
                recursive_enumeration, recursive_enumeration)
244 210
        else:
245
            print('%s%s' % (prefix, item))
211
            item = ('%s' % item).strip()
212
            if item in exclude:
213
                continue
214
            print '%s%s' % (print_str, item)
215
        if (i + 1) < len(l):
216
            print
246 217

  
247 218

  
248 219
def page_hold(index, limit, maxlen):
......
274 245
    Objects of next level don't inherit enumeration (default: off) or titles
275 246

  
276 247
    :param items: (list) items are lists or dict
248

  
277 249
    :param title: (tuple) keys to use their values as title
250

  
278 251
    :param with_enumeration: (boolean) enumerate items (order id on title)
252

  
279 253
    :param with_redundancy: (boolean) values in title also appear on body
254

  
280 255
    :param page_size: (int) show results in pages of page_size items, enter to
281 256
        continue
282 257
    """
......
299 274
                header = ' '.join('%s' % item.pop(key) for key in title)
300 275
            print(bold(header))
301 276
        if isinstance(item, dict):
302
            print_dict(item, ident=1)
277
            print_dict(item, indent=IDENT_TAB)
303 278
        elif isinstance(item, list):
304
            print_list(item, ident=1)
279
            print_list(item, indent=IDENT_TAB)
305 280
        else:
306 281
            print(' %s' % item)
307 282
        page_hold(i + 1, page_size, len(items))
......
433 408
    return terms
434 409

  
435 410

  
436
def ask_user(msg, true_resp=['Y', 'y']):
411
def ask_user(msg, true_resp=('y', )):
437 412
    """Print msg and read user response
438 413

  
439 414
    :param true_resp: (tuple of chars)
440 415

  
441 416
    :returns: (bool) True if reponse in true responses, False otherwise
442 417
    """
443
    stdout.write('%s (%s or enter for yes):' % (msg, ', '.join(true_resp)))
418
    stdout.write('%s [%s/N]: ' % (msg, ', '.join(true_resp)))
444 419
    stdout.flush()
445 420
    user_response = stdin.readline()
446
    return user_response[0] in true_resp + ['\n']
421
    return user_response[0].lower() in true_resp
447 422

  
448 423

  
449 424
def spiner(size=None):

Also available in: Unified diff