From c6fc228a250aeb22d7079b4abb9f7f19f1cbc814 Mon Sep 17 00:00:00 2001 From: Doug Hellmann Date: Wed, 22 Nov 2017 15:09:18 -0500 Subject: [PATCH] add support for legacy command name translation Add add_legacy_command() method to the command manager and update the command search logic to try translating the old legacy name to the new name. Change-Id: I0c0cdbfcb1612ec3975864fc7f730ff186879027 Signed-off-by: Doug Hellmann --- cliff/commandmanager.py | 23 ++++++++++++-- cliff/tests/test_commandmanager.py | 49 ++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 2 deletions(-) diff --git a/cliff/commandmanager.py b/cliff/commandmanager.py index f10685e5..a0a9bb36 100644 --- a/cliff/commandmanager.py +++ b/cliff/commandmanager.py @@ -45,13 +45,15 @@ class CommandManager(object): """ def __init__(self, namespace, convert_underscores=True): self.commands = {} + self._legacy = {} self.namespace = namespace self.convert_underscores = convert_underscores self._load_commands() def _load_commands(self): # NOTE(jamielennox): kept for compatibility. - self.load_commands(self.namespace) + if self.namespace: + self.load_commands(self.namespace) def load_commands(self, namespace): """Load all the commands from an entrypoint""" @@ -69,6 +71,17 @@ class CommandManager(object): def add_command(self, name, command_class): self.commands[name] = EntryPointWrapper(name, command_class) + def add_legacy_command(self, old_name, new_name): + """Map an old command name to the new name. + + :param old_name: The old command name. + :type old_name: str + :param new_name: The new command name. + :type new_name: str + + """ + self._legacy[old_name] = new_name + def find_command(self, argv): """Given an argument list, find a command and return the processor and any remaining arguments. @@ -77,6 +90,12 @@ class CommandManager(object): for i in range(start, 0, -1): name = ' '.join(argv[:i]) search_args = argv[i:] + # The legacy command handling may modify name, so remember + # the value we actually found in argv so we can return it. + return_name = name + # Convert the legacy command name to its new name. + if name in self._legacy: + name = self._legacy[name] if name in self.commands: cmd_ep = self.commands[name] if hasattr(cmd_ep, 'resolve'): @@ -89,7 +108,7 @@ class CommandManager(object): cmd_factory = cmd_ep.load(require=False) else: cmd_factory = cmd_ep.load() - return (cmd_factory, name, search_args) + return (cmd_factory, return_name, search_args) else: raise ValueError('Unknown command %r' % (argv,)) diff --git a/cliff/tests/test_commandmanager.py b/cliff/tests/test_commandmanager.py index e4ba225b..5a3f9280 100644 --- a/cliff/tests/test_commandmanager.py +++ b/cliff/tests/test_commandmanager.py @@ -13,6 +13,7 @@ import mock import testscenarios +from cliff import command from cliff import commandmanager from cliff.tests import base from cliff.tests import utils @@ -150,3 +151,51 @@ class TestLoad(base.TestBase): iter_entry_points.assert_called_once_with('test') names = [n for n, v in mgr] self.assertEqual(['test cmd'], names) + + +class FauxCommand(command.Command): + + def take_action(self, parsed_args): + return 0 + + +class FauxCommand2(FauxCommand): + pass + + +class TestLegacyCommand(base.TestBase): + + def test_find_legacy(self): + mgr = utils.TestCommandManager(None) + mgr.add_command('new name', FauxCommand) + mgr.add_legacy_command('old name', 'new name') + cmd, name, remaining = mgr.find_command(['old', 'name']) + self.assertIs(cmd, FauxCommand) + self.assertEqual(name, 'old name') + + def test_legacy_overrides_new(self): + mgr = utils.TestCommandManager(None) + mgr.add_command('cmd1', FauxCommand) + mgr.add_command('cmd2', FauxCommand2) + mgr.add_legacy_command('cmd2', 'cmd1') + cmd, name, remaining = mgr.find_command(['cmd2']) + self.assertIs(cmd, FauxCommand) + self.assertEqual(name, 'cmd2') + + def test_no_legacy(self): + mgr = utils.TestCommandManager(None) + mgr.add_command('cmd1', FauxCommand) + self.assertRaises( + ValueError, + mgr.find_command, + ['cmd2'], + ) + + def test_no_command(self): + mgr = utils.TestCommandManager(None) + mgr.add_legacy_command('cmd2', 'cmd1') + self.assertRaises( + ValueError, + mgr.find_command, + ['cmd2'], + )