mirror of
https://github.com/python/cpython.git
synced 2025-12-08 06:10:17 +00:00
GH-75949: Fix argparse dropping '|' in mutually exclusive groups on line wrap (#142312)
This commit is contained in:
parent
61823a5382
commit
5be3405e4e
3 changed files with 49 additions and 4 deletions
|
|
@ -353,8 +353,14 @@ def _format_usage(self, usage, actions, groups, prefix):
|
|||
if len(prefix) + len(self._decolor(usage)) > text_width:
|
||||
|
||||
# break usage into wrappable parts
|
||||
opt_parts = self._get_actions_usage_parts(optionals, groups)
|
||||
pos_parts = self._get_actions_usage_parts(positionals, groups)
|
||||
# keep optionals and positionals together to preserve
|
||||
# mutually exclusive group formatting (gh-75949)
|
||||
all_actions = optionals + positionals
|
||||
parts, pos_start = self._get_actions_usage_parts_with_split(
|
||||
all_actions, groups, len(optionals)
|
||||
)
|
||||
opt_parts = parts[:pos_start]
|
||||
pos_parts = parts[pos_start:]
|
||||
|
||||
# helper for wrapping lines
|
||||
def get_lines(parts, indent, prefix=None):
|
||||
|
|
@ -418,6 +424,17 @@ def _is_long_option(self, string):
|
|||
return len(string) > 2
|
||||
|
||||
def _get_actions_usage_parts(self, actions, groups):
|
||||
parts, _ = self._get_actions_usage_parts_with_split(actions, groups)
|
||||
return parts
|
||||
|
||||
def _get_actions_usage_parts_with_split(self, actions, groups, opt_count=None):
|
||||
"""Get usage parts with split index for optionals/positionals.
|
||||
|
||||
Returns (parts, pos_start) where pos_start is the index in parts
|
||||
where positionals begin. When opt_count is None, pos_start is None.
|
||||
This preserves mutually exclusive group formatting across the
|
||||
optionals/positionals boundary (gh-75949).
|
||||
"""
|
||||
# find group indices and identify actions in groups
|
||||
group_actions = set()
|
||||
inserts = {}
|
||||
|
|
@ -513,8 +530,16 @@ def _get_actions_usage_parts(self, actions, groups):
|
|||
for i in range(start + group_size, end):
|
||||
parts[i] = None
|
||||
|
||||
# return the usage parts
|
||||
return [item for item in parts if item is not None]
|
||||
# if opt_count is provided, calculate where positionals start in
|
||||
# the final parts list (for wrapping onto separate lines).
|
||||
# Count before filtering None entries since indices shift after.
|
||||
if opt_count is not None:
|
||||
pos_start = sum(1 for p in parts[:opt_count] if p is not None)
|
||||
else:
|
||||
pos_start = None
|
||||
|
||||
# return the usage parts and split point (gh-75949)
|
||||
return [item for item in parts if item is not None], pos_start
|
||||
|
||||
def _format_text(self, text):
|
||||
if '%(prog)' in text:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue