Revision d252a7a8

b/kamaki/cli/__init__.py
346 346
        if pkg:
347 347
            cmds = getattr(pkg, '_commands')
348 348
            try:
349
                for cmd in cmds:
350
                    if cmd.name in acceptable_groups:
351
                        descriptions[cmd.name] = cmd.help
349
                for cmd_tree in cmds:
350
                    if cmd_tree.name in acceptable_groups:
351
                        descriptions[cmd_tree.name] = cmd_tree.description
352 352
            except TypeError:
353 353
                if _debug:
354 354
                    kloger.warning(
b/kamaki/cli/command_shell.py
150 150
            pass
151 151

  
152 152
    def _roll_command(self, cmd_path=None):
153
        for subname in self.cmd_tree.get_subnames(cmd_path):
153
        for subname in self.cmd_tree.subnames(cmd_path):
154 154
            self._unregister_method('do_%s' % subname)
155 155
            self._unregister_method('complete_%s' % subname)
156 156
            self._unregister_method('help_%s' % subname)
......
288 288
                    cmd_args[','.join(arg.parsed_name)] = arg.help
289 289
                print_dict(cmd_args, indent=2)
290 290
                stdout.write('%s %s' % (self.prompt, line))
291
            return subcmd.get_subnames()
291
            return subcmd.subnames()
292 292
        self._register_method(complete_method, 'complete_%s' % cmd.name)
293 293

  
294 294
    @property
......
311 311
            intro = self.cmd_tree.name
312 312

  
313 313
        acceptable = parser.arguments['config'].get_groups()
314
        total = self.cmd_tree.get_group_names()
314
        total = self.cmd_tree.groups.keys()
315 315
        self.cmd_tree.exclude(set(total).difference(acceptable))
316 316

  
317 317
        for subcmd in self.cmd_tree.get_subcommands(path):
b/kamaki/cli/command_tree/__init__.py
101 101
        return cmd, args[index:]
102 102

  
103 103
    def pretty_print(self, recursive=False):
104
        print('Path: %s (Name: %s) is_cmd: %s\n\thelp: %s' % (
105
            self.path,
106
            self.name,
107
            self.is_command,
108
            self.help))
104
        print('%s\t\t(Name: %s is_cmd: %s help: %s)' % (
105
            self.path, self.name, self.is_command, self.help))
109 106
        for cmd in self.subcommands.values():
110 107
            cmd.pretty_print(recursive)
111 108

  
112 109

  
113 110
class CommandTree(object):
114 111

  
115
    groups = {}
116
    _all_commands = {}
117
    name = None
118
    description = None
119

  
120 112
    def __init__(self, name, description=''):
121 113
        self.name = name
122 114
        self.description = description
115
        self.groups = dict()
116
        self._all_commands = dict()
123 117

  
124 118
    def exclude(self, groups_to_exclude=[]):
125 119
        for group in groups_to_exclude:
......
143 137
                self._all_commands[path] = new_cmd
144 138
                cmd.add_subcmd(new_cmd)
145 139
                cmd = new_cmd
146
        if cmd_class:
147
            cmd.cmd_class = cmd_class
148
        if description is not None:
149
            cmd.help = description
140
        cmd.cmd_class = cmd_class or None
141
        cmd.help = description or None
150 142

  
151 143
    def find_best_match(self, terms):
152 144
        """Find a command that best matches a given list of terms
153 145

  
154
        :param terms: (list of str) match them against paths in cmd_tree
146
        :param terms: (list of str) match against paths in cmd_tree, e.g.
147
            ['aa', 'bb', 'cc'] matches aa_bb_cc
155 148

  
156
        :returns: (Command, list) the matching command, the remaining terms
149
        :returns: (Command, list) the matching command, the remaining terms or
150
            None
157 151
        """
158 152
        path = []
159 153
        for term in terms:
......
170 164
        tdesc = new_tree.description
171 165
        self.groups.update(new_tree.groups)
172 166
        self._all_commands.update(new_tree._all_commands)
173
        self.set_description(tname, tdesc)
167
        try:
168
            self._all_commands[tname].help = tdesc
169
        except KeyError:
170
            self.add_command(tname, tdesc)
174 171

  
175 172
    def has_command(self, path):
176 173
        return path in self._all_commands
......
178 175
    def get_command(self, path):
179 176
        return self._all_commands[path]
180 177

  
181
    def get_groups(self):
182
        return self.groups.values()
183

  
184
    def get_group_names(self):
185
        return self.groups.keys()
186

  
187
    def set_description(self, path, description):
188
        self._all_commands[path].help = description
189

  
190
    def get_description(self, path):
191
        return self._all_commands[path].help
192

  
193
    def get_subnames(self, path=None):
178
    def subnames(self, path=None):
194 179
        if path in (None, ''):
195
            return self.get_group_names()
180
            return self.groups.keys()
196 181
        return self._all_commands[path].subcommands.keys()
197 182

  
198 183
    def get_subcommands(self, path=None):
199 184
        return self._all_commands[path].subcommands.values() if (
200
            path) else self.get_groups()
201

  
202
    def get_parent(self, path):
203
        if '_' not in path:
204
            return None
205
        terms = path.split('_')
206
        parent_path = '_'.join(terms[:-1])
207
        return self._all_commands[parent_path]
208

  
209
    def get_closest_ancestor_command(self, path):
210
        path, sep, name = path.rpartition('_')
211
        while len(path) > 0:
212
            cmd = self._all_commands[path]
213
            if cmd.is_command:
214
                return cmd
215
            path, sep, name = path.rpartition('_')
216
        return None
217

  
218
        if '_' not in path:
219
            return None
220
        terms = path.split()[:-1]
221
        while len(terms) > 0:
222
            tmp_path = '_'.join(terms)
223
            cmd = self._all_commands[tmp_path]
224
            if cmd.is_command:
225
                return cmd
226
            terms = terms[:-1]
227
        raise KeyError('No ancestor commands')
185
            path) else self.groups.values()
228 186

  
229 187
    def pretty_print(self, group=None):
230 188
        if group is None:
b/kamaki/cli/command_tree/test.py
165 165

  
166 166
class CommandTree(TestCase):
167 167

  
168
    def _add_commands(self, ctree):
169
        for cmd in self.commands:
170
            ctree.add_command(cmd.path, cmd.help, cmd.cmd_class)
171

  
172
    def _commands_are_equal(self, c1, c2):
173
        self.assertEqual(c1.path, c2.path)
174
        self.assertEqual(c1.name, c2.name)
175
        self.assertEqual(c1.cmd_class, c2.cmd_class)
176
        self.assertEqual(c1.help, c2.help)
177

  
168 178
    def setUp(self):
169 179
        cmd = command_tree.Command('cmd', subcommands=dict(
170 180
            cmd0a=command_tree.Command('cmd_cmd0a', subcommands=dict(
171 181
                cmd1a=command_tree.Command(
172 182
                    'cmd_cmd0a_cmd1a', subcommands=dict(
173
                        cmd2=command_tree.Command('cmd_cmd0a_cmd1a_cmd2'),
174
                    )
183
                        cmd2=command_tree.Command(
184
                            'cmd_cmd0a_cmd1a_cmd2', cmd_class=Command)
185
                        ),
175 186
                ),
176 187
                cmd1b=command_tree.Command(
177 188
                    'cmd_cmd0a_cmd1b', subcommands=dict(
178
                        cmd2=command_tree.Command('cmd_cmd0a_cmd1b_cmd2'),
179
                    )
189
                        cmd2=command_tree.Command(
190
                            'cmd_cmd0a_cmd1b_cmd2', cmd_class=Command)
191
                        ),
180 192
                )
181 193
            )),
182 194
            cmd0b=command_tree.Command('cmd_cmd0b'),
......
184 196
                cmd1a=command_tree.Command('cmd_cmd0c_cmd1a'),
185 197
                cmd1b=command_tree.Command(
186 198
                    'cmd_cmd0c_cmd1b', subcommands=dict(
187
                        cmd2=command_tree.Command('cmd_cmd0c_cmd1b_cmd2'),
188
                    )
199
                        cmd2=command_tree.Command(
200
                            'cmd_cmd0c_cmd1b_cmd2', cmd_class=Command)
201
                        ),
189 202
                )
190 203
            ))
191 204
        ))
......
201 214
            cmd.subcommands['cmd0c'].subcommands['cmd1a'],
202 215
            cmd.subcommands['cmd0c'].subcommands['cmd1b'],
203 216
            cmd.subcommands['cmd0c'].subcommands['cmd1b'].subcommands['cmd2'],
217
            command_tree.Command('othercmd')
204 218
        ]
205 219

  
206 220
    def tearDown(self):
......
209 223
        del self.commands
210 224

  
211 225
    def test___init__(self):
212
        ctree = command_tree.CommandTree('sampleTree', 'a sample Tree')
213
        ctree.pretty_print()
226
        name, description = 'sampleTree', 'a sample Tree'
227
        ctree = command_tree.CommandTree(name)
228
        for attr, exp in (
229
                ('groups', {}), ('_all_commands', {}),
230
                ('name', name), ('description', '')):
231
            self.assertEqual(getattr(ctree, attr), exp)
232
        ctree = command_tree.CommandTree(name, description)
233
        for attr, exp in (
234
                ('groups', {}), ('_all_commands', {}),
235
                ('name', name), ('description', description)):
236
            self.assertEqual(getattr(ctree, attr), exp)
237

  
238
    def test_exclude(self):
239
        ctree = command_tree.CommandTree('excludeTree', 'test exclude group')
240
        exp = dict()
241
        for cmd in self.commands[0:6]:
242
            ctree.groups[cmd.name] = cmd
243
            exp[cmd.name] = cmd
244
        self.assertEqual(exp, ctree.groups)
245
        ctree.exclude(exp.keys()[1::2])
246
        for key in exp.keys()[1::2]:
247
            exp.pop(key)
248
        self.assertEqual(exp, ctree.groups)
249

  
250
    def test_add_command(self):
251
        ctree = command_tree.CommandTree('addCommand', 'test add_command')
252
        self._add_commands(ctree)
253
        for cmd in self.commands:
254
            self.assertTrue(cmd, ctree._all_commands)
255
            if cmd.path.count('_'):
256
                self.assertFalse(cmd.name in ctree.groups)
257
            else:
258
                self.assertTrue(cmd.name in ctree.groups)
259
                self._commands_are_equal(cmd, ctree.groups[cmd.name])
260

  
261
    def test_find_best_match(self):
262
        ctree = command_tree.CommandTree('bestMatch', 'test find_best_match')
263
        for cmd in self.commands:
264
            terms = cmd.path.split('_')
265
            best_match, rest = ctree.find_best_match(terms)
266
            if len(terms) > 1:
267
                self.assertEqual(best_match.path, '_'.join(terms[:-1]))
268
            else:
269
                self.assertEqual(best_match, None)
270
            self.assertEqual(rest, terms[-1:])
271
            ctree.add_command(cmd.path, cmd.help, cmd.cmd_class)
272
            best_match, rest = ctree.find_best_match(terms)
273
            self._commands_are_equal(best_match, cmd)
274
            self.assertEqual(rest, [])
275

  
276
    def test_add_tree(self):
277
        ctree = command_tree.CommandTree('tree', 'the main tree')
278
        ctree1 = command_tree.CommandTree('tree1', 'the first tree')
279
        ctree2 = command_tree.CommandTree('tree2', 'the second tree')
280

  
281
        cmds = list(self.commands)
282
        del self.commands
283
        cmds1, cmds2 = cmds[:6], cmds[6:]
284
        self.commands = cmds1
285
        self._add_commands(ctree1)
286
        self.commands = cmds2
287
        self._add_commands(ctree2)
288
        self.commands = cmds
289

  
290
        def check_all(
291
                p1=False, p2=False, p3=False, p4=False, p5=False, p6=False):
292
            for cmd in cmds[:6]:
293
                self.assertEquals(cmd.path in ctree._all_commands, p1)
294
                self.assertEquals(cmd.path in ctree1._all_commands, p2)
295
                if cmd.path != 'cmd':
296
                    self.assertEquals(cmd.path in ctree2._all_commands, p3)
297
            for cmd in cmds[6:]:
298
                self.assertEquals(cmd.path in ctree._all_commands, p4)
299
                if cmd.path != 'cmd':
300
                    self.assertEquals(cmd.path in ctree1._all_commands, p5)
301
                self.assertEquals(cmd.path in ctree2._all_commands, p6)
302

  
303
        check_all(False, True, False, False, False, True)
304
        ctree.add_tree(ctree1)
305
        check_all(True, True, False, False, False, True)
306
        ctree.add_tree(ctree2)
307
        check_all(True, True, False, True, False, True)
308
        ctree2.add_tree(ctree1)
309
        check_all(True, True, True, True, False, True)
310

  
311
    def test_has_command(self):
312
        ctree = command_tree.CommandTree('treeHasCommand', 'test has_command')
313
        for cmd in self.commands:
314
            self.assertFalse(ctree.has_command(cmd.path))
315
        self._add_commands(ctree)
316
        for cmd in self.commands:
317
            self.assertTrue(ctree.has_command(cmd.path))
318
        self.assertFalse(ctree.has_command('NON_EXISTING_COMMAND'))
319

  
320
    def test_get_command(self):
321
        ctree = command_tree.CommandTree('treeGetCommand', 'test get_command')
322
        for cmd in self.commands:
323
            self.assertRaises(KeyError, ctree.get_command, cmd.path)
324
        self._add_commands(ctree)
325
        for cmd in self.commands:
326
            self._commands_are_equal(ctree.get_command(cmd.path), cmd)
327
        self.assertRaises(KeyError, ctree.get_command, 'NON_EXISTNG_COMMAND')
328

  
329
    def test_subnames(self):
330
        ctree = command_tree.CommandTree('treeSubnames', 'test subnames')
331
        self.assertEqual(ctree.subnames(), [])
332
        self.assertRaises(KeyError, ctree.subnames, 'cmd')
333
        self._add_commands(ctree)
334
        for l1, l2 in (
335
                (ctree.subnames(), ['cmd', 'othercmd']),
336
                (ctree.subnames('cmd'), ['cmd0a', 'cmd0b', 'cmd0c']),
337
                (ctree.subnames('cmd_cmd0a'), ['cmd1a', 'cmd1b']),
338
                (ctree.subnames('cmd_cmd0a_cmd1a'), ['cmd2', ]),
339
                (ctree.subnames('cmd_cmd0a_cmd1b'), ['cmd2', ]),
340
                (ctree.subnames('cmd_cmd0a_cmd1a_cmd2'), []),
341
                (ctree.subnames('cmd_cmd0a_cmd1b_cmd2'), []),
342
                (ctree.subnames('cmd_cmd0b'), []),
343
                (ctree.subnames('cmd_cmd0c'), ['cmd1a', 'cmd1b']),
344
                (ctree.subnames('cmd_cmd0c_cmd1a'), []),
345
                (ctree.subnames('cmd_cmd0c_cmd1b'), ['cmd2', ]),
346
                (ctree.subnames('cmd_cmd0c_cmd1b_cmd2'), []),
347
                (ctree.subnames('othercmd'), [])):
348
            l1.sort(), l2.sort(), self.assertEqual(l1, l2)
349
        self.assertRaises(KeyError, ctree.subnames, 'NON_EXISTNG_CMD')
350

  
351
    def test_get_subcommands(self):
352
        ctree = command_tree.CommandTree('treeSub', 'test get_subcommands')
353
        self.assertEqual(ctree.get_subcommands(), [])
354
        self.assertRaises(KeyError, ctree.get_subcommands, 'cmd')
355
        self._add_commands(ctree)
356
        for s1, l2 in (
357
            ('', ['cmd', 'othercmd']),
358
            ('cmd', ['cmd0a', 'cmd0b', 'cmd0c']),
359
            ('cmd_cmd0a', ['cmd1a', 'cmd1b']),
360
            ('cmd_cmd0a_cmd1a', ['cmd2', ]),
361
            ('cmd_cmd0a_cmd1b', ['cmd2', ]),
362
            ('cmd_cmd0a_cmd1a_cmd2', []),
363
            ('cmd_cmd0a_cmd1b_cmd2', []),
364
            ('cmd_cmd0b', []),
365
            ('cmd_cmd0c', ['cmd1a', 'cmd1b']),
366
            ('cmd_cmd0c_cmd1a', []),
367
            ('cmd_cmd0c_cmd1b', ['cmd2', ]),
368
            ('cmd_cmd0c_cmd1b_cmd2', []),
369
            ('othercmd', [])
370
        ):
371
            l1 = [cmd.path for cmd in ctree.get_subcommands(s1)]
372
            l2 = ['_'.join([s1, i]) for i in l2] if s1 else l2
373
            l1.sort(), l2.sort(), self.assertEqual(l1, l2)
374
        self.assertRaises(KeyError, ctree.get_subcommands, 'NON_EXISTNG_CMD')
214 375

  
215 376

  
216 377
if __name__ == '__main__':
b/kamaki/clients/compute/__init__.py
320 320

  
321 321
        :param pool: (str) pool of ips to allocate from
322 322

  
323
        :returns: (dict) {
324
                fixed_ip: ..., id: ..., instance_id: ..., ip: ..., pool: ...
325
            }
323
        :returns: (dict) {fixed_ip: . id: . instance_id: . ip: . pool: .}
326 324
        """
327 325
        json_data = dict(pool=pool) if pool else dict()
328 326
        r = self.floating_ips_post(tenant_id, json_data)

Also available in: Unified diff