mirror of
https://github.com/python/cpython.git
synced 2025-12-08 06:10:17 +00:00
gh-142346: Fix usage formatting for mutually exclusive groups in argparse (GH-142381)
Support groups preceded by positional arguments or followed or intermixed with other optional arguments. Support empty groups.
This commit is contained in:
parent
d6d850df89
commit
1db9f56bff
3 changed files with 126 additions and 141 deletions
|
|
@ -3398,12 +3398,11 @@ def test_help_subparser_all_mutually_exclusive_group_members_suppressed(self):
|
|||
'''
|
||||
self.assertEqual(cmd_foo.format_help(), textwrap.dedent(expected))
|
||||
|
||||
def test_empty_group(self):
|
||||
def test_usage_empty_group(self):
|
||||
# See issue 26952
|
||||
parser = argparse.ArgumentParser()
|
||||
parser = ErrorRaisingArgumentParser(prog='PROG')
|
||||
group = parser.add_mutually_exclusive_group()
|
||||
with self.assertRaises(ValueError):
|
||||
parser.parse_args(['-h'])
|
||||
self.assertEqual(parser.format_usage(), 'usage: PROG [-h]\n')
|
||||
|
||||
def test_nested_mutex_groups(self):
|
||||
parser = argparse.ArgumentParser(prog='PROG')
|
||||
|
|
@ -3671,25 +3670,29 @@ def get_parser(self, required):
|
|||
group.add_argument('-b', action='store_true', help='b help')
|
||||
parser.add_argument('-y', action='store_true', help='y help')
|
||||
group.add_argument('-c', action='store_true', help='c help')
|
||||
parser.add_argument('-z', action='store_true', help='z help')
|
||||
return parser
|
||||
|
||||
failures = ['-a -b', '-b -c', '-a -c', '-a -b -c']
|
||||
successes = [
|
||||
('-a', NS(a=True, b=False, c=False, x=False, y=False)),
|
||||
('-b', NS(a=False, b=True, c=False, x=False, y=False)),
|
||||
('-c', NS(a=False, b=False, c=True, x=False, y=False)),
|
||||
('-a -x', NS(a=True, b=False, c=False, x=True, y=False)),
|
||||
('-y -b', NS(a=False, b=True, c=False, x=False, y=True)),
|
||||
('-x -y -c', NS(a=False, b=False, c=True, x=True, y=True)),
|
||||
('-a', NS(a=True, b=False, c=False, x=False, y=False, z=False)),
|
||||
('-b', NS(a=False, b=True, c=False, x=False, y=False, z=False)),
|
||||
('-c', NS(a=False, b=False, c=True, x=False, y=False, z=False)),
|
||||
('-a -x', NS(a=True, b=False, c=False, x=True, y=False, z=False)),
|
||||
('-y -b', NS(a=False, b=True, c=False, x=False, y=True, z=False)),
|
||||
('-x -y -c', NS(a=False, b=False, c=True, x=True, y=True, z=False)),
|
||||
]
|
||||
successes_when_not_required = [
|
||||
('', NS(a=False, b=False, c=False, x=False, y=False)),
|
||||
('-x', NS(a=False, b=False, c=False, x=True, y=False)),
|
||||
('-y', NS(a=False, b=False, c=False, x=False, y=True)),
|
||||
('', NS(a=False, b=False, c=False, x=False, y=False, z=False)),
|
||||
('-x', NS(a=False, b=False, c=False, x=True, y=False, z=False)),
|
||||
('-y', NS(a=False, b=False, c=False, x=False, y=True, z=False)),
|
||||
]
|
||||
|
||||
usage_when_required = usage_when_not_required = '''\
|
||||
usage: PROG [-h] [-x] [-a] [-b] [-y] [-c]
|
||||
usage_when_not_required = '''\
|
||||
usage: PROG [-h] [-x] [-a | -b | -c] [-y] [-z]
|
||||
'''
|
||||
usage_when_required = '''\
|
||||
usage: PROG [-h] [-x] (-a | -b | -c) [-y] [-z]
|
||||
'''
|
||||
help = '''\
|
||||
|
||||
|
|
@ -3700,6 +3703,7 @@ def get_parser(self, required):
|
|||
-b b help
|
||||
-y y help
|
||||
-c c help
|
||||
-z z help
|
||||
'''
|
||||
|
||||
|
||||
|
|
@ -3753,23 +3757,27 @@ def get_parser(self, required):
|
|||
group.add_argument('a', nargs='?', help='a help')
|
||||
group.add_argument('-b', action='store_true', help='b help')
|
||||
group.add_argument('-c', action='store_true', help='c help')
|
||||
parser.add_argument('-z', action='store_true', help='z help')
|
||||
return parser
|
||||
|
||||
failures = ['X A -b', '-b -c', '-c X A']
|
||||
successes = [
|
||||
('X A', NS(a='A', b=False, c=False, x='X', y=False)),
|
||||
('X -b', NS(a=None, b=True, c=False, x='X', y=False)),
|
||||
('X -c', NS(a=None, b=False, c=True, x='X', y=False)),
|
||||
('X A -y', NS(a='A', b=False, c=False, x='X', y=True)),
|
||||
('X -y -b', NS(a=None, b=True, c=False, x='X', y=True)),
|
||||
('X A', NS(a='A', b=False, c=False, x='X', y=False, z=False)),
|
||||
('X -b', NS(a=None, b=True, c=False, x='X', y=False, z=False)),
|
||||
('X -c', NS(a=None, b=False, c=True, x='X', y=False, z=False)),
|
||||
('X A -y', NS(a='A', b=False, c=False, x='X', y=True, z=False)),
|
||||
('X -y -b', NS(a=None, b=True, c=False, x='X', y=True, z=False)),
|
||||
]
|
||||
successes_when_not_required = [
|
||||
('X', NS(a=None, b=False, c=False, x='X', y=False)),
|
||||
('X -y', NS(a=None, b=False, c=False, x='X', y=True)),
|
||||
('X', NS(a=None, b=False, c=False, x='X', y=False, z=False)),
|
||||
('X -y', NS(a=None, b=False, c=False, x='X', y=True, z=False)),
|
||||
]
|
||||
|
||||
usage_when_required = usage_when_not_required = '''\
|
||||
usage: PROG [-h] [-y] [-b] [-c] x [a]
|
||||
usage_when_not_required = '''\
|
||||
usage: PROG [-h] [-y] [-z] x [-b | -c | a]
|
||||
'''
|
||||
usage_when_required = '''\
|
||||
usage: PROG [-h] [-y] [-z] x (-b | -c | a)
|
||||
'''
|
||||
help = '''\
|
||||
|
||||
|
|
@ -3782,6 +3790,7 @@ def get_parser(self, required):
|
|||
-y y help
|
||||
-b b help
|
||||
-c c help
|
||||
-z z help
|
||||
'''
|
||||
|
||||
|
||||
|
|
@ -4989,9 +4998,9 @@ def test_mutex_groups_with_mixed_optionals_positionals_wrap(self):
|
|||
g.add_argument('positional', nargs='?')
|
||||
|
||||
usage = textwrap.dedent('''\
|
||||
usage: PROG [-h] [-v | -q | -x [EXTRA_LONG_OPTION_NAME] |
|
||||
-y [YET_ANOTHER_LONG_OPTION] |
|
||||
positional]
|
||||
usage: PROG [-h]
|
||||
[-v | -q | -x [EXTRA_LONG_OPTION_NAME] |
|
||||
-y [YET_ANOTHER_LONG_OPTION] | positional]
|
||||
''')
|
||||
self.assertEqual(parser.format_usage(), usage)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue