Revision 8df239df kamaki/cli/utils/__init__.py
b/kamaki/cli/utils/__init__.py | ||
---|---|---|
31 | 31 |
# interpreted as representing official policies, either expressed |
32 | 32 |
# or implied, of GRNET S.A. |
33 | 33 |
|
34 |
from sys import stdout, stdin |
|
34 |
from sys import stdout, stdin, stderr
|
|
35 | 35 |
from re import compile as regex_compile |
36 | 36 |
from os import walk, path |
37 | 37 |
from json import dumps |
... | ... | |
99 | 99 |
return wrap |
100 | 100 |
|
101 | 101 |
|
102 |
def encode_for_console(s, encoding=pref_enc, replacement='?'): |
|
103 |
if encoding.lower() == 'utf-8': |
|
104 |
return s |
|
105 |
try: |
|
106 |
return s.encode(encoding) |
|
107 |
except UnicodeError as ue: |
|
108 |
log.debug('Encoding(%s): %s' % (encoding, ue)) |
|
109 |
return _encode_nicely(s, encoding, replacement) |
|
110 |
|
|
111 |
|
|
102 | 112 |
def suggest_missing(miss=None, exclude=[]): |
103 | 113 |
global suggest |
104 | 114 |
sgs = dict(suggest) |
... | ... | |
108 | 118 |
except KeyError: |
109 | 119 |
pass |
110 | 120 |
kamaki_docs = 'http://www.synnefo.org/docs/kamaki/latest' |
121 |
|
|
111 | 122 |
for k, v in (miss, sgs[miss]) if miss else sgs.items(): |
112 |
if v['active'] and stdout.isatty(): |
|
113 |
print('Suggestion: for better user experience install %s' % k) |
|
114 |
print('\t%s' % v['description']) |
|
115 |
print('\tIt is easy, here are the instructions:') |
|
116 |
print('\t%s/installation.html%s' % (kamaki_docs, v['url'])) |
|
117 |
print('') |
|
123 |
if v['active'] and stderr.isatty(): |
|
124 |
stderr.write('Suggestion: you may like to install %s\n' % k) |
|
125 |
stderr.write('\t%s\n' % encode_for_console(v['description'])) |
|
126 |
stderr.write('\tIt is easy, here are the instructions:\n') |
|
127 |
stderr.write('\t%s/installation.html%s\n' % ( |
|
128 |
kamaki_docs, v['url'])) |
|
129 |
stderr.flush() |
|
118 | 130 |
|
119 | 131 |
|
120 | 132 |
def guess_mime_type( |
... | ... | |
127 | 139 |
ctype, cenc = guess_type(filename) |
128 | 140 |
return ctype or default_content_type, cenc or default_encoding |
129 | 141 |
except ImportError: |
130 |
print 'WARNING: Cannot import mimetypes, using defaults' |
|
142 |
stderr.write('WARNING: Cannot import mimetypes, using defaults\n') |
|
143 |
stderr.flush() |
|
131 | 144 |
return (default_content_type, default_encoding) |
132 | 145 |
|
133 | 146 |
|
... | ... | |
153 | 166 |
return new_d |
154 | 167 |
|
155 | 168 |
|
156 |
def print_json(data, out=stdout): |
|
169 |
def print_json(data, out=stdout, encoding=pref_enc):
|
|
157 | 170 |
"""Print a list or dict as json in console |
158 | 171 |
|
159 | 172 |
:param data: json-dumpable data |
160 | 173 |
|
161 | 174 |
:param out: Input/Output stream to dump values into |
162 | 175 |
""" |
163 |
out.write(unicode(dumps(data, indent=INDENT_TAB) + '\n')) |
|
176 |
s = encode_for_console(dumps(data, indent=INDENT_TAB), encoding) |
|
177 |
out.write(s + '\n') |
|
164 | 178 |
out.flush() |
165 | 179 |
|
166 | 180 |
|
... | ... | |
199 | 213 |
print_str += '%s.' % (i + 1) if with_enumeration else '' |
200 | 214 |
print_str += '%s:' % k |
201 | 215 |
if isinstance(v, dict): |
202 |
out.write(print_str + '\n')
|
|
216 |
out.write(encode_for_console(print_str) + '\n')
|
|
203 | 217 |
print_dict( |
204 | 218 |
v, exclude, indent + INDENT_TAB, |
205 | 219 |
recursive_enumeration, recursive_enumeration, out) |
206 | 220 |
elif isinstance(v, list) or isinstance(v, tuple): |
207 |
out.write(print_str + '\n')
|
|
221 |
out.write(encode_for_console(print_str) + '\n')
|
|
208 | 222 |
print_list( |
209 | 223 |
v, exclude, indent + INDENT_TAB, |
210 | 224 |
recursive_enumeration, recursive_enumeration, out) |
211 | 225 |
else: |
212 |
out.write('%s %s\n' % (print_str, v))
|
|
226 |
out.write(encode_for_console('%s %s\n' % (print_str, v)))
|
|
213 | 227 |
out.flush() |
214 | 228 |
|
215 | 229 |
|
... | ... | |
246 | 260 |
print_str += '%s.' % (i + 1) if with_enumeration else '' |
247 | 261 |
if isinstance(item, dict): |
248 | 262 |
if with_enumeration: |
249 |
out.write(print_str + '\n')
|
|
263 |
out.write(encode_for_console(print_str) + '\n')
|
|
250 | 264 |
elif i and i < len(l): |
251 | 265 |
out.write('\n') |
252 | 266 |
print_dict( |
... | ... | |
255 | 269 |
recursive_enumeration, recursive_enumeration, out) |
256 | 270 |
elif isinstance(item, list) or isinstance(item, tuple): |
257 | 271 |
if with_enumeration: |
258 |
out.write(print_str + '\n')
|
|
272 |
out.write(encode_for_console(print_str) + '\n')
|
|
259 | 273 |
elif i and i < len(l): |
260 | 274 |
out.write('\n') |
261 | 275 |
print_list( |
... | ... | |
265 | 279 |
item = ('%s' % item).strip() |
266 | 280 |
if item in exclude: |
267 | 281 |
continue |
268 |
out.write('%s%s\n' % (print_str, item))
|
|
282 |
out.write(encode_for_console('%s%s\n' % (print_str, item)))
|
|
269 | 283 |
out.flush() |
270 | 284 |
out.flush() |
271 | 285 |
|
... | ... | |
290 | 304 |
return |
291 | 305 |
if not (isinstance(items, dict) or isinstance(items, list) or isinstance( |
292 | 306 |
items, tuple)): |
293 |
out.write('%s\n' % items)
|
|
307 |
out.write(encode_for_console('%s\n' % items))
|
|
294 | 308 |
out.flush() |
295 | 309 |
return |
296 | 310 |
|
297 | 311 |
for i, item in enumerate(items): |
298 | 312 |
if with_enumeration: |
299 |
out.write('%s. ' % (i + 1))
|
|
313 |
out.write(encode_for_console('%s. ' % (i + 1)))
|
|
300 | 314 |
if isinstance(item, dict): |
301 | 315 |
item = dict(item) |
302 | 316 |
title = sorted(set(title).intersection(item)) |
303 | 317 |
pick = item.get if with_redundancy else item.pop |
304 | 318 |
header = ' '.join('%s' % pick(key) for key in title) |
305 |
out.write((unicode(bold(header) if header else '') + '\n')) |
|
319 |
out.write(encode_for_console( |
|
320 |
(unicode(bold(header) if header else '') + '\n'))) |
|
306 | 321 |
print_dict(item, indent=INDENT_TAB, out=out) |
307 | 322 |
elif isinstance(item, list) or isinstance(item, tuple): |
308 | 323 |
print_list(item, indent=INDENT_TAB, out=out) |
309 | 324 |
else: |
310 |
out.write(' %s\n' % item)
|
|
325 |
out.write(encode_for_console(' %s\n' % item))
|
|
311 | 326 |
out.flush() |
312 | 327 |
out.flush() |
313 | 328 |
|
... | ... | |
432 | 447 |
""" |
433 | 448 |
yep = ', '.join(true_resp) |
434 | 449 |
nope = '<not %s>' % yep if 'n' in true_resp or 'N' in true_resp else 'N' |
435 |
out.write('%s [%s/%s]: ' % (msg, yep, nope))
|
|
450 |
out.write(encode_for_console('%s [%s/%s]: ' % (msg, yep, nope)))
|
|
436 | 451 |
out.flush() |
437 | 452 |
user_response = user_in.readline() |
438 | 453 |
return user_response[0].lower() in [s.lower() for s in true_resp] |
Also available in: Unified diff