Kaydet (Commit) fd311a71 authored tarafından Steven Bethard's avatar Steven Bethard

Add subparser aliases for argparse. Resolves issue 9324. Approved by Georg for…

Add subparser aliases for argparse. Resolves issue 9324. Approved by Georg for beta2 on the tracker.
üst 04129748
......@@ -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
......
......@@ -84,6 +84,8 @@ Build
- The Windows build now uses Tcl/Tk 8.5.9 and sqlite3 3.7.4.
- Issue #9234: argparse supports alias names for subparsers.
What's New in Python 3.2 Beta 1?
================================
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment