Revision b6a99832 kamaki/cli/__init__.py
b/kamaki/cli/__init__.py | ||
---|---|---|
47 | 47 |
_colors = False |
48 | 48 |
kloger = None |
49 | 49 |
|
50 |
# command auxiliary methods |
|
51 |
|
|
52 |
_best_match = [] |
|
53 |
|
|
50 | 54 |
|
51 | 55 |
def _construct_command_syntax(cls): |
52 | 56 |
spec = getargspec(cls.main.im_func) |
... | ... | |
67 | 71 |
cls.syntax += ' <%s ...>' % spec.varargs |
68 | 72 |
|
69 | 73 |
|
70 |
def _get_cmd_tree_from_spec(spec, cmd_tree_list): |
|
71 |
for tree in cmd_tree_list: |
|
72 |
if tree.name == spec: |
|
73 |
return tree |
|
74 |
return None |
|
75 |
|
|
76 |
|
|
77 |
_best_match = [] |
|
78 |
|
|
79 |
|
|
80 | 74 |
def _num_of_matching_terms(basic_list, attack_list): |
81 | 75 |
if not attack_list: |
82 | 76 |
return len(basic_list) |
... | ... | |
158 | 152 |
return wrap |
159 | 153 |
|
160 | 154 |
|
161 |
def get_cmd_terms(): |
|
162 |
global command |
|
163 |
return [term for term in command.func_defaults[0]\ |
|
164 |
if not term.startswith('-')] |
|
165 |
|
|
166 | 155 |
cmd_spec_locations = [ |
167 | 156 |
'kamaki.cli.commands', |
168 | 157 |
'kamaki.commands', |
... | ... | |
171 | 160 |
''] |
172 | 161 |
|
173 | 162 |
|
163 |
# Generic init auxiliary functions |
|
164 |
|
|
165 |
|
|
174 | 166 |
def _setup_logging(silent=False, debug=False, verbose=False, include=False): |
175 | 167 |
"""handle logging for clients package""" |
176 | 168 |
|
... | ... | |
190 | 182 |
add_handler('requests', logging.INFO, prefix='* ') |
191 | 183 |
add_handler('clients.send', logging.DEBUG, prefix='> ') |
192 | 184 |
add_handler('clients.recv', logging.DEBUG, prefix='< ') |
193 |
add_handler('kamaki', logging.DEBUG, prefix='DEBUG: ')
|
|
185 |
add_handler('kamaki', logging.DEBUG, prefix='(debug): ')
|
|
194 | 186 |
elif verbose: |
195 | 187 |
add_handler('requests', logging.INFO, prefix='* ') |
196 | 188 |
add_handler('clients.send', logging.INFO, prefix='> ') |
197 | 189 |
add_handler('clients.recv', logging.INFO, prefix='< ') |
198 |
add_handler('kamaki', logging.INFO, prefix='INFO: ')
|
|
190 |
add_handler('kamaki', logging.INFO, prefix='(i): ')
|
|
199 | 191 |
elif include: |
200 | 192 |
add_handler('clients.recv', logging.INFO) |
201 |
add_handler('kamaki', logging.WARNING, prefix='WARNING: ')
|
|
193 |
add_handler('kamaki', logging.WARNING, prefix='(warning): ')
|
|
202 | 194 |
global kloger |
203 |
kloger = logging.getLogger('kamaki.warning')
|
|
195 |
kloger = logging.getLogger('kamaki') |
|
204 | 196 |
|
205 | 197 |
|
206 | 198 |
def _init_session(arguments): |
... | ... | |
220 | 212 |
_setup_logging(_silent, _debug, _verbose, _include) |
221 | 213 |
|
222 | 214 |
|
223 |
def get_command_group(unparsed, arguments): |
|
224 |
groups = arguments['config'].get_groups() |
|
225 |
for term in unparsed: |
|
226 |
if term.startswith('-'): |
|
227 |
continue |
|
228 |
if term in groups: |
|
229 |
unparsed.remove(term) |
|
230 |
return term |
|
231 |
return None |
|
232 |
return None |
|
233 |
|
|
234 |
|
|
235 | 215 |
def _load_spec_module(spec, arguments, module): |
236 | 216 |
spec_name = arguments['config'].get(spec, 'cli') |
237 | 217 |
if spec_name is None: |
... | ... | |
275 | 255 |
print_dict(descriptions) |
276 | 256 |
|
277 | 257 |
|
278 |
def _print_subcommands_help(cmd): |
|
258 |
def _load_all_commands(cmd_tree, arguments): |
|
259 |
_config = arguments['config'] |
|
260 |
for spec in [spec for spec in _config.get_groups()\ |
|
261 |
if _config.get(spec, 'cli')]: |
|
262 |
try: |
|
263 |
spec_module = _load_spec_module(spec, arguments, '_commands') |
|
264 |
spec_commands = getattr(spec_module, '_commands') |
|
265 |
except AttributeError: |
|
266 |
if _debug: |
|
267 |
global kloger |
|
268 |
kloger.warning('No valid description for %s' % spec) |
|
269 |
continue |
|
270 |
for spec_tree in spec_commands: |
|
271 |
if spec_tree.name == spec: |
|
272 |
cmd_tree.add_tree(spec_tree) |
|
273 |
break |
|
274 |
|
|
275 |
|
|
276 |
# Methods to be used by CLI implementations |
|
277 |
|
|
278 |
|
|
279 |
def print_subcommands_help(cmd): |
|
279 | 280 |
printout = {} |
280 | 281 |
for subcmd in cmd.get_subcommands(): |
281 | 282 |
spec, sep, print_path = subcmd.path.partition('_') |
... | ... | |
285 | 286 |
print_dict(printout) |
286 | 287 |
|
287 | 288 |
|
288 |
def _update_parser_help(parser, cmd):
|
|
289 |
def update_parser_help(parser, cmd): |
|
289 | 290 |
global _best_match |
290 | 291 |
parser.syntax = parser.syntax.split('<')[0] |
291 | 292 |
parser.syntax += ' '.join(_best_match) |
... | ... | |
302 | 303 |
parser.parser.description = cmd.help |
303 | 304 |
|
304 | 305 |
|
305 |
def _print_error_message(cli_err):
|
|
306 |
def print_error_message(cli_err): |
|
306 | 307 |
errmsg = '%s' % cli_err |
307 | 308 |
if cli_err.importance == 1: |
308 | 309 |
errmsg = magenta(errmsg) |
... | ... | |
314 | 315 |
print_list(cli_err.details) |
315 | 316 |
|
316 | 317 |
|
317 |
def _get_best_match_from_cmd_tree(cmd_tree, unparsed): |
|
318 |
matched = [term for term in unparsed if not term.startswith('-')] |
|
319 |
while matched: |
|
320 |
try: |
|
321 |
return cmd_tree.get_command('_'.join(matched)) |
|
322 |
except KeyError: |
|
323 |
matched = matched[:-1] |
|
324 |
return None |
|
325 |
|
|
326 |
|
|
327 |
def _exec_cmd(instance, cmd_args, help_method): |
|
318 |
def exec_cmd(instance, cmd_args, help_method): |
|
328 | 319 |
try: |
329 | 320 |
return instance.main(*cmd_args) |
330 | 321 |
except TypeError as err: |
... | ... | |
340 | 331 |
return 1 |
341 | 332 |
|
342 | 333 |
|
334 |
def get_command_group(unparsed, arguments): |
|
335 |
groups = arguments['config'].get_groups() |
|
336 |
for term in unparsed: |
|
337 |
if term.startswith('-'): |
|
338 |
continue |
|
339 |
if term in groups: |
|
340 |
unparsed.remove(term) |
|
341 |
return term |
|
342 |
return None |
|
343 |
return None |
|
344 |
|
|
345 |
|
|
343 | 346 |
def set_command_params(parameters): |
344 | 347 |
"""Add a parameters list to a command |
345 | 348 |
|
... | ... | |
351 | 354 |
command.func_defaults = tuple(def_params) |
352 | 355 |
|
353 | 356 |
|
354 |
#def one_cmd(parser, unparsed, arguments): |
|
355 |
def one_cmd(parser): |
|
356 |
group = get_command_group(list(parser.unparsed), parser.arguments) |
|
357 |
if not group: |
|
358 |
parser.parser.print_help() |
|
359 |
_groups_help(parser.arguments) |
|
360 |
exit(0) |
|
361 |
|
|
362 |
nonargs = [term for term in parser.unparsed if not term.startswith('-')] |
|
363 |
set_command_params(nonargs) |
|
364 |
|
|
365 |
global _best_match |
|
366 |
_best_match = [] |
|
367 |
|
|
368 |
spec_module = _load_spec_module(group, parser.arguments, '_commands') |
|
369 |
|
|
370 |
cmd_tree = _get_cmd_tree_from_spec(group, spec_module._commands) |
|
371 |
|
|
372 |
if _best_match: |
|
373 |
cmd = cmd_tree.get_command('_'.join(_best_match)) |
|
374 |
else: |
|
375 |
cmd = _get_best_match_from_cmd_tree(cmd_tree, parser.unparsed) |
|
376 |
_best_match = cmd.path.split('_') |
|
377 |
if cmd is None: |
|
378 |
if _debug or _verbose: |
|
379 |
print('Unexpected error: failed to load command') |
|
380 |
exit(1) |
|
381 |
|
|
382 |
_update_parser_help(parser, cmd) |
|
383 |
|
|
384 |
if _help or not cmd.is_command: |
|
385 |
parser.parser.print_help() |
|
386 |
_print_subcommands_help(cmd) |
|
387 |
exit(0) |
|
388 |
|
|
389 |
cls = cmd.get_class() |
|
390 |
executable = cls(parser.arguments) |
|
391 |
parser.update_arguments(executable.arguments) |
|
392 |
#parsed, unparsed = parse_known_args(parser, executable.arguments) |
|
393 |
for term in _best_match: |
|
394 |
parser.unparsed.remove(term) |
|
395 |
_exec_cmd(executable, parser.unparsed, parser.parser.print_help) |
|
396 |
|
|
357 |
# CLI Choice: |
|
397 | 358 |
|
398 |
def _load_all_commands(cmd_tree, arguments): |
|
399 |
_config = arguments['config'] |
|
400 |
for spec in [spec for spec in _config.get_groups()\ |
|
401 |
if _config.get(spec, 'cli')]: |
|
402 |
try: |
|
403 |
spec_module = _load_spec_module(spec, arguments, '_commands') |
|
404 |
spec_commands = getattr(spec_module, '_commands') |
|
405 |
except AttributeError: |
|
406 |
if _debug: |
|
407 |
global kloger |
|
408 |
kloger.warning('No valid description for %s' % spec) |
|
409 |
continue |
|
410 |
for spec_tree in spec_commands: |
|
411 |
if spec_tree.name == spec: |
|
412 |
cmd_tree.add_tree(spec_tree) |
|
413 |
break |
|
359 |
def run_one_cmd(exe_string, parser): |
|
360 |
global _history |
|
361 |
_history = History( |
|
362 |
parser.arguments['config'].get('history', 'file')) |
|
363 |
_history.add(' '.join([exe_string] + argv[1:])) |
|
364 |
from kamaki.cli import one_command |
|
365 |
one_command.run(parser, _help) |
|
414 | 366 |
|
415 | 367 |
|
416 | 368 |
def run_shell(exe_string, parser): |
... | ... | |
431 | 383 |
_init_session(parser.arguments) |
432 | 384 |
|
433 | 385 |
if parser.unparsed: |
434 |
_history = History( |
|
435 |
parser.arguments['config'].get('history', 'file')) |
|
436 |
_history.add(' '.join([exe] + argv[1:])) |
|
437 |
one_cmd(parser) |
|
386 |
run_one_cmd(exe, parser) |
|
438 | 387 |
elif _help: |
439 | 388 |
parser.parser.print_help() |
440 | 389 |
_groups_help(parser.arguments) |
441 | 390 |
else: |
442 | 391 |
run_shell(exe, parser) |
443 | 392 |
except CLIError as err: |
444 |
_print_error_message(err)
|
|
393 |
print_error_message(err) |
|
445 | 394 |
if _debug: |
446 | 395 |
raise err |
447 | 396 |
exit(1) |
Also available in: Unified diff