Skip to content

Commit f1a6d22

Browse files
[3.13] gh-121151: argparse: Fix wrapping of long usage text of arguments inside a mutually exclusive groups (GH-121159) (#122777)
gh-121151: argparse: Fix wrapping of long usage text of arguments inside a mutually exclusive groups (GH-121159) (cherry picked from commit 013a092) Co-authored-by: Ali Hamdan <[email protected]>
1 parent 8c01b34 commit f1a6d22

File tree

3 files changed

+36
-7
lines changed

3 files changed

+36
-7
lines changed

Lib/argparse.py

+12-3
Original file line numberDiff line numberDiff line change
@@ -447,15 +447,24 @@ def _get_actions_usage_parts(self, actions, groups):
447447
parts.append(part)
448448

449449
# group mutually exclusive actions
450+
inserted_separators_indices = set()
450451
for start, end in sorted(inserts, reverse=True):
451452
group = inserts[start, end]
452453
group_parts = [item for item in parts[start:end] if item is not None]
454+
group_size = len(group_parts)
453455
if group.required:
454-
open, close = "()" if len(group_parts) > 1 else ("", "")
456+
open, close = "()" if group_size > 1 else ("", "")
455457
else:
456458
open, close = "[]"
457-
parts[start] = open + " | ".join(group_parts) + close
458-
for i in range(start + 1, end):
459+
group_parts[0] = open + group_parts[0]
460+
group_parts[-1] = group_parts[-1] + close
461+
for i, part in enumerate(group_parts[:-1], start=start):
462+
# insert a separator if not already done in a nested group
463+
if i not in inserted_separators_indices:
464+
parts[i] = part + ' |'
465+
inserted_separators_indices.add(i)
466+
parts[start + group_size - 1] = group_parts[-1]
467+
for i in range(start + group_size, end):
459468
parts[i] = None
460469

461470
# return the usage parts

Lib/test/test_argparse.py

+22-4
Original file line numberDiff line numberDiff line change
@@ -3002,12 +3002,12 @@ def get_parser(self, required=None):
30023002
]
30033003

30043004
usage_when_not_required = '''\
3005-
usage: PROG [-h] [--abcde ABCDE] [--fghij FGHIJ]
3006-
[--klmno KLMNO | --pqrst PQRST]
3005+
usage: PROG [-h] [--abcde ABCDE] [--fghij FGHIJ] [--klmno KLMNO |
3006+
--pqrst PQRST]
30073007
'''
30083008
usage_when_required = '''\
3009-
usage: PROG [-h] [--abcde ABCDE] [--fghij FGHIJ]
3010-
(--klmno KLMNO | --pqrst PQRST)
3009+
usage: PROG [-h] [--abcde ABCDE] [--fghij FGHIJ] (--klmno KLMNO |
3010+
--pqrst PQRST)
30113011
'''
30123012
help = '''\
30133013
@@ -4390,6 +4390,24 @@ def test_nested_mutex_groups(self):
43904390
''')
43914391
self.assertEqual(parser.format_usage(), usage)
43924392

4393+
def test_long_mutex_groups_wrap(self):
4394+
parser = argparse.ArgumentParser(prog='PROG')
4395+
g = parser.add_mutually_exclusive_group()
4396+
g.add_argument('--op1', metavar='MET', nargs='?')
4397+
g.add_argument('--op2', metavar=('MET1', 'MET2'), nargs='*')
4398+
g.add_argument('--op3', nargs='*')
4399+
g.add_argument('--op4', metavar=('MET1', 'MET2'), nargs='+')
4400+
g.add_argument('--op5', nargs='+')
4401+
g.add_argument('--op6', nargs=3)
4402+
g.add_argument('--op7', metavar=('MET1', 'MET2', 'MET3'), nargs=3)
4403+
4404+
usage = textwrap.dedent('''\
4405+
usage: PROG [-h] [--op1 [MET] | --op2 [MET1 [MET2 ...]] | --op3 [OP3 ...] |
4406+
--op4 MET1 [MET2 ...] | --op5 OP5 [OP5 ...] | --op6 OP6 OP6 OP6 |
4407+
--op7 MET1 MET2 MET3]
4408+
''')
4409+
self.assertEqual(parser.format_usage(), usage)
4410+
43934411

43944412
class TestHelpVariableExpansion(HelpTestCase):
43954413
"""Test that variables are expanded properly in help messages"""
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix wrapping of long usage text of arguments inside a mutually exclusive
2+
group in :mod:`argparse`.

0 commit comments

Comments
 (0)