Commit d252a7a8 authored by Stavros Sachtouris's avatar Stavros Sachtouris
Browse files

Fully test CommandTree

Refs: #4058
parent a624a072
...@@ -346,9 +346,9 @@ def _groups_help(arguments): ...@@ -346,9 +346,9 @@ def _groups_help(arguments):
if pkg: if pkg:
cmds = getattr(pkg, '_commands') cmds = getattr(pkg, '_commands')
try: try:
for cmd in cmds: for cmd_tree in cmds:
if cmd.name in acceptable_groups: if cmd_tree.name in acceptable_groups:
descriptions[cmd.name] = cmd.help descriptions[cmd_tree.name] = cmd_tree.description
except TypeError: except TypeError:
if _debug: if _debug:
kloger.warning( kloger.warning(
......
...@@ -150,7 +150,7 @@ class Shell(Cmd): ...@@ -150,7 +150,7 @@ class Shell(Cmd):
pass pass
def _roll_command(self, cmd_path=None): def _roll_command(self, cmd_path=None):
for subname in self.cmd_tree.get_subnames(cmd_path): for subname in self.cmd_tree.subnames(cmd_path):
self._unregister_method('do_%s' % subname) self._unregister_method('do_%s' % subname)
self._unregister_method('complete_%s' % subname) self._unregister_method('complete_%s' % subname)
self._unregister_method('help_%s' % subname) self._unregister_method('help_%s' % subname)
...@@ -288,7 +288,7 @@ class Shell(Cmd): ...@@ -288,7 +288,7 @@ class Shell(Cmd):
cmd_args[','.join(arg.parsed_name)] = arg.help cmd_args[','.join(arg.parsed_name)] = arg.help
print_dict(cmd_args, indent=2) print_dict(cmd_args, indent=2)
stdout.write('%s %s' % (self.prompt, line)) stdout.write('%s %s' % (self.prompt, line))
return subcmd.get_subnames() return subcmd.subnames()
self._register_method(complete_method, 'complete_%s' % cmd.name) self._register_method(complete_method, 'complete_%s' % cmd.name)
@property @property
...@@ -311,7 +311,7 @@ class Shell(Cmd): ...@@ -311,7 +311,7 @@ class Shell(Cmd):
intro = self.cmd_tree.name intro = self.cmd_tree.name
acceptable = parser.arguments['config'].get_groups() acceptable = parser.arguments['config'].get_groups()
total = self.cmd_tree.get_group_names() total = self.cmd_tree.groups.keys()
self.cmd_tree.exclude(set(total).difference(acceptable)) self.cmd_tree.exclude(set(total).difference(acceptable))
for subcmd in self.cmd_tree.get_subcommands(path): for subcmd in self.cmd_tree.get_subcommands(path):
......
...@@ -101,25 +101,19 @@ class Command(object): ...@@ -101,25 +101,19 @@ class Command(object):
return cmd, args[index:] return cmd, args[index:]
def pretty_print(self, recursive=False): def pretty_print(self, recursive=False):
print('Path: %s (Name: %s) is_cmd: %s\n\thelp: %s' % ( print('%s\t\t(Name: %s is_cmd: %s help: %s)' % (
self.path, self.path, self.name, self.is_command, self.help))
self.name,
self.is_command,
self.help))
for cmd in self.subcommands.values(): for cmd in self.subcommands.values():
cmd.pretty_print(recursive) cmd.pretty_print(recursive)
class CommandTree(object): class CommandTree(object):
groups = {}
_all_commands = {}
name = None
description = None
def __init__(self, name, description=''): def __init__(self, name, description=''):
self.name = name self.name = name
self.description = description self.description = description
self.groups = dict()
self._all_commands = dict()
def exclude(self, groups_to_exclude=[]): def exclude(self, groups_to_exclude=[]):
for group in groups_to_exclude: for group in groups_to_exclude:
...@@ -143,17 +137,17 @@ class CommandTree(object): ...@@ -143,17 +137,17 @@ class CommandTree(object):
self._all_commands[path] = new_cmd self._all_commands[path] = new_cmd
cmd.add_subcmd(new_cmd) cmd.add_subcmd(new_cmd)
cmd = new_cmd cmd = new_cmd
if cmd_class: cmd.cmd_class = cmd_class or None
cmd.cmd_class = cmd_class cmd.help = description or None
if description is not None:
cmd.help = description
def find_best_match(self, terms): def find_best_match(self, terms):
"""Find a command that best matches a given list of terms """Find a command that best matches a given list of terms
:param terms: (list of str) match them against paths in cmd_tree :param terms: (list of str) match against paths in cmd_tree, e.g.
['aa', 'bb', 'cc'] matches aa_bb_cc
:returns: (Command, list) the matching command, the remaining terms :returns: (Command, list) the matching command, the remaining terms or
None
""" """
path = [] path = []
for term in terms: for term in terms:
...@@ -170,7 +164,10 @@ class CommandTree(object): ...@@ -170,7 +164,10 @@ class CommandTree(object):
tdesc = new_tree.description tdesc = new_tree.description
self.groups.update(new_tree.groups) self.groups.update(new_tree.groups)
self._all_commands.update(new_tree._all_commands) self._all_commands.update(new_tree._all_commands)
self.set_description(tname, tdesc) try:
self._all_commands[tname].help = tdesc
except KeyError:
self.add_command(tname, tdesc)
def has_command(self, path): def has_command(self, path):
return path in self._all_commands return path in self._all_commands
...@@ -178,53 +175,14 @@ class CommandTree(object): ...@@ -178,53 +175,14 @@ class CommandTree(object):
def get_command(self, path): def get_command(self, path):
return self._all_commands[path] return self._all_commands[path]
def get_groups(self): def subnames(self, path=None):
return self.groups.values()
def get_group_names(self):
return self.groups.keys()
def set_description(self, path, description):
self._all_commands[path].help = description
def get_description(self, path):
return self._all_commands[path].help
def get_subnames(self, path=None):
if path in (None, ''): if path in (None, ''):
return self.get_group_names() return self.groups.keys()
return self._all_commands[path].subcommands.keys() return self._all_commands[path].subcommands.keys()
def get_subcommands(self, path=None): def get_subcommands(self, path=None):
return self._all_commands[path].subcommands.values() if ( return self._all_commands[path].subcommands.values() if (
path) else self.get_groups() path) else self.groups.values()
def get_parent(self, path):
if '_' not in path:
return None
terms = path.split('_')
parent_path = '_'.join(terms[:-1])
return self._all_commands[parent_path]
def get_closest_ancestor_command(self, path):
path, sep, name = path.rpartition('_')
while len(path) > 0:
cmd = self._all_commands[path]
if cmd.is_command:
return cmd
path, sep, name = path.rpartition('_')
return None
if '_' not in path:
return None
terms = path.split()[:-1]
while len(terms) > 0:
tmp_path = '_'.join(terms)
cmd = self._all_commands[tmp_path]
if cmd.is_command:
return cmd
terms = terms[:-1]
raise KeyError('No ancestor commands')
def pretty_print(self, group=None): def pretty_print(self, group=None):
if group is None: if group is None:
......
...@@ -165,18 +165,30 @@ class Command(TestCase): ...@@ -165,18 +165,30 @@ class Command(TestCase):
class CommandTree(TestCase): class CommandTree(TestCase):
def _add_commands(self, ctree):
for cmd in self.commands:
ctree.add_command(cmd.path, cmd.help, cmd.cmd_class)
def _commands_are_equal(self, c1, c2):
self.assertEqual(c1.path, c2.path)
self.assertEqual(c1.name, c2.name)
self.assertEqual(c1.cmd_class, c2.cmd_class)
self.assertEqual(c1.help, c2.help)
def setUp(self): def setUp(self):
cmd = command_tree.Command('cmd', subcommands=dict( cmd = command_tree.Command('cmd', subcommands=dict(
cmd0a=command_tree.Command('cmd_cmd0a', subcommands=dict( cmd0a=command_tree.Command('cmd_cmd0a', subcommands=dict(
cmd1a=command_tree.Command( cmd1a=command_tree.Command(
'cmd_cmd0a_cmd1a', subcommands=dict( 'cmd_cmd0a_cmd1a', subcommands=dict(
cmd2=command_tree.Command('cmd_cmd0a_cmd1a_cmd2'), cmd2=command_tree.Command(
) 'cmd_cmd0a_cmd1a_cmd2', cmd_class=Command)
),
), ),
cmd1b=command_tree.Command( cmd1b=command_tree.Command(
'cmd_cmd0a_cmd1b', subcommands=dict( 'cmd_cmd0a_cmd1b', subcommands=dict(
cmd2=command_tree.Command('cmd_cmd0a_cmd1b_cmd2'), cmd2=command_tree.Command(
) 'cmd_cmd0a_cmd1b_cmd2', cmd_class=Command)
),
) )
)), )),
cmd0b=command_tree.Command('cmd_cmd0b'), cmd0b=command_tree.Command('cmd_cmd0b'),
...@@ -184,8 +196,9 @@ class CommandTree(TestCase): ...@@ -184,8 +196,9 @@ class CommandTree(TestCase):
cmd1a=command_tree.Command('cmd_cmd0c_cmd1a'), cmd1a=command_tree.Command('cmd_cmd0c_cmd1a'),
cmd1b=command_tree.Command( cmd1b=command_tree.Command(
'cmd_cmd0c_cmd1b', subcommands=dict( 'cmd_cmd0c_cmd1b', subcommands=dict(
cmd2=command_tree.Command('cmd_cmd0c_cmd1b_cmd2'), cmd2=command_tree.Command(
) 'cmd_cmd0c_cmd1b_cmd2', cmd_class=Command)
),
) )
)) ))
)) ))
...@@ -201,6 +214,7 @@ class CommandTree(TestCase): ...@@ -201,6 +214,7 @@ class CommandTree(TestCase):
cmd.subcommands['cmd0c'].subcommands['cmd1a'], cmd.subcommands['cmd0c'].subcommands['cmd1a'],
cmd.subcommands['cmd0c'].subcommands['cmd1b'], cmd.subcommands['cmd0c'].subcommands['cmd1b'],
cmd.subcommands['cmd0c'].subcommands['cmd1b'].subcommands['cmd2'], cmd.subcommands['cmd0c'].subcommands['cmd1b'].subcommands['cmd2'],
command_tree.Command('othercmd')
] ]
def tearDown(self): def tearDown(self):
...@@ -209,8 +223,155 @@ class CommandTree(TestCase): ...@@ -209,8 +223,155 @@ class CommandTree(TestCase):
del self.commands del self.commands
def test___init__(self): def test___init__(self):
ctree = command_tree.CommandTree('sampleTree', 'a sample Tree') name, description = 'sampleTree', 'a sample Tree'
ctree.pretty_print() ctree = command_tree.CommandTree(name)
for attr, exp in (
('groups', {}), ('_all_commands', {}),
('name', name), ('description', '')):
self.assertEqual(getattr(ctree, attr), exp)
ctree = command_tree.CommandTree(name, description)
for attr, exp in (
('groups', {}), ('_all_commands', {}),
('name', name), ('description', description)):
self.assertEqual(getattr(ctree, attr), exp)
def test_exclude(self):
ctree = command_tree.CommandTree('excludeTree', 'test exclude group')
exp = dict()
for cmd in self.commands[0:6]:
ctree.groups[cmd.name] = cmd
exp[cmd.name] = cmd
self.assertEqual(exp, ctree.groups)
ctree.exclude(exp.keys()[1::2])
for key in exp.keys()[1::2]:
exp.pop(key)
self.assertEqual(exp, ctree.groups)
def test_add_command(self):
ctree = command_tree.CommandTree('addCommand', 'test add_command')
self._add_commands(ctree)
for cmd in self.commands:
self.assertTrue(cmd, ctree._all_commands)
if cmd.path.count('_'):
self.assertFalse(cmd.name in ctree.groups)
else:
self.assertTrue(cmd.name in ctree.groups)
self._commands_are_equal(cmd, ctree.groups[cmd.name])
def test_find_best_match(self):
ctree = command_tree.CommandTree('bestMatch', 'test find_best_match')
for cmd in self.commands:
terms = cmd.path.split('_')
best_match, rest = ctree.find_best_match(terms)
if len(terms) > 1:
self.assertEqual(best_match.path, '_'.join(terms[:-1]))
else:
self.assertEqual(best_match, None)
self.assertEqual(rest, terms[-1:])
ctree.add_command(cmd.path, cmd.help, cmd.cmd_class)
best_match, rest = ctree.find_best_match(terms)
self._commands_are_equal(best_match, cmd)
self.assertEqual(rest, [])
def test_add_tree(self):
ctree = command_tree.CommandTree('tree', 'the main tree')
ctree1 = command_tree.CommandTree('tree1', 'the first tree')
ctree2 = command_tree.CommandTree('tree2', 'the second tree')
cmds = list(self.commands)
del self.commands
cmds1, cmds2 = cmds[:6], cmds[6:]
self.commands = cmds1
self._add_commands(ctree1)
self.commands = cmds2
self._add_commands(ctree2)
self.commands = cmds
def check_all(
p1=False, p2=False, p3=False, p4=False, p5=False, p6=False):
for cmd in cmds[:6]:
self.assertEquals(cmd.path in ctree._all_commands, p1)
self.assertEquals(cmd.path in ctree1._all_commands, p2)
if cmd.path != 'cmd':
self.assertEquals(cmd.path in ctree2._all_commands, p3)
for cmd in cmds[6:]:
self.assertEquals(cmd.path in ctree._all_commands, p4)
if cmd.path != 'cmd':
self.assertEquals(cmd.path in ctree1._all_commands, p5)
self.assertEquals(cmd.path in ctree2._all_commands, p6)
check_all(False, True, False, False, False, True)
ctree.add_tree(ctree1)
check_all(True, True, False, False, False, True)
ctree.add_tree(ctree2)
check_all(True, True, False, True, False, True)
ctree2.add_tree(ctree1)
check_all(True, True, True, True, False, True)
def test_has_command(self):
ctree = command_tree.CommandTree('treeHasCommand', 'test has_command')
for cmd in self.commands:
self.assertFalse(ctree.has_command(cmd.path))
self._add_commands(ctree)
for cmd in self.commands:
self.assertTrue(ctree.has_command(cmd.path))
self.assertFalse(ctree.has_command('NON_EXISTING_COMMAND'))
def test_get_command(self):
ctree = command_tree.CommandTree('treeGetCommand', 'test get_command')
for cmd in self.commands:
self.assertRaises(KeyError, ctree.get_command, cmd.path)
self._add_commands(ctree)
for cmd in self.commands:
self._commands_are_equal(ctree.get_command(cmd.path), cmd)
self.assertRaises(KeyError, ctree.get_command, 'NON_EXISTNG_COMMAND')
def test_subnames(self):
ctree = command_tree.CommandTree('treeSubnames', 'test subnames')
self.assertEqual(ctree.subnames(), [])
self.assertRaises(KeyError, ctree.subnames, 'cmd')
self._add_commands(ctree)
for l1, l2 in (
(ctree.subnames(), ['cmd', 'othercmd']),
(ctree.subnames('cmd'), ['cmd0a', 'cmd0b', 'cmd0c']),
(ctree.subnames('cmd_cmd0a'), ['cmd1a', 'cmd1b']),
(ctree.subnames('cmd_cmd0a_cmd1a'), ['cmd2', ]),
(ctree.subnames('cmd_cmd0a_cmd1b'), ['cmd2', ]),
(ctree.subnames('cmd_cmd0a_cmd1a_cmd2'), []),
(ctree.subnames('cmd_cmd0a_cmd1b_cmd2'), []),
(ctree.subnames('cmd_cmd0b'), []),
(ctree.subnames('cmd_cmd0c'), ['cmd1a', 'cmd1b']),
(ctree.subnames('cmd_cmd0c_cmd1a'), []),
(ctree.subnames('cmd_cmd0c_cmd1b'), ['cmd2', ]),
(ctree.subnames('cmd_cmd0c_cmd1b_cmd2'), []),
(ctree.subnames('othercmd'), [])):
l1.sort(), l2.sort(), self.assertEqual(l1, l2)
self.assertRaises(KeyError, ctree.subnames, 'NON_EXISTNG_CMD')
def test_get_subcommands(self):
ctree = command_tree.CommandTree('treeSub', 'test get_subcommands')
self.assertEqual(ctree.get_subcommands(), [])
self.assertRaises(KeyError, ctree.get_subcommands, 'cmd')
self._add_commands(ctree)
for s1, l2 in (
('', ['cmd', 'othercmd']),
('cmd', ['cmd0a', 'cmd0b', 'cmd0c']),
('cmd_cmd0a', ['cmd1a', 'cmd1b']),
('cmd_cmd0a_cmd1a', ['cmd2', ]),
('cmd_cmd0a_cmd1b', ['cmd2', ]),
('cmd_cmd0a_cmd1a_cmd2', []),
('cmd_cmd0a_cmd1b_cmd2', []),
('cmd_cmd0b', []),
('cmd_cmd0c', ['cmd1a', 'cmd1b']),
('cmd_cmd0c_cmd1a', []),
('cmd_cmd0c_cmd1b', ['cmd2', ]),
('cmd_cmd0c_cmd1b_cmd2', []),
('othercmd', [])
):
l1 = [cmd.path for cmd in ctree.get_subcommands(s1)]
l2 = ['_'.join([s1, i]) for i in l2] if s1 else l2
l1.sort(), l2.sort(), self.assertEqual(l1, l2)
self.assertRaises(KeyError, ctree.get_subcommands, 'NON_EXISTNG_CMD')
if __name__ == '__main__': if __name__ == '__main__':
......
...@@ -320,9 +320,7 @@ class ComputeClient(ComputeRestClient): ...@@ -320,9 +320,7 @@ class ComputeClient(ComputeRestClient):
:param pool: (str) pool of ips to allocate from :param pool: (str) pool of ips to allocate from
:returns: (dict) { :returns: (dict) {fixed_ip: . id: . instance_id: . ip: . pool: .}
fixed_ip: ..., id: ..., instance_id: ..., ip: ..., pool: ...
}
""" """
json_data = dict(pool=pool) if pool else dict() json_data = dict(pool=pool) if pool else dict()
r = self.floating_ips_post(tenant_id, json_data) r = self.floating_ips_post(tenant_id, json_data)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment