Revision 017d37ce

b/kamaki/cli/__init__.py
53 53
    from ordereddict import OrderedDict
54 54

  
55 55
#from kamaki import clients
56
from .errors import CLIError
56
from .errors import CLIError, CLISyntaxError, CLICmdIncompleteError
57 57
from .config import Config #TO BE REMOVED
58
from .utils import magenta, red, yellow, CommandTree
58
from .utils import bold, magenta, red, yellow, CommandTree, print_list
59 59
from argument import _arguments, parse_known_args
60 60

  
61 61
_commands = CommandTree()
62 62

  
63
GROUPS={}
64
CLI_LOCATIONS = ['kamaki.cli.commands', 'kamaki.commands', 'kamaki.cli', 'kamaki', '']
63
#basic command groups
65 64

  
66 65
def command():
67 66
    """Class decorator that registers a class as a CLI command"""
......
112 111
    else:
113 112
        print
114 113

  
114
def _expand_cmd(cmd_prefix, unparsed):
115
    if len(unparsed) == 0:
116
        return None
117
    prefix = (cmd_prefix+'_') if len(cmd_prefix) > 0 else ''
118
    for term in _commands.list(cmd_prefix):
119
        try:
120
            unparsed.remove(term)
121
        except ValueError:
122
            continue
123
        return prefix+term
124
    return None
125

  
126
def _retrieve_cmd(unparsed):
127
    cmd_str = None
128
    cur_cmd = _expand_cmd('', unparsed)
129
    while cur_cmd is not None:
130
        cmd_str = cur_cmd
131
        cur_cmd = _expand_cmd(cur_cmd, unparsed)
132
    if cmd_str is None:
133
        print(bold('Command groups:'))
134
        print_list(_commands.get_groups(), ident=14)
135
        print
136
        return None
137
    try:
138
        return _commands.get_class(cmd_str)
139
    except CLICmdIncompleteError:
140
        print(bold('%s:'%cmd_str))
141
        print_list(_commands.list(cmd_str))
142
    return None
143

  
115 144
def one_command():
116 145
    try:
117 146
        exe = basename(argv[0])
......
119 148
        parsed, unparsed = parse_known_args(parser)
120 149
        if _arguments['version'].value:
121 150
            exit(0)
151
        _commands.set_groups(_arguments['config'].get_groups())
152
        cmd = _retrieve_cmd(unparsed)
153

  
154
        if cmd is None:
155
            parser.print_help()
156
            exit(0)
157

  
122 158
    except CLIError as err:
123 159
        _print_error_message(err)
124 160
        exit(1)
b/kamaki/cli/argument.py
142 142
	def value(self, config_file):
143 143
		self._value = Config(config_file) if config_file is not None else Config()
144 144

  
145
	def get_groups(self):
146
		return self.value.apis()
147

  
148

  
149
_config_arg = ConfigArgument(1, 'Path to configuration file', '--config')
150

  
145 151
class CmdLineConfigArgument(Argument):
146 152
	def __init__(self, config_arg, help='', parsed_name=None, default=None):
147 153
		super(self.__class__, self).__init__(1, help, parsed_name, default)
......
164 170
				raise CLISyntaxError(details='Missing . between section and key: -o section.key=val')
165 171
		self._config_arg.value.override(section.strip(), key.strip(), val.strip())
166 172

  
167
_config_arg = ConfigArgument(1, 'Path to configuration file', '--config')
168 173
_arguments = dict(config = _config_arg,
169 174
	debug = Argument(0, 'Include debug output', ('-d', '--debug')),
170 175
	include = Argument(0, 'Include protocol headers in the output', ('-i', '--include')),
b/kamaki/cli/errors.py
55 55
		super(CLIUnknownCommand, self).__init__(message, status, details, importance=0)
56 56

  
57 57
class CLICmdSpecError(CLIError):
58
	def __init__(self, message='Command Specification Error', status=13, details=''):
58
	def __init__(self, message='Command Specification Error', status=13, details='', importance=1):
59 59
		super(CLICmdSpecError, self).__init__(message, status, details, importance=0)
60 60

  
61
class CLICmdIncompleteError(CLICmdSpecError):
62
    def __init__(self, message='Incomplete Command Error', status=14, details=''):
63
        super(CLICmdSpecError, self).__init__(message, status, details, importance=1)
64

  
61 65
def raiseCLIError(err, importance = -1):
62 66
    if importance < 0:
63 67
        if err.status <= 0:
b/kamaki/cli/utils.py
38 38
        return val
39 39
    red = yellow = magenta = bold
40 40

  
41
from .errors import CLIUnknownCommand, CLICmdSpecError, CLIError
41
from .errors import CLIUnknownCommand, CLICmdIncompleteError, CLICmdSpecError, CLIError
42 42

  
43 43
"""
44 44
def magenta(val):
......
88 88
    def __init__(self):
89 89
        self._commands = {}
90 90

  
91
    def set_groups(self, groups):
92
        for grp in groups:
93
            self._commands[grp] = {}
94

  
95
    def get_groups(self):
96
        return self._commands.keys()
97

  
91 98
    def _get_commands_from_prefix(self, prefix):
99
        if len(prefix) == 0:
100
            return self._commands
92 101
        path = get_pathlist_from_prefix(prefix)
93 102
        next_list = self._commands
94 103
        try:
......
116 125
        except ValueError:
117 126
            return ret
118 127

  
119
    def is_full_command(self, command):
128
    def get_class(self, command):
120 129
        """ Check if a command exists as a full/terminal command
121 130
        e.g. store_list is full, store is partial, stort is not existing
122 131
        @param command can either be a cmd1_cmd2_... str or a ['cmd1, cmd2, ...'] list
......
124 133
        @raise CLIUnknownCommand if command is unknown to this tree
125 134
        """
126 135
        next_level = self._get_commands_from_prefix(command)
127
        if '_class' in next_level.keys():
128
            return True
129
        return False
136
        try:
137
            return next_level['_class']
138
        except KeyError:
139
            raise CLICmdIncompleteError(details='Cmd %s is not a full cmd'%command)
130 140

  
131 141
    def add(self, command, cmd_class):
132 142
        """Add a command_path-->cmd_class relation to the path """
......
146 156
            try:
147 157
                cmds = cmds[cmd]
148 158
            except KeyError:
149
                raise CLIUnknownCommand('set_description to cmd %s failed: cmd not found'%command)
159
                raise CLIUnknownCommand(details='set_description to cmd %s failed: cmd not found'%command)
150 160
        cmds['_description'] = description
161

  
151 162
    def load_spec_package(self, spec_package):
152 163
        loaded = False
153 164
        for location in self.cmd_spec_locations:
......
159 170
            except ImportError:
160 171
                pass
161 172
        if not loaded:
162
            raise CLICmdSpecError('Cmd Spec Package %s load failed'%spec_package)
173
            raise CLICmdSpecError(details='Cmd Spec Package %s load failed'%spec_package)
163 174

  
164 175
    def load_spec(self, spec_package, spec):
165 176
        """Load spec from a non nessecery loaded spec package"""
......
177 188
            raise CLICmdSpecError('Cmd Spec %s load failed'%spec)
178 189

  
179 190
def get_pathlist_from_prefix(prefix):
180
    return prefix if isinstance(prefix,list) else unicode(prefix).split('_')
191
    if isinstance(prefix, list):
192
        return prefix
193
    if len(prefix) == 0:
194
        return []
195
    return unicode(prefix).split('_')
181 196

  
182 197
def pretty_keys(d, delim='_', recurcive=False):
183 198
    """Transform keys of a dict from the form

Also available in: Unified diff