From 95c749d55e58f78047f719f3a57d37e5f7acf140 Mon Sep 17 00:00:00 2001 From: Doug Hellmann Date: Thu, 25 May 2017 19:04:42 -0400 Subject: [PATCH] add before and after hooks Add hooks that are called before and after the take_action() method of the command. Change-Id: Id6527dfe0946c0ab169fc165b84d40f3ff95e08c Signed-off-by: Doug Hellmann --- cliff/command.py | 7 ++++++- cliff/hooks.py | 22 ++++++++++++++++++++++ cliff/tests/test_command_hooks.py | 19 +++++++++++++++++++ demoapp/cliffdemo/hook.py | 8 +++++++- doc/source/user/demoapp.rst | 6 ++++++ 5 files changed, 60 insertions(+), 2 deletions(-) diff --git a/cliff/command.py b/cliff/command.py index 6a4af11f..ac5e23a4 100644 --- a/cliff/command.py +++ b/cliff/command.py @@ -133,7 +133,12 @@ class Command(object): Return the value returned by :meth:`take_action` or 0. """ - return self.take_action(parsed_args) or 0 + for hook in self._hooks: + hook.obj.before(parsed_args) + return_code = self.take_action(parsed_args) or 0 + for hook in self._hooks: + hook.obj.after(parsed_args, return_code) + return return_code class _SmartHelpFormatter(_argparse.HelpFormatter): diff --git a/cliff/hooks.py b/cliff/hooks.py index b41cef1d..9af627c0 100644 --- a/cliff/hooks.py +++ b/cliff/hooks.py @@ -41,3 +41,25 @@ class CommandHook(object): def get_epilog(self): "Return text to add to the command help epilog." return '' + + @abc.abstractmethod + def before(self, parsed_args): + """Called before the command's take_action() method. + + Any return value is ignored. + + :param parsed_args: The arguments to the command. + :paramtype parsed_args: argparse.Namespace + """ + + @abc.abstractmethod + def after(self, parsed_args, return_code): + """Called after the command's take_action() method. + + Any return value is ignored. + + :param parsed_args: The arguments to the command. + :paramtype parsed_args: argparse.Namespace + :param return_code: The value returned from take_action(). + :paramtype return_code: int + """ diff --git a/cliff/tests/test_command_hooks.py b/cliff/tests/test_command_hooks.py index bb69d115..0d9c8b06 100644 --- a/cliff/tests/test_command_hooks.py +++ b/cliff/tests/test_command_hooks.py @@ -62,6 +62,9 @@ class TestCommand(command.Command): class TestHook(hooks.CommandHook): + _before_called = False + _after_called = False + def get_parser(self, parser): parser.add_argument('--added-by-hook') return parser @@ -69,6 +72,12 @@ class TestHook(hooks.CommandHook): def get_epilog(self): return 'hook epilog' + def before(self, parsed_args): + self._before_called = True + + def after(self, parsed_args, return_code): + self._after_called = True + class TestCommandLoadHooks(base.TestBase): @@ -112,3 +121,13 @@ class TestHooks(base.TestBase): def test_get_epilog(self): results = self.cmd.get_epilog() self.assertIn('hook epilog', results) + + def test_before(self): + self.assertFalse(self.hook._before_called) + self.cmd.run(None) + self.assertTrue(self.hook._before_called) + + def test_after(self): + self.assertFalse(self.hook._after_called) + self.cmd.run(None) + self.assertTrue(self.hook._after_called) diff --git a/demoapp/cliffdemo/hook.py b/demoapp/cliffdemo/hook.py index 405ff331..ee39602e 100644 --- a/demoapp/cliffdemo/hook.py +++ b/demoapp/cliffdemo/hook.py @@ -24,7 +24,7 @@ class Hooked(Command): log = logging.getLogger(__name__) def take_action(self, parsed_args): - self.app.stdout.write('this command has an extension') + self.app.stdout.write('this command has an extension\n') class Hook(CommandHook): @@ -42,3 +42,9 @@ class Hook(CommandHook): def get_epilog(self): return 'extension epilog text' + + def before(self, parsed_args): + self.cmd.app.stdout.write('before\n') + + def after(self, parsed_args, return_code): + self.cmd.app.stdout.write('after\n') diff --git a/doc/source/user/demoapp.rst b/doc/source/user/demoapp.rst index 35e2586c..328b732d 100644 --- a/doc/source/user/demoapp.rst +++ b/doc/source/user/demoapp.rst @@ -295,6 +295,12 @@ single ``--added-by-hook`` option. extension epilog text + (.venv)$ cliffdemo hooked + sample hook get_parser() + before + this command has an extension + after + .. seealso:: :class:`cliff.hooks.CommandHook` -- The API for command hooks.