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