Statistics
| Branch: | Tag: | Revision:

root / kamaki / cli / __init__.py @ d88ba587

History | View | Annotate | Download (13.3 kB)

1 d486baec Stavros Sachtouris
# Copyright 2012-2013 GRNET S.A. All rights reserved.
2 7493ccb6 Stavros Sachtouris
#
3 7493ccb6 Stavros Sachtouris
# Redistribution and use in source and binary forms, with or
4 7493ccb6 Stavros Sachtouris
# without modification, are permitted provided that the following
5 7493ccb6 Stavros Sachtouris
# conditions are met:
6 7493ccb6 Stavros Sachtouris
#
7 7493ccb6 Stavros Sachtouris
#   1. Redistributions of source code must retain the above
8 fd5db045 Stavros Sachtouris
#      copyright notice, this list of conditions and the following
9 fd5db045 Stavros Sachtouris
#      disclaimer.
10 7493ccb6 Stavros Sachtouris
#
11 7493ccb6 Stavros Sachtouris
#   2. Redistributions in binary form must reproduce the above
12 fd5db045 Stavros Sachtouris
#      copyright notice, this list of conditions and the following
13 fd5db045 Stavros Sachtouris
#      disclaimer in the documentation and/or other materials
14 fd5db045 Stavros Sachtouris
#      provided with the distribution.
15 7493ccb6 Stavros Sachtouris
#
16 7493ccb6 Stavros Sachtouris
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 7493ccb6 Stavros Sachtouris
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 7493ccb6 Stavros Sachtouris
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 7493ccb6 Stavros Sachtouris
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 7493ccb6 Stavros Sachtouris
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 7493ccb6 Stavros Sachtouris
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 7493ccb6 Stavros Sachtouris
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 7493ccb6 Stavros Sachtouris
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 7493ccb6 Stavros Sachtouris
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 7493ccb6 Stavros Sachtouris
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 7493ccb6 Stavros Sachtouris
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 7493ccb6 Stavros Sachtouris
# POSSIBILITY OF SUCH DAMAGE.
28 7493ccb6 Stavros Sachtouris
#
29 7493ccb6 Stavros Sachtouris
# The views and conclusions contained in the software and
30 7493ccb6 Stavros Sachtouris
# documentation are those of the authors and should not be
31 7493ccb6 Stavros Sachtouris
# interpreted as representing official policies, either expressed
32 d486baec Stavros Sachtouris
# or implied, of GRNET S.A.command
33 7493ccb6 Stavros Sachtouris
34 7493ccb6 Stavros Sachtouris
import logging
35 d486baec Stavros Sachtouris
from sys import argv, exit, stdout
36 f3e94e06 Stavros Sachtouris
from os.path import basename
37 d486baec Stavros Sachtouris
from inspect import getargspec
38 3dabe5d2 Stavros Sachtouris
39 d486baec Stavros Sachtouris
from kamaki.cli.argument import _arguments, parse_known_args, init_parser,\
40 d486baec Stavros Sachtouris
    update_arguments
41 fd5db045 Stavros Sachtouris
from kamaki.cli.history import History
42 d486baec Stavros Sachtouris
from kamaki.cli.utils import print_dict, print_list, red, magenta, yellow
43 d486baec Stavros Sachtouris
from kamaki.cli.errors import CLIError
44 7493ccb6 Stavros Sachtouris
45 d486baec Stavros Sachtouris
_help = False
46 d486baec Stavros Sachtouris
_debug = False
47 d486baec Stavros Sachtouris
_verbose = False
48 d486baec Stavros Sachtouris
_colors = False
49 fd5db045 Stavros Sachtouris
50 fd5db045 Stavros Sachtouris
51 d486baec Stavros Sachtouris
def _construct_command_syntax(cls):
52 fd5db045 Stavros Sachtouris
        spec = getargspec(cls.main.im_func)
53 fd5db045 Stavros Sachtouris
        args = spec.args[1:]
54 fd5db045 Stavros Sachtouris
        n = len(args) - len(spec.defaults or ())
55 fd5db045 Stavros Sachtouris
        required = ' '.join('<%s>' % x\
56 fd5db045 Stavros Sachtouris
            .replace('____', '[:')\
57 fd5db045 Stavros Sachtouris
            .replace('___', ':')\
58 fd5db045 Stavros Sachtouris
            .replace('__', ']').\
59 fd5db045 Stavros Sachtouris
            replace('_', ' ') for x in args[:n])
60 fd5db045 Stavros Sachtouris
        optional = ' '.join('[%s]' % x\
61 fd5db045 Stavros Sachtouris
            .replace('____', '[:')\
62 fd5db045 Stavros Sachtouris
            .replace('___', ':')\
63 fd5db045 Stavros Sachtouris
            .replace('__', ']').\
64 fd5db045 Stavros Sachtouris
            replace('_', ' ') for x in args[n:])
65 fd5db045 Stavros Sachtouris
        cls.syntax = ' '.join(x for x in [required, optional] if x)
66 fd5db045 Stavros Sachtouris
        if spec.varargs:
67 fd5db045 Stavros Sachtouris
            cls.syntax += ' <%s ...>' % spec.varargs
68 fd5db045 Stavros Sachtouris
69 fd5db045 Stavros Sachtouris
70 d486baec Stavros Sachtouris
def _get_cmd_tree_from_spec(spec, cmd_tree_list):
71 d486baec Stavros Sachtouris
    for tree in cmd_tree_list:
72 d486baec Stavros Sachtouris
        if tree.name == spec:
73 d486baec Stavros Sachtouris
            return tree
74 d486baec Stavros Sachtouris
    return None
75 73e0914d Stavros Sachtouris
76 7493ccb6 Stavros Sachtouris
77 d486baec Stavros Sachtouris
_best_match = []
78 fd5db045 Stavros Sachtouris
79 c41a86b2 Stavros Sachtouris
80 d486baec Stavros Sachtouris
def _num_of_matching_terms(basic_list, attack_list):
81 d486baec Stavros Sachtouris
    if not attack_list:
82 75c3fc42 Stavros Sachtouris
        return len(basic_list)
83 fd5db045 Stavros Sachtouris
84 d486baec Stavros Sachtouris
    matching_terms = 0
85 d486baec Stavros Sachtouris
    for i, term in enumerate(basic_list):
86 d486baec Stavros Sachtouris
        try:
87 d486baec Stavros Sachtouris
            if term != attack_list[i]:
88 d486baec Stavros Sachtouris
                break
89 d486baec Stavros Sachtouris
        except IndexError:
90 d486baec Stavros Sachtouris
            break
91 d486baec Stavros Sachtouris
        matching_terms += 1
92 d486baec Stavros Sachtouris
    return matching_terms
93 dfee2caf Stavros Sachtouris
94 fd5db045 Stavros Sachtouris
95 d486baec Stavros Sachtouris
def _update_best_match(name_terms, prefix=[]):
96 d486baec Stavros Sachtouris
    if prefix:
97 d486baec Stavros Sachtouris
        pref_list = prefix if isinstance(prefix, list) else prefix.split('_')
98 d486baec Stavros Sachtouris
    else:
99 d486baec Stavros Sachtouris
        pref_list = []
100 dfee2caf Stavros Sachtouris
101 d486baec Stavros Sachtouris
    num_of_matching_terms = _num_of_matching_terms(name_terms, pref_list)
102 d486baec Stavros Sachtouris
    global _best_match
103 e9533b0c Stavros Sachtouris
    if not prefix:
104 e9533b0c Stavros Sachtouris
        _best_match = []
105 fd5db045 Stavros Sachtouris
106 d486baec Stavros Sachtouris
    if num_of_matching_terms and len(_best_match) <= num_of_matching_terms:
107 d486baec Stavros Sachtouris
        if len(_best_match) < num_of_matching_terms:
108 d486baec Stavros Sachtouris
            _best_match = name_terms[:num_of_matching_terms]
109 d486baec Stavros Sachtouris
        return True
110 d486baec Stavros Sachtouris
    return False
111 d486baec Stavros Sachtouris
112 d486baec Stavros Sachtouris
113 d486baec Stavros Sachtouris
def command(cmd_tree, prefix='', descedants_depth=1):
114 d486baec Stavros Sachtouris
    """Load a class as a command
115 d486baec Stavros Sachtouris
        spec_cmd0_cmd1 will be command spec cmd0
116 d486baec Stavros Sachtouris
        @cmd_tree is initialized in cmd_spec file and is the structure
117 d486baec Stavros Sachtouris
            where commands are loaded. Var name should be _commands
118 d486baec Stavros Sachtouris
        @param prefix if given, load only commands prefixed with prefix,
119 d486baec Stavros Sachtouris
        @param descedants_depth is the depth of the tree descedants of the
120 d486baec Stavros Sachtouris
            prefix command. It is used ONLY if prefix and if prefix is not
121 d486baec Stavros Sachtouris
            a terminal command
122 d486baec Stavros Sachtouris
    """
123 d486baec Stavros Sachtouris
124 d486baec Stavros Sachtouris
    def wrap(cls):
125 d486baec Stavros Sachtouris
        cls_name = cls.__name__
126 d486baec Stavros Sachtouris
127 d486baec Stavros Sachtouris
        if not cmd_tree:
128 d486baec Stavros Sachtouris
            if _debug:
129 d486baec Stavros Sachtouris
                print('Warning: command %s found but not loaded' % cls_name)
130 d486baec Stavros Sachtouris
            return cls
131 0b368c8c Stavros Sachtouris
132 d486baec Stavros Sachtouris
        name_terms = cls_name.split('_')
133 d486baec Stavros Sachtouris
        if not _update_best_match(name_terms, prefix):
134 e9533b0c Stavros Sachtouris
            if _debug:
135 e9533b0c Stavros Sachtouris
                print('Warning: %s failed to update_best_match' % cls_name)
136 d486baec Stavros Sachtouris
            return None
137 fd5db045 Stavros Sachtouris
138 d486baec Stavros Sachtouris
        global _best_match
139 d486baec Stavros Sachtouris
        max_len = len(_best_match) + descedants_depth
140 d486baec Stavros Sachtouris
        if len(name_terms) > max_len:
141 d486baec Stavros Sachtouris
            partial = '_'.join(name_terms[:max_len])
142 d486baec Stavros Sachtouris
            if not cmd_tree.has_command(partial):  # add partial path
143 d486baec Stavros Sachtouris
                cmd_tree.add_command(partial)
144 e9533b0c Stavros Sachtouris
            if _debug:
145 e9533b0c Stavros Sachtouris
                print('Warning: %s failed max_len test' % cls_name)
146 d486baec Stavros Sachtouris
            return None
147 fd5db045 Stavros Sachtouris
148 d486baec Stavros Sachtouris
        cls.description, sep, cls.long_description\
149 d486baec Stavros Sachtouris
        = cls.__doc__.partition('\n')
150 d486baec Stavros Sachtouris
        _construct_command_syntax(cls)
151 0b368c8c Stavros Sachtouris
152 d486baec Stavros Sachtouris
        cmd_tree.add_command(cls_name, cls.description, cls)
153 d486baec Stavros Sachtouris
        return cls
154 d486baec Stavros Sachtouris
    return wrap
155 fd5db045 Stavros Sachtouris
156 0b368c8c Stavros Sachtouris
157 d486baec Stavros Sachtouris
def get_cmd_terms():
158 d486baec Stavros Sachtouris
    global command
159 d486baec Stavros Sachtouris
    return [term for term in command.func_defaults[0]\
160 d486baec Stavros Sachtouris
        if not term.startswith('-')]
161 d486baec Stavros Sachtouris
162 d486baec Stavros Sachtouris
cmd_spec_locations = [
163 d486baec Stavros Sachtouris
    'kamaki.cli.commands',
164 d486baec Stavros Sachtouris
    'kamaki.commands',
165 d486baec Stavros Sachtouris
    'kamaki.cli',
166 d486baec Stavros Sachtouris
    'kamaki',
167 d486baec Stavros Sachtouris
    '']
168 fd5db045 Stavros Sachtouris
169 0b368c8c Stavros Sachtouris
170 d486baec Stavros Sachtouris
def _setup_logging(silent=False, debug=False, verbose=False, include=False):
171 fd5db045 Stavros Sachtouris
    """handle logging for clients package"""
172 fd5db045 Stavros Sachtouris
173 fd5db045 Stavros Sachtouris
    def add_handler(name, level, prefix=''):
174 fd5db045 Stavros Sachtouris
        h = logging.StreamHandler()
175 fd5db045 Stavros Sachtouris
        fmt = logging.Formatter(prefix + '%(message)s')
176 fd5db045 Stavros Sachtouris
        h.setFormatter(fmt)
177 fd5db045 Stavros Sachtouris
        logger = logging.getLogger(name)
178 fd5db045 Stavros Sachtouris
        logger.addHandler(h)
179 fd5db045 Stavros Sachtouris
        logger.setLevel(level)
180 fd5db045 Stavros Sachtouris
181 fd5db045 Stavros Sachtouris
    if silent:
182 fd5db045 Stavros Sachtouris
        add_handler('', logging.CRITICAL)
183 fd5db045 Stavros Sachtouris
    elif debug:
184 fd5db045 Stavros Sachtouris
        add_handler('requests', logging.INFO, prefix='* ')
185 fd5db045 Stavros Sachtouris
        add_handler('clients.send', logging.DEBUG, prefix='> ')
186 fd5db045 Stavros Sachtouris
        add_handler('clients.recv', logging.DEBUG, prefix='< ')
187 fd5db045 Stavros Sachtouris
    elif verbose:
188 fd5db045 Stavros Sachtouris
        add_handler('requests', logging.INFO, prefix='* ')
189 fd5db045 Stavros Sachtouris
        add_handler('clients.send', logging.INFO, prefix='> ')
190 fd5db045 Stavros Sachtouris
        add_handler('clients.recv', logging.INFO, prefix='< ')
191 fd5db045 Stavros Sachtouris
    elif include:
192 fd5db045 Stavros Sachtouris
        add_handler('clients.recv', logging.INFO)
193 fd5db045 Stavros Sachtouris
    else:
194 fd5db045 Stavros Sachtouris
        add_handler('', logging.WARNING)
195 fd5db045 Stavros Sachtouris
196 ce48608f Stavros Sachtouris
197 d486baec Stavros Sachtouris
def _init_session(arguments):
198 d486baec Stavros Sachtouris
    global _help
199 d486baec Stavros Sachtouris
    _help = arguments['help'].value
200 d486baec Stavros Sachtouris
    global _debug
201 d486baec Stavros Sachtouris
    _debug = arguments['debug'].value
202 d486baec Stavros Sachtouris
    global _verbose
203 d486baec Stavros Sachtouris
    _verbose = arguments['verbose'].value
204 d486baec Stavros Sachtouris
    global _colors
205 d486baec Stavros Sachtouris
    _colors = arguments['config'].get('global', 'colors')
206 87565d2c Stavros Sachtouris
    if not (stdout.isatty() and _colors == 'on'):
207 4f6a21f6 Stavros Sachtouris
        from kamaki.cli.utils import remove_colors
208 4f6a21f6 Stavros Sachtouris
        remove_colors()
209 d486baec Stavros Sachtouris
    _silent = arguments['silent'].value
210 d486baec Stavros Sachtouris
    _include = arguments['include'].value
211 d486baec Stavros Sachtouris
    _setup_logging(_silent, _debug, _verbose, _include)
212 d486baec Stavros Sachtouris
213 d486baec Stavros Sachtouris
214 d486baec Stavros Sachtouris
def get_command_group(unparsed, arguments):
215 d486baec Stavros Sachtouris
    groups = arguments['config'].get_groups()
216 d486baec Stavros Sachtouris
    for term in unparsed:
217 d486baec Stavros Sachtouris
        if term.startswith('-'):
218 d486baec Stavros Sachtouris
            continue
219 d486baec Stavros Sachtouris
        if term in groups:
220 d486baec Stavros Sachtouris
            unparsed.remove(term)
221 d486baec Stavros Sachtouris
            return term
222 d486baec Stavros Sachtouris
        return None
223 d486baec Stavros Sachtouris
    return None
224 d486baec Stavros Sachtouris
225 d486baec Stavros Sachtouris
226 d486baec Stavros Sachtouris
def _load_spec_module(spec, arguments, module):
227 d486baec Stavros Sachtouris
    spec_name = arguments['config'].get(spec, 'cli')
228 d486baec Stavros Sachtouris
    if spec_name is None:
229 d486baec Stavros Sachtouris
        return None
230 d486baec Stavros Sachtouris
    pkg = None
231 d486baec Stavros Sachtouris
    for location in cmd_spec_locations:
232 d486baec Stavros Sachtouris
        location += spec_name if location == '' else '.%s' % spec_name
233 d486baec Stavros Sachtouris
        try:
234 d486baec Stavros Sachtouris
            pkg = __import__(location, fromlist=[module])
235 d486baec Stavros Sachtouris
            return pkg
236 d486baec Stavros Sachtouris
        except ImportError:
237 d486baec Stavros Sachtouris
            continue
238 d486baec Stavros Sachtouris
    return pkg
239 d486baec Stavros Sachtouris
240 d486baec Stavros Sachtouris
241 d486baec Stavros Sachtouris
def _groups_help(arguments):
242 d486baec Stavros Sachtouris
    global _debug
243 d486baec Stavros Sachtouris
    descriptions = {}
244 d486baec Stavros Sachtouris
    for spec in arguments['config'].get_groups():
245 d486baec Stavros Sachtouris
        pkg = _load_spec_module(spec, arguments, '_commands')
246 d486baec Stavros Sachtouris
        if pkg:
247 d486baec Stavros Sachtouris
            cmds = None
248 d486baec Stavros Sachtouris
            try:
249 d486baec Stavros Sachtouris
                cmds = [
250 d486baec Stavros Sachtouris
                    cmd for cmd in getattr(pkg, '_commands')\
251 d486baec Stavros Sachtouris
                    if arguments['config'].get(cmd.name, 'cli')
252 d486baec Stavros Sachtouris
                ]
253 d486baec Stavros Sachtouris
            except AttributeError:
254 d486baec Stavros Sachtouris
                if _debug:
255 d486baec Stavros Sachtouris
                    print('Warning: No description for %s' % spec)
256 d486baec Stavros Sachtouris
            try:
257 d486baec Stavros Sachtouris
                for cmd in cmds:
258 d486baec Stavros Sachtouris
                    descriptions[cmd.name] = cmd.description
259 d486baec Stavros Sachtouris
            except TypeError:
260 d486baec Stavros Sachtouris
                if _debug:
261 d486baec Stavros Sachtouris
                    print('Warning: no cmd specs in module %s' % spec)
262 d486baec Stavros Sachtouris
        elif _debug:
263 d486baec Stavros Sachtouris
            print('Warning: Loading of %s cmd spec failed' % spec)
264 d486baec Stavros Sachtouris
    print('\nOptions:\n - - - -')
265 d486baec Stavros Sachtouris
    print_dict(descriptions)
266 d486baec Stavros Sachtouris
267 d486baec Stavros Sachtouris
268 d486baec Stavros Sachtouris
def _print_subcommands_help(cmd):
269 d486baec Stavros Sachtouris
    printout = {}
270 d486baec Stavros Sachtouris
    for subcmd in cmd.get_subcommands():
271 4f6a21f6 Stavros Sachtouris
        spec, sep, print_path = subcmd.path.partition('_')
272 4f6a21f6 Stavros Sachtouris
        printout[print_path.replace('_', ' ')] = subcmd.description
273 d486baec Stavros Sachtouris
    if printout:
274 d486baec Stavros Sachtouris
        print('\nOptions:\n - - - -')
275 d486baec Stavros Sachtouris
        print_dict(printout)
276 d486baec Stavros Sachtouris
277 d486baec Stavros Sachtouris
278 d486baec Stavros Sachtouris
def _update_parser_help(parser, cmd):
279 d486baec Stavros Sachtouris
    global _best_match
280 d486baec Stavros Sachtouris
    parser.prog = parser.prog.split('<')[0]
281 d486baec Stavros Sachtouris
    parser.prog += ' '.join(_best_match)
282 d486baec Stavros Sachtouris
283 d486baec Stavros Sachtouris
    if cmd.is_command:
284 d486baec Stavros Sachtouris
        cls = cmd.get_class()
285 d486baec Stavros Sachtouris
        parser.prog += ' ' + cls.syntax
286 d486baec Stavros Sachtouris
        arguments = cls().arguments
287 d486baec Stavros Sachtouris
        update_arguments(parser, arguments)
288 d486baec Stavros Sachtouris
    else:
289 d486baec Stavros Sachtouris
        parser.prog += ' <...>'
290 d486baec Stavros Sachtouris
    if cmd.has_description:
291 d486baec Stavros Sachtouris
        parser.description = cmd.help
292 d486baec Stavros Sachtouris
293 d486baec Stavros Sachtouris
294 d486baec Stavros Sachtouris
def _print_error_message(cli_err):
295 d486baec Stavros Sachtouris
    errmsg = '%s' % cli_err
296 d486baec Stavros Sachtouris
    if cli_err.importance == 1:
297 d486baec Stavros Sachtouris
        errmsg = magenta(errmsg)
298 d486baec Stavros Sachtouris
    elif cli_err.importance == 2:
299 d486baec Stavros Sachtouris
        errmsg = yellow(errmsg)
300 d486baec Stavros Sachtouris
    elif cli_err.importance > 2:
301 d486baec Stavros Sachtouris
        errmsg = red(errmsg)
302 d486baec Stavros Sachtouris
    stdout.write(errmsg)
303 d486baec Stavros Sachtouris
    print_list(cli_err.details)
304 d486baec Stavros Sachtouris
305 d486baec Stavros Sachtouris
306 d486baec Stavros Sachtouris
def _get_best_match_from_cmd_tree(cmd_tree, unparsed):
307 d486baec Stavros Sachtouris
    matched = [term for term in unparsed if not term.startswith('-')]
308 d486baec Stavros Sachtouris
    while matched:
309 d486baec Stavros Sachtouris
        try:
310 d486baec Stavros Sachtouris
            return cmd_tree.get_command('_'.join(matched))
311 d486baec Stavros Sachtouris
        except KeyError:
312 d486baec Stavros Sachtouris
            matched = matched[:-1]
313 d486baec Stavros Sachtouris
    return None
314 d486baec Stavros Sachtouris
315 d486baec Stavros Sachtouris
316 ce48608f Stavros Sachtouris
def _exec_cmd(instance, cmd_args, help_method):
317 fd5db045 Stavros Sachtouris
    try:
318 fd5db045 Stavros Sachtouris
        return instance.main(*cmd_args)
319 fd5db045 Stavros Sachtouris
    except TypeError as err:
320 fd5db045 Stavros Sachtouris
        if err.args and err.args[0].startswith('main()'):
321 fd5db045 Stavros Sachtouris
            print(magenta('Syntax error'))
322 d486baec Stavros Sachtouris
            if _debug:
323 d486baec Stavros Sachtouris
                raise err
324 d486baec Stavros Sachtouris
            if _verbose:
325 fd5db045 Stavros Sachtouris
                print(unicode(err))
326 fd5db045 Stavros Sachtouris
            help_method()
327 fd5db045 Stavros Sachtouris
        else:
328 fd5db045 Stavros Sachtouris
            raise
329 fd5db045 Stavros Sachtouris
    return 1
330 fd5db045 Stavros Sachtouris
331 f247bcb4 Stavros Sachtouris
332 d486baec Stavros Sachtouris
def set_command_param(param, value):
333 d486baec Stavros Sachtouris
    if param == 'prefix':
334 d486baec Stavros Sachtouris
        pos = 0
335 d486baec Stavros Sachtouris
    elif param == 'descedants_depth':
336 d486baec Stavros Sachtouris
        pos = 1
337 d486baec Stavros Sachtouris
    else:
338 d486baec Stavros Sachtouris
        return
339 d486baec Stavros Sachtouris
    global command
340 d486baec Stavros Sachtouris
    def_params = list(command.func_defaults)
341 d486baec Stavros Sachtouris
    def_params[pos] = value
342 d486baec Stavros Sachtouris
    command.func_defaults = tuple(def_params)
343 d486baec Stavros Sachtouris
344 d486baec Stavros Sachtouris
345 d486baec Stavros Sachtouris
def one_cmd(parser, unparsed, arguments):
346 d486baec Stavros Sachtouris
    group = get_command_group(list(unparsed), arguments)
347 d486baec Stavros Sachtouris
    if not group:
348 d486baec Stavros Sachtouris
        parser.print_help()
349 d486baec Stavros Sachtouris
        _groups_help(arguments)
350 d486baec Stavros Sachtouris
        exit(0)
351 d486baec Stavros Sachtouris
352 d486baec Stavros Sachtouris
    set_command_param(
353 d486baec Stavros Sachtouris
        'prefix',
354 d486baec Stavros Sachtouris
        [term for term in unparsed if not term.startswith('-')]
355 d486baec Stavros Sachtouris
    )
356 d486baec Stavros Sachtouris
    global _best_match
357 d486baec Stavros Sachtouris
    _best_match = []
358 d486baec Stavros Sachtouris
359 d486baec Stavros Sachtouris
    spec_module = _load_spec_module(group, arguments, '_commands')
360 d486baec Stavros Sachtouris
361 d486baec Stavros Sachtouris
    cmd_tree = _get_cmd_tree_from_spec(group, spec_module._commands)
362 d486baec Stavros Sachtouris
363 d486baec Stavros Sachtouris
    if _best_match:
364 d486baec Stavros Sachtouris
        cmd = cmd_tree.get_command('_'.join(_best_match))
365 d486baec Stavros Sachtouris
    else:
366 d486baec Stavros Sachtouris
        cmd = _get_best_match_from_cmd_tree(cmd_tree, unparsed)
367 d486baec Stavros Sachtouris
        _best_match = cmd.path.split('_')
368 d486baec Stavros Sachtouris
    if cmd is None:
369 d486baec Stavros Sachtouris
        if _debug or _verbose:
370 d486baec Stavros Sachtouris
            print('Unexpected error: failed to load command')
371 fd5db045 Stavros Sachtouris
        exit(1)
372 fd5db045 Stavros Sachtouris
373 d486baec Stavros Sachtouris
    _update_parser_help(parser, cmd)
374 d486baec Stavros Sachtouris
375 d486baec Stavros Sachtouris
    if _help or not cmd.is_command:
376 d486baec Stavros Sachtouris
        parser.print_help()
377 d486baec Stavros Sachtouris
        _print_subcommands_help(cmd)
378 d486baec Stavros Sachtouris
        exit(0)
379 d486baec Stavros Sachtouris
380 d486baec Stavros Sachtouris
    cls = cmd.get_class()
381 d486baec Stavros Sachtouris
    executable = cls(arguments)
382 d486baec Stavros Sachtouris
    parsed, unparsed = parse_known_args(parser, executable.arguments)
383 d486baec Stavros Sachtouris
    for term in _best_match:
384 d486baec Stavros Sachtouris
        unparsed.remove(term)
385 d486baec Stavros Sachtouris
    _exec_cmd(executable, unparsed, parser.print_help)
386 d486baec Stavros Sachtouris
387 d486baec Stavros Sachtouris
388 d53062bd Stavros Sachtouris
def _load_all_commands(cmd_tree, arguments):
389 75c3fc42 Stavros Sachtouris
    _config = arguments['config']
390 d486baec Stavros Sachtouris
    for spec in [spec for spec in _config.get_groups()\
391 75c3fc42 Stavros Sachtouris
            if _config.get(spec, 'cli')]:
392 d486baec Stavros Sachtouris
        try:
393 d486baec Stavros Sachtouris
            spec_module = _load_spec_module(spec, arguments, '_commands')
394 d486baec Stavros Sachtouris
            spec_commands = getattr(spec_module, '_commands')
395 d486baec Stavros Sachtouris
        except AttributeError:
396 d486baec Stavros Sachtouris
            if _debug:
397 d486baec Stavros Sachtouris
                print('Warning: No valid description for %s' % spec)
398 d486baec Stavros Sachtouris
            continue
399 d486baec Stavros Sachtouris
        for spec_tree in spec_commands:
400 d486baec Stavros Sachtouris
            if spec_tree.name == spec:
401 d53062bd Stavros Sachtouris
                cmd_tree.add_tree(spec_tree)
402 d486baec Stavros Sachtouris
                break
403 d53062bd Stavros Sachtouris
404 d53062bd Stavros Sachtouris
405 d53062bd Stavros Sachtouris
def run_shell(exe_string, arguments):
406 d53062bd Stavros Sachtouris
    from command_shell import _init_shell
407 d53062bd Stavros Sachtouris
    shell = _init_shell(exe_string, arguments)
408 d53062bd Stavros Sachtouris
    _load_all_commands(shell.cmd_tree, arguments)
409 834200da Stavros Sachtouris
    shell.run(arguments)
410 fd5db045 Stavros Sachtouris
411 1c1fd2fa Stavros Sachtouris
412 1c1fd2fa Stavros Sachtouris
def main():
413 71882bca Stavros Sachtouris
    try:
414 71882bca Stavros Sachtouris
        exe = basename(argv[0])
415 71882bca Stavros Sachtouris
        parser = init_parser(exe, _arguments)
416 71882bca Stavros Sachtouris
        parsed, unparsed = parse_known_args(parser, _arguments)
417 71882bca Stavros Sachtouris
418 71882bca Stavros Sachtouris
        if _arguments['version'].value:
419 71882bca Stavros Sachtouris
            exit(0)
420 71882bca Stavros Sachtouris
421 71882bca Stavros Sachtouris
        _init_session(_arguments)
422 71882bca Stavros Sachtouris
423 71882bca Stavros Sachtouris
        if unparsed:
424 71882bca Stavros Sachtouris
            _history = History(_arguments['config'].get('history', 'file'))
425 71882bca Stavros Sachtouris
            _history.add(' '.join([exe] + argv[1:]))
426 71882bca Stavros Sachtouris
            one_cmd(parser, unparsed, _arguments)
427 71882bca Stavros Sachtouris
        elif _help:
428 71882bca Stavros Sachtouris
            parser.print_help()
429 71882bca Stavros Sachtouris
            _groups_help(_arguments)
430 71882bca Stavros Sachtouris
        else:
431 75c3fc42 Stavros Sachtouris
            run_shell(exe, _arguments)
432 71882bca Stavros Sachtouris
    except CLIError as err:
433 71882bca Stavros Sachtouris
        if _debug:
434 71882bca Stavros Sachtouris
            raise err
435 71882bca Stavros Sachtouris
        _print_error_message(err)
436 71882bca Stavros Sachtouris
        exit(1)
437 71882bca Stavros Sachtouris
    except Exception as err:
438 71882bca Stavros Sachtouris
        if _debug:
439 71882bca Stavros Sachtouris
            raise err
440 71882bca Stavros Sachtouris
        print('Unknown Error: %s' % err)