summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Volkov <avolkov@mirantis.com>2018-03-14 19:30:06 +0300
committerAndrey Volkov <avolkov@mirantis.com>2018-03-15 17:50:11 +0300
commit8bcd068e876ddd48ae61c1803449d666f5e28ba0 (patch)
treefa67f241971d4bfb8596302562200d6084ebed6a
parentfa5303f058cdd1bc90a86d2dc2fff70a9cbd5de1 (diff)
downloadcliff-8bcd068e876ddd48ae61c1803449d666f5e28ba0.tar.gz
Allow finding command by partial name2.17.0
This small improvement helps to decrease the amount of typing. $ openstack resource provider list ... ^ too long? $ alias os=openstack $ os r p l ... ^ much better! Change-Id: I713eab2bd9f949da01c03b65ff16a01de92e3e62
-rw-r--r--cliff/commandmanager.py23
-rw-r--r--cliff/tests/test_commandmanager.py54
2 files changed, 76 insertions, 1 deletions
diff --git a/cliff/commandmanager.py b/cliff/commandmanager.py
index a0a9bb3..8ee733d 100644
--- a/cliff/commandmanager.py
+++ b/cliff/commandmanager.py
@@ -22,6 +22,18 @@ import pkg_resources
LOG = logging.getLogger(__name__)
+def _get_commands_by_partial_name(args, commands):
+ n = len(args)
+ candidates = []
+ for command_name in commands:
+ command_parts = command_name.split()
+ if len(command_parts) != n:
+ continue
+ if all(command_parts[i].startswith(args[i]) for i in range(n)):
+ candidates.append(command_name)
+ return candidates
+
+
class EntryPointWrapper(object):
"""Wrap up a command class already imported to make it look like a plugin.
"""
@@ -96,8 +108,17 @@ class CommandManager(object):
# Convert the legacy command name to its new name.
if name in self._legacy:
name = self._legacy[name]
+
+ found = None
if name in self.commands:
- cmd_ep = self.commands[name]
+ found = name
+ else:
+ candidates = _get_commands_by_partial_name(
+ argv[:i], self.commands)
+ if len(candidates) == 1:
+ found = candidates[0]
+ if found:
+ cmd_ep = self.commands[found]
if hasattr(cmd_ep, 'resolve'):
cmd_factory = cmd_ep.resolve()
else:
diff --git a/cliff/tests/test_commandmanager.py b/cliff/tests/test_commandmanager.py
index 5a3f928..fae9d0a 100644
--- a/cliff/tests/test_commandmanager.py
+++ b/cliff/tests/test_commandmanager.py
@@ -199,3 +199,57 @@ class TestLegacyCommand(base.TestBase):
mgr.find_command,
['cmd2'],
)
+
+
+class TestLookupAndFindPartialName(base.TestBase):
+
+ scenarios = [
+ ('one-word', {'argv': ['o']}),
+ ('two-words', {'argv': ['t', 'w']}),
+ ('three-words', {'argv': ['t', 'w', 'c']}),
+ ]
+
+ def test(self):
+ mgr = utils.TestCommandManager(utils.TEST_NAMESPACE)
+ cmd, name, remaining = mgr.find_command(self.argv)
+ self.assertTrue(cmd)
+ self.assertEqual(' '.join(self.argv), name)
+ self.assertFalse(remaining)
+
+
+class TestGetByPartialName(base.TestBase):
+
+ def setUp(self):
+ super(TestGetByPartialName, self).setUp()
+ self.commands = {
+ 'resource provider list': 1,
+ 'resource class list': 2,
+ 'server list': 3,
+ 'service list': 4}
+
+ def test_no_candidates(self):
+ self.assertEqual(
+ [], commandmanager._get_commands_by_partial_name(
+ ['r', 'p'], self.commands))
+ self.assertEqual(
+ [], commandmanager._get_commands_by_partial_name(
+ ['r', 'p', 'c'], self.commands))
+
+ def test_multiple_candidates(self):
+ self.assertEqual(
+ 2, len(commandmanager._get_commands_by_partial_name(
+ ['se', 'li'], self.commands)))
+
+ def test_one_candidate(self):
+ self.assertEqual(
+ ['resource provider list'],
+ commandmanager._get_commands_by_partial_name(
+ ['r', 'p', 'l'], self.commands))
+ self.assertEqual(
+ ['resource provider list'],
+ commandmanager._get_commands_by_partial_name(
+ ['resource', 'provider', 'list'], self.commands))
+ self.assertEqual(
+ ['server list'],
+ commandmanager._get_commands_by_partial_name(
+ ['serve', 'l'], self.commands))