From d82f48a42ffb46f7862e3fa9ac92a634bd2fad67 Mon Sep 17 00:00:00 2001 From: Thomas Adamcik Date: Thu, 14 Nov 2013 19:50:20 +0100 Subject: [PATCH] commands: Internalise handling of help action This means help will always be handled by the root command. Additionally this adds an exit helper. --- mopidy/utils/command.py | 29 +++++++++++++++++++++++++++-- tests/utils/command_test.py | 10 ++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/mopidy/utils/command.py b/mopidy/utils/command.py index bd2c97e6..df33b444 100644 --- a/mopidy/utils/command.py +++ b/mopidy/utils/command.py @@ -18,6 +18,23 @@ class ArgumentParser(argparse.ArgumentParser): raise CommandError(message) +class _HelpError(Exception): + """Internal exception used to trigger help code path.""" + + +class _HelpAction(argparse.Action): + def __init__(self, option_strings, dest=None, help=None): + super(_HelpAction, self).__init__( + option_strings=option_strings, + dest=dest or argparse.SUPPRESS, + default=argparse.SUPPRESS, + nargs=0, + help=help) + + def __call__(self, parser, namespace, values, option_string=None): + raise _HelpError() + + class Command(object): def __init__(self): self._children = collections.OrderedDict() @@ -27,6 +44,7 @@ class Command(object): def _build(self): actions = [] parser = ArgumentParser(add_help=False) + parser.register('action', 'help', _HelpAction) for args, kwargs in self._arguments: actions.append(parser.add_argument(*args, **kwargs)) @@ -44,6 +62,9 @@ class Command(object): def set_defaults(self, **kwargs): self._defaults.update(kwargs) + def exit(self, return_code): + sys.exit(return_code) + def format_usage(self, prog=None): actions = self._build()[1] prog = prog or os.path.basename(sys.argv[0]) @@ -99,8 +120,12 @@ class Command(object): def parse(self, args, prog=None): prog = prog or os.path.basename(sys.argv[0]) - return self._parse( - args, argparse.Namespace(), self._defaults.copy(), prog) + try: + return self._parse( + args, argparse.Namespace(), self._defaults.copy(), prog) + except _HelpError: + print self.format_help(prog) + self.exit(0) def _parse(self, args, namespace, defaults, prog): defaults.update(self._defaults) diff --git a/tests/utils/command_test.py b/tests/utils/command_test.py index 8017a92c..5410e8da 100644 --- a/tests/utils/command_test.py +++ b/tests/utils/command_test.py @@ -197,6 +197,16 @@ class CommandParsingTest(unittest.TestCase): result = cmd.parse(['command']) self.assertEqual(result.foo, 'bar') + def test_help_action_works(self): + cmd = command.Command() + cmd.add_argument('-h', action='help') + cmd.format_help = mock.Mock() + cmd.exit = mock.Mock() + + cmd.parse(['-h']) + cmd.format_help.assert_called_once_with(mock.ANY) + cmd.exit.assert_called_once_with(0) + class UsageTest(unittest.TestCase): @mock.patch('sys.argv')