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):
|