@@ -358,7 +358,7 @@ def _format_usage(self, usage, actions, groups, prefix):
358358 # keep optionals and positionals together to preserve
359359 # mutually exclusive group formatting (gh-75949)
360360 all_actions = optionals + positionals
361- parts , pos_start = self ._get_actions_usage_parts (
361+ parts , pos_start = self ._get_actions_usage_parts_with_split (
362362 all_actions , groups , len (optionals )
363363 )
364364 opt_parts = parts [:pos_start ]
@@ -420,13 +420,23 @@ def get_lines(parts, indent, prefix=None):
420420 return f'{ t .usage } { prefix } { t .reset } { usage } \n \n '
421421
422422 def _format_actions_usage (self , actions , groups ):
423- parts , _ = self ._get_actions_usage_parts (actions , groups )
424- return ' ' .join (parts )
423+ return ' ' .join (self ._get_actions_usage_parts (actions , groups ))
425424
426425 def _is_long_option (self , string ):
427426 return len (string ) > 2
428427
429- def _get_actions_usage_parts (self , actions , groups , opt_count = None ):
428+ def _get_actions_usage_parts (self , actions , groups ):
429+ parts , _ = self ._get_actions_usage_parts_with_split (actions , groups )
430+ return parts
431+
432+ def _get_actions_usage_parts_with_split (self , actions , groups , opt_count = None ):
433+ """Get usage parts with split index for optionals/positionals.
434+
435+ Returns (parts, pos_start) where pos_start is the index in parts
436+ where positionals begin. When opt_count is None, pos_start is None.
437+ This preserves mutually exclusive group formatting across the
438+ optionals/positionals boundary (gh-75949).
439+ """
430440 # find group indices and identify actions in groups
431441 group_actions = set ()
432442 inserts = {}
0 commit comments