Add subparser aliases for argparse. Resolves issue 9324. Approved by Georg for beta2 on the tracker.
This commit is contained in:
parent
04129748ae
commit
fd311a712d
|
@ -1428,6 +1428,16 @@ Sub-commands
|
|||
|
||||
{foo,bar} additional help
|
||||
|
||||
Furthermore, ``add_parser`` supports an additional ``aliases`` argument,
|
||||
which allows multiple strings to refer to the same subparser. This example,
|
||||
like ``svn``, aliases ``co`` as a shorthand for ``checkout``::
|
||||
|
||||
>>> parser = argparse.ArgumentParser()
|
||||
>>> subparsers = parser.add_subparsers()
|
||||
>>> checkout = subparsers.add_parser('checkout', aliases=['co'])
|
||||
>>> checkout.add_argument('foo')
|
||||
>>> parser.parse_args(['co', 'bar'])
|
||||
Namespace(foo='bar')
|
||||
|
||||
One particularly effective way of handling sub-commands is to combine the use
|
||||
of the :meth:`add_subparsers` method with calls to :meth:`set_defaults` so
|
||||
|
@ -1466,7 +1476,7 @@ Sub-commands
|
|||
>>> args.func(args)
|
||||
((XYZYX))
|
||||
|
||||
This way, you can let :meth:`parse_args` does the job of calling the
|
||||
This way, you can let :meth:`parse_args` do the job of calling the
|
||||
appropriate function after argument parsing is complete. Associating
|
||||
functions with actions like this is typically the easiest way to handle the
|
||||
different actions for each of your subparsers. However, if it is necessary
|
||||
|
|
|
@ -1023,9 +1023,13 @@ class _SubParsersAction(Action):
|
|||
|
||||
class _ChoicesPseudoAction(Action):
|
||||
|
||||
def __init__(self, name, help):
|
||||
def __init__(self, name, aliases, help):
|
||||
metavar = dest = name
|
||||
if aliases:
|
||||
metavar += ' (%s)' % ', '.join(aliases)
|
||||
sup = super(_SubParsersAction._ChoicesPseudoAction, self)
|
||||
sup.__init__(option_strings=[], dest=name, help=help)
|
||||
sup.__init__(option_strings=[], dest=dest, help=help,
|
||||
metavar=metavar)
|
||||
|
||||
def __init__(self,
|
||||
option_strings,
|
||||
|
@ -1053,15 +1057,22 @@ class _SubParsersAction(Action):
|
|||
if kwargs.get('prog') is None:
|
||||
kwargs['prog'] = '%s %s' % (self._prog_prefix, name)
|
||||
|
||||
aliases = kwargs.pop('aliases', ())
|
||||
|
||||
# create a pseudo-action to hold the choice help
|
||||
if 'help' in kwargs:
|
||||
help = kwargs.pop('help')
|
||||
choice_action = self._ChoicesPseudoAction(name, help)
|
||||
choice_action = self._ChoicesPseudoAction(name, aliases, help)
|
||||
self._choices_actions.append(choice_action)
|
||||
|
||||
# create the parser and add it to the map
|
||||
parser = self._parser_class(**kwargs)
|
||||
self._name_parser_map[name] = parser
|
||||
|
||||
# make parser available under aliases also
|
||||
for alias in aliases:
|
||||
self._name_parser_map[alias] = parser
|
||||
|
||||
return parser
|
||||
|
||||
def _get_subactions(self):
|
||||
|
|
|
@ -1708,7 +1708,8 @@ class TestAddSubparsers(TestCase):
|
|||
def assertArgumentParserError(self, *args, **kwargs):
|
||||
self.assertRaises(ArgumentParserError, *args, **kwargs)
|
||||
|
||||
def _get_parser(self, subparser_help=False, prefix_chars=None):
|
||||
def _get_parser(self, subparser_help=False, prefix_chars=None,
|
||||
aliases=False):
|
||||
# create a parser with a subparsers argument
|
||||
if prefix_chars:
|
||||
parser = ErrorRaisingArgumentParser(
|
||||
|
@ -1724,13 +1725,21 @@ class TestAddSubparsers(TestCase):
|
|||
'bar', type=float, help='bar help')
|
||||
|
||||
# check that only one subparsers argument can be added
|
||||
subparsers = parser.add_subparsers(help='command help')
|
||||
subparsers_kwargs = {}
|
||||
if aliases:
|
||||
subparsers_kwargs['metavar'] = 'COMMAND'
|
||||
subparsers_kwargs['title'] = 'commands'
|
||||
else:
|
||||
subparsers_kwargs['help'] = 'command help'
|
||||
subparsers = parser.add_subparsers(**subparsers_kwargs)
|
||||
self.assertArgumentParserError(parser.add_subparsers)
|
||||
|
||||
# add first sub-parser
|
||||
parser1_kwargs = dict(description='1 description')
|
||||
if subparser_help:
|
||||
parser1_kwargs['help'] = '1 help'
|
||||
if aliases:
|
||||
parser1_kwargs['aliases'] = ['1alias1', '1alias2']
|
||||
parser1 = subparsers.add_parser('1', **parser1_kwargs)
|
||||
parser1.add_argument('-w', type=int, help='w help')
|
||||
parser1.add_argument('x', choices='abc', help='x help')
|
||||
|
@ -1947,6 +1956,44 @@ class TestAddSubparsers(TestCase):
|
|||
-y {1,2,3} y help
|
||||
'''))
|
||||
|
||||
def test_alias_invocation(self):
|
||||
parser = self._get_parser(aliases=True)
|
||||
self.assertEqual(
|
||||
parser.parse_known_args('0.5 1alias1 b'.split()),
|
||||
(NS(foo=False, bar=0.5, w=None, x='b'), []),
|
||||
)
|
||||
self.assertEqual(
|
||||
parser.parse_known_args('0.5 1alias2 b'.split()),
|
||||
(NS(foo=False, bar=0.5, w=None, x='b'), []),
|
||||
)
|
||||
|
||||
def test_error_alias_invocation(self):
|
||||
parser = self._get_parser(aliases=True)
|
||||
self.assertArgumentParserError(parser.parse_args,
|
||||
'0.5 1alias3 b'.split())
|
||||
|
||||
def test_alias_help(self):
|
||||
parser = self._get_parser(aliases=True, subparser_help=True)
|
||||
self.maxDiff = None
|
||||
self.assertEqual(parser.format_help(), textwrap.dedent("""\
|
||||
usage: PROG [-h] [--foo] bar COMMAND ...
|
||||
|
||||
main description
|
||||
|
||||
positional arguments:
|
||||
bar bar help
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
--foo foo help
|
||||
|
||||
commands:
|
||||
COMMAND
|
||||
1 (1alias1, 1alias2)
|
||||
1 help
|
||||
2 2 help
|
||||
"""))
|
||||
|
||||
# ============
|
||||
# Groups tests
|
||||
# ============
|
||||
|
|
|
@ -734,6 +734,7 @@ Hajime Saitou
|
|||
George Sakkis
|
||||
Rich Salz
|
||||
Kevin Samborn
|
||||
Adrian Sampson
|
||||
Ilya Sandler
|
||||
Mark Sapiro
|
||||
Ty Sarna
|
||||
|
|
Loading…
Reference in New Issue