Revision b6a99832
b/docs/installation.rst | ||
---|---|---|
162 | 162 |
Requirements |
163 | 163 |
^^^^^^^^^^^^ |
164 | 164 |
|
165 |
* Python 2.7 or better (Official versions `here <http://www.python.org/getit>`_)
|
|
165 |
* Python 2.7 or better (`Official versions <http://www.python.org/getit>`_)
|
|
166 | 166 |
|
167 | 167 |
* Git (download `windows version <http://git-scm.com/download/win>`_) |
168 | 168 |
|
169 |
* Setuptools (Official versions and workarrounds `here <http://pypi.python.org/pypi/setuptools>`_)
|
|
169 |
* Setuptools (`Official versions and workarounds <http://pypi.python.org/pypi/setuptools>`_)
|
|
170 | 170 |
|
171 | 171 |
Installation from source |
172 | 172 |
^^^^^^^^^^^^^^^^^^^^^^^^ |
... | ... | |
185 | 185 |
|
186 | 186 |
* Select **System** from the Control Panel, select the **Advanced** tab, the **Environment Variables** button and then find the **PATH** (user or system) and **edit** |
187 | 187 |
|
188 |
* Without removing existing values, append the following to PATH: |
|
188 |
* Without removing existing values, append the following to PATH::
|
|
189 | 189 |
|
190 | 190 |
C:\Python;C:\Python\Scripts |
191 | 191 |
|
192 |
.. note:: Path values are separated by a semicolons
|
|
192 |
.. note:: Path values are separated by semicolons
|
|
193 | 193 |
|
194 |
.. warning:: C:\Python should be replaced with the actual python path in the system, e.g. C:\Python27
|
|
194 |
.. warning:: C:\\Python should be replaced with the actual python path in the system, e.g. C:\\Python27
|
|
195 | 195 |
|
196 | 196 |
Install setuptools |
197 | 197 |
"""""""""""""""""" |
198 | 198 |
|
199 |
According to the corresponding `python.org page <http://pypi.python.org/pypi/setuptools>`_, the setuptools installer doesn't currently work on 64bit machines.
|
|
199 |
According to the corresponding `python org page <http://pypi.python.org/pypi/setuptools>`_, the setuptools installer doesn't currently work on 64bit machines.
|
|
200 | 200 |
|
201 | 201 |
* Users with 32-bit operating systems should download and run the graphic installer |
202 | 202 |
|
203 |
* Users with 64-bit machines should download the `ez_setup.py <http://peak.telecommunity.com/dist/ez_setup.py>`_ script and install it from a command shell. In the following, the script is downloaded at C:\Downloads::
|
|
203 |
* Users with 64-bit machines should download the `ez_setup.py <http://peak.telecommunity.com/dist/ez_setup.py>`_ script and install it from a command shell. In the following example, the script was downloaded at C:\\Downloads::
|
|
204 | 204 |
|
205 | 205 |
C:\> cd Downloads |
206 | 206 |
C:\Downloads\> python ez_setup.py |
... | ... | |
211 | 211 |
Install GIT |
212 | 212 |
""""""""""" |
213 | 213 |
|
214 |
Download GIT from `here <http://git-scm.com/download/win>`_ and run the graphic installer. During the installation, users will be able to modify some installation options. The present guide is tested with the default selections.
|
|
214 |
`Download GIT <http://git-scm.com/download/win>`_ and run the graphic installer. During the installation, users will be able to modify some installation options. The present guide is tested with the default selections.
|
|
215 | 215 |
|
216 | 216 |
After the installation is completed, a GIT standalone shell will be installed (a desktop shortcut is created, by default). Users are advised to run kamaki through this shell. |
217 | 217 |
|
... | ... | |
220 | 220 |
|
221 | 221 |
* Run the GIT standalone shell |
222 | 222 |
|
223 |
* Enter the location where kamaki will be installed, e.g. *C\:*
|
|
223 |
* Enter the location where kamaki will be installed, e.g. **C:\\**
|
|
224 | 224 |
|
225 |
.. code-block:: console |
|
225 |
.. code-block:: console
|
|
226 | 226 |
|
227 |
$ cd /c/ |
|
227 |
$ cd /c/
|
|
228 | 228 |
|
229 | 229 |
* Download source from GRNET repository |
230 | 230 |
|
231 |
.. code-block:: console |
|
231 |
.. code-block:: console
|
|
232 | 232 |
|
233 |
$ git clone http://code.grnet.gr/git/kamaki |
|
234 |
Cloning into 'kamaki'... |
|
235 |
Receiving objects: ... |
|
236 |
Resolving Deltas: ... |
|
233 |
$ git clone http://code.grnet.gr/git/kamaki
|
|
234 |
Cloning into 'kamaki'...
|
|
235 |
Receiving objects: ...
|
|
236 |
Resolving Deltas: ...
|
|
237 | 237 |
|
238 | 238 |
* Enter source and install kamaki |
239 | 239 |
|
240 |
.. code-block:: console |
|
240 |
.. code-block:: console
|
|
241 | 241 |
|
242 |
$ cd kamaki |
|
243 |
$ python setup.py install |
|
244 |
running install |
|
245 |
... |
|
246 |
Finished processing dependencies for kamaki==0.6.2 |
|
242 |
$ cd kamaki
|
|
243 |
$ python setup.py install
|
|
244 |
running install
|
|
245 |
...
|
|
246 |
Finished processing dependencies for kamaki==0.6.2
|
|
247 | 247 |
|
248 | 248 |
.. warning:: kamaki version should be 0.6.2 or better, otherwise it will not function. Users can test that by running:: |
249 | 249 |
|
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) |
b/kamaki/cli/argument.py | ||
---|---|---|
45 | 45 |
# progress not installed - pls, pip install progress |
46 | 46 |
pass |
47 | 47 |
|
48 |
kloger = getLogger('kamaki.warning')
|
|
48 |
kloger = getLogger('kamaki') |
|
49 | 49 |
|
50 | 50 |
|
51 | 51 |
class Argument(object): |
b/kamaki/cli/command_shell.py | ||
---|---|---|
35 | 35 |
from os import popen |
36 | 36 |
from sys import stdout |
37 | 37 |
|
38 |
from kamaki.cli import _exec_cmd, _print_error_message
|
|
38 |
from kamaki.cli import exec_cmd, print_error_message, print_subcommands_help
|
|
39 | 39 |
from kamaki.cli.argument import ArgumentParseManager |
40 |
from kamaki.cli.utils import print_dict, split_input, print_items
|
|
40 |
from kamaki.cli.utils import print_dict, split_input |
|
41 | 41 |
from kamaki.cli.history import History |
42 | 42 |
from kamaki.cli.errors import CLIError |
43 | 43 |
from kamaki.clients import ClientError |
... | ... | |
189 | 189 |
arg.value = getattr(cmd_parser.parsed, name, arg.default) |
190 | 190 |
|
191 | 191 |
try: |
192 |
_exec_cmd(instance,
|
|
192 |
exec_cmd(instance, |
|
193 | 193 |
cmd_parser.unparsed, |
194 | 194 |
cmd_parser.parser.print_help) |
195 | 195 |
except (ClientError, CLIError) as err: |
196 |
_print_error_message(err)
|
|
196 |
print_error_message(err) |
|
197 | 197 |
elif ('-h' in cmd_args or '--help' in cmd_args) \ |
198 | 198 |
or len(cmd_args): # print options |
199 |
print('%s: %s' % (cmd.name, subcmd.help)) |
|
200 |
options = {} |
|
201 |
for sub in subcmd.get_subcommands(): |
|
202 |
options[sub.name] = sub.help |
|
203 |
print_dict(options) |
|
199 |
print_subcommands_help(cmd) |
|
204 | 200 |
else: # change context |
205 | 201 |
#new_context = this |
206 | 202 |
backup_context = self._backup() |
... | ... | |
233 | 229 |
break |
234 | 230 |
print('Syntax: %s %s' % (' '.join(clist[upto:]), cls.syntax)) |
235 | 231 |
else: |
236 |
options = dict(name='Options:') |
|
237 |
for sub in cmd.get_subcommands(): |
|
238 |
options[sub.name] = sub.help |
|
239 |
print_items([options]) |
|
232 |
print_subcommands_help(cmd) |
|
240 | 233 |
|
241 | 234 |
self._register_method(help_method, 'help_%s' % cmd.name) |
242 | 235 |
|
b/kamaki/cli/commands/history_cli.py | ||
---|---|---|
39 | 39 |
from kamaki.cli.history import History |
40 | 40 |
from kamaki.cli import command |
41 | 41 |
from kamaki.cli.commands import _command_init |
42 |
from kamaki.cli import _exec_cmd, _print_error_message
|
|
42 |
from kamaki.cli import exec_cmd, print_error_message
|
|
43 | 43 |
from kamaki.cli.errors import CLIError, CLISyntaxError, raiseCLIError |
44 | 44 |
from kamaki.cli.utils import split_input |
45 | 45 |
from kamaki.clients import ClientError |
... | ... | |
145 | 145 |
prs.syntax = '%s %s' % (cmd.path.replace('_', ' '), |
146 | 146 |
cmd.get_class().syntax) |
147 | 147 |
prs.parse(args) |
148 |
_exec_cmd(instance, prs.unparsed, prs.parser.print_help)
|
|
148 |
exec_cmd(instance, prs.unparsed, prs.parser.print_help) |
|
149 | 149 |
except (CLIError, ClientError) as err: |
150 |
_print_error_message(err)
|
|
150 |
print_error_message(err) |
|
151 | 151 |
except Exception as e: |
152 | 152 |
print('Execution of [ %s ] failed' % line) |
153 | 153 |
print('\t%s' % e) |
b/kamaki/cli/commands/test_cli.py | ||
---|---|---|
40 | 40 |
_commands = [test_cmds] |
41 | 41 |
|
42 | 42 |
|
43 |
#print('Command Terms: ', get_cmd_terms()) |
|
44 |
|
|
45 |
|
|
46 | 43 |
class _test_init(_command_init): |
47 | 44 |
|
48 | 45 |
def main(self, client, method=None): |
b/kamaki/cli/one_command.py | ||
---|---|---|
1 |
# Copyright 2012-2013 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.command |
|
33 |
|
|
34 |
from logging import getLogger |
|
35 |
|
|
36 |
from kamaki.cli import get_command_group, set_command_params |
|
37 |
from kamaki.cli import print_subcommands_help, exec_cmd, update_parser_help |
|
38 |
from kamaki.cli import _groups_help, _load_spec_module |
|
39 |
|
|
40 |
|
|
41 |
kloger = getLogger('kamaki') |
|
42 |
|
|
43 |
|
|
44 |
def _get_cmd_tree_from_spec(spec, cmd_tree_list): |
|
45 |
for tree in cmd_tree_list: |
|
46 |
if tree.name == spec: |
|
47 |
return tree |
|
48 |
return None |
|
49 |
|
|
50 |
|
|
51 |
def _get_best_match_from_cmd_tree(cmd_tree, unparsed): |
|
52 |
matched = [term for term in unparsed if not term.startswith('-')] |
|
53 |
while matched: |
|
54 |
try: |
|
55 |
return cmd_tree.get_command('_'.join(matched)) |
|
56 |
except KeyError: |
|
57 |
matched = matched[:-1] |
|
58 |
return None |
|
59 |
|
|
60 |
|
|
61 |
def run(parser, _help): |
|
62 |
group = get_command_group(list(parser.unparsed), parser.arguments) |
|
63 |
if not group: |
|
64 |
parser.parser.print_help() |
|
65 |
_groups_help(parser.arguments) |
|
66 |
exit(0) |
|
67 |
|
|
68 |
nonargs = [term for term in parser.unparsed if not term.startswith('-')] |
|
69 |
set_command_params(nonargs) |
|
70 |
|
|
71 |
global _best_match |
|
72 |
_best_match = [] |
|
73 |
|
|
74 |
spec_module = _load_spec_module(group, parser.arguments, '_commands') |
|
75 |
|
|
76 |
cmd_tree = _get_cmd_tree_from_spec(group, spec_module._commands) |
|
77 |
|
|
78 |
if _best_match: |
|
79 |
cmd = cmd_tree.get_command('_'.join(_best_match)) |
|
80 |
else: |
|
81 |
cmd = _get_best_match_from_cmd_tree(cmd_tree, parser.unparsed) |
|
82 |
_best_match = cmd.path.split('_') |
|
83 |
if cmd is None: |
|
84 |
kloger.info( |
|
85 |
'Unexpected error: failed to load command (-d for details)') |
|
86 |
exit(1) |
|
87 |
|
|
88 |
update_parser_help(parser, cmd) |
|
89 |
|
|
90 |
if _help or not cmd.is_command: |
|
91 |
parser.parser.print_help() |
|
92 |
print_subcommands_help(cmd) |
|
93 |
exit(0) |
|
94 |
|
|
95 |
cls = cmd.get_class() |
|
96 |
executable = cls(parser.arguments) |
|
97 |
parser.update_arguments(executable.arguments) |
|
98 |
#parsed, unparsed = parse_known_args(parser, executable.arguments) |
|
99 |
for term in _best_match: |
|
100 |
parser.unparsed.remove(term) |
|
101 |
exec_cmd(executable, parser.unparsed, parser.parser.print_help) |
Also available in: Unified diff