From 7fdd7cb4c50a33233a7052fc345221cc7b935889 Mon Sep 17 00:00:00 2001 From: Doug Hellmann Date: Wed, 9 Sep 2020 09:01:56 -0400 Subject: change help action to use its own exception for exit Provide a new exception class for the help action to use to indicate that the app should exit, instead of calling sys.exit(). This allows argument parsing errors in interactive mode to print help without exiting the entire application, while still being treated as a short-cut to avoid every command plugin having to process argument errors itself. Change-Id: If882b305ff9186f97ece6c77ef8c1b888c24a72d Story: 2008071 Signed-off-by: Doug Hellmann --- cliff/app.py | 2 ++ cliff/help.py | 14 ++++++++++++-- cliff/tests/test_help.py | 12 ++++++------ 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/cliff/app.py b/cliff/app.py index a3a0657..8b8217c 100644 --- a/cliff/app.py +++ b/cliff/app.py @@ -400,6 +400,8 @@ class App(object): cmd_parser = cmd.get_parser(full_name) parsed_args = cmd_parser.parse_args(sub_argv) result = cmd.run(parsed_args) + except help.HelpExit: + result = 0 except SystemExit as ex: raise cmd2.exceptions.Cmd2ArgparseError from ex except Exception as err: diff --git a/cliff/help.py b/cliff/help.py index 92e4c2f..cb858fd 100644 --- a/cliff/help.py +++ b/cliff/help.py @@ -12,14 +12,24 @@ import argparse import inspect -import sys import traceback from . import command from . import utils +class HelpExit(SystemExit): + """Special exception type to trigger quick exit from the application + + We subclass from SystemExit to preserve API compatibility for + anything that used to catch SystemExit, but use a different class + so that cliff's Application can tell the difference between + something trying to hard-exit and help saying it's done. + """ + + class HelpAction(argparse.Action): + """Provide a custom action so the -h and --help options to the main app will print a list of the commands. @@ -65,7 +75,7 @@ class HelpAction(argparse.Action): else: dist_info = '' app.stdout.write(' %-13s %s%s\n' % (name, one_liner, dist_info)) - sys.exit(0) + raise HelpExit() class HelpCommand(command.Command): diff --git a/cliff/tests/test_help.py b/cliff/tests/test_help.py index 1b86cba..8b40d58 100644 --- a/cliff/tests/test_help.py +++ b/cliff/tests/test_help.py @@ -42,7 +42,7 @@ class TestHelp(base.TestBase): parsed_args = parser.parse_args(['one']) try: help_cmd.run(parsed_args) - except SystemExit: + except help.HelpExit: pass self.assertEqual('TestParser', stdout.getvalue()) @@ -60,7 +60,7 @@ class TestHelp(base.TestBase): parsed_args = parser.parse_args(['t']) try: help_cmd.run(parsed_args) - except SystemExit: + except help.HelpExit: pass help_output = stdout.getvalue() self.assertIn('Command "t" matches:', help_output) @@ -99,7 +99,7 @@ class TestHelp(base.TestBase): parsed_args = parser.parse_args([]) try: help_cmd.run(parsed_args) - except SystemExit: + except help.HelpExit: pass help_text = stdout.getvalue() basecommand = os.path.split(sys.argv[0])[1] @@ -122,7 +122,7 @@ class TestHelp(base.TestBase): app.NAME = 'test' try: app.run(['--help']) - except SystemExit: + except help.HelpExit: pass help_output = stdout.getvalue() self.assertIn('two words', help_output) @@ -144,7 +144,7 @@ class TestHelp(base.TestBase): parsed_args = parser.parse_args([]) try: help_cmd.run(parsed_args) - except SystemExit: + except help.HelpExit: pass help_output = stdout.getvalue() self.assertIn('Commands:', help_output) @@ -166,7 +166,7 @@ class TestHelp(base.TestBase): parsed_args = parser.parse_args([]) try: help_cmd.run(parsed_args) - except SystemExit: + except help.HelpExit: pass help_output = stdout.getvalue() self.assertIn('Commands:', help_output) -- cgit v1.2.1