Skip to content

Commit 44438bf

Browse files
committed
Update argparse.py from CPython v3.12.0
1 parent dd0c393 commit 44438bf

File tree

1 file changed

+49
-15
lines changed

1 file changed

+49
-15
lines changed

Lib/argparse.py

+49-15
Original file line numberDiff line numberDiff line change
@@ -345,21 +345,22 @@ def _format_usage(self, usage, actions, groups, prefix):
345345
def get_lines(parts, indent, prefix=None):
346346
lines = []
347347
line = []
348+
indent_length = len(indent)
348349
if prefix is not None:
349350
line_len = len(prefix) - 1
350351
else:
351-
line_len = len(indent) - 1
352+
line_len = indent_length - 1
352353
for part in parts:
353354
if line_len + 1 + len(part) > text_width and line:
354355
lines.append(indent + ' '.join(line))
355356
line = []
356-
line_len = len(indent) - 1
357+
line_len = indent_length - 1
357358
line.append(part)
358359
line_len += len(part) + 1
359360
if line:
360361
lines.append(indent + ' '.join(line))
361362
if prefix is not None:
362-
lines[0] = lines[0][len(indent):]
363+
lines[0] = lines[0][indent_length:]
363364
return lines
364365

365366
# if prog is short, follow it with optionals or positionals
@@ -403,10 +404,18 @@ def _format_actions_usage(self, actions, groups):
403404
except ValueError:
404405
continue
405406
else:
406-
end = start + len(group._group_actions)
407+
group_action_count = len(group._group_actions)
408+
end = start + group_action_count
407409
if actions[start:end] == group._group_actions:
410+
411+
suppressed_actions_count = 0
408412
for action in group._group_actions:
409413
group_actions.add(action)
414+
if action.help is SUPPRESS:
415+
suppressed_actions_count += 1
416+
417+
exposed_actions_count = group_action_count - suppressed_actions_count
418+
410419
if not group.required:
411420
if start in inserts:
412421
inserts[start] += ' ['
@@ -416,7 +425,7 @@ def _format_actions_usage(self, actions, groups):
416425
inserts[end] += ']'
417426
else:
418427
inserts[end] = ']'
419-
else:
428+
elif exposed_actions_count > 1:
420429
if start in inserts:
421430
inserts[start] += ' ('
422431
else:
@@ -490,7 +499,6 @@ def _format_actions_usage(self, actions, groups):
490499
text = _re.sub(r'(%s) ' % open, r'\1', text)
491500
text = _re.sub(r' (%s)' % close, r'\1', text)
492501
text = _re.sub(r'%s *%s' % (open, close), r'', text)
493-
text = _re.sub(r'\(([^|]*)\)', r'\1', text)
494502
text = text.strip()
495503

496504
# return the text
@@ -875,16 +883,19 @@ def __call__(self, parser, namespace, values, option_string=None):
875883
raise NotImplementedError(_('.__call__() not defined'))
876884

877885

886+
# FIXME: remove together with `BooleanOptionalAction` deprecated arguments.
887+
_deprecated_default = object()
888+
878889
class BooleanOptionalAction(Action):
879890
def __init__(self,
880891
option_strings,
881892
dest,
882893
default=None,
883-
type=None,
884-
choices=None,
894+
type=_deprecated_default,
895+
choices=_deprecated_default,
885896
required=False,
886897
help=None,
887-
metavar=None):
898+
metavar=_deprecated_default):
888899

889900
_option_strings = []
890901
for option_string in option_strings:
@@ -894,6 +905,24 @@ def __init__(self,
894905
option_string = '--no-' + option_string[2:]
895906
_option_strings.append(option_string)
896907

908+
# We need `_deprecated` special value to ban explicit arguments that
909+
# match default value. Like:
910+
# parser.add_argument('-f', action=BooleanOptionalAction, type=int)
911+
for field_name in ('type', 'choices', 'metavar'):
912+
if locals()[field_name] is not _deprecated_default:
913+
warnings._deprecated(
914+
field_name,
915+
"{name!r} is deprecated as of Python 3.12 and will be "
916+
"removed in Python {remove}.",
917+
remove=(3, 14))
918+
919+
if type is _deprecated_default:
920+
type = None
921+
if choices is _deprecated_default:
922+
choices = None
923+
if metavar is _deprecated_default:
924+
metavar = None
925+
897926
super().__init__(
898927
option_strings=_option_strings,
899928
dest=dest,
@@ -2165,7 +2194,9 @@ def _read_args_from_files(self, arg_strings):
21652194
# replace arguments referencing files with the file content
21662195
else:
21672196
try:
2168-
with open(arg_string[1:]) as args_file:
2197+
with open(arg_string[1:],
2198+
encoding=_sys.getfilesystemencoding(),
2199+
errors=_sys.getfilesystemencodeerrors()) as args_file:
21692200
arg_strings = []
21702201
for arg_line in args_file.read().splitlines():
21712202
for arg in self.convert_arg_line_to_args(arg_line):
@@ -2479,9 +2510,11 @@ def _get_values(self, action, arg_strings):
24792510
not action.option_strings):
24802511
if action.default is not None:
24812512
value = action.default
2513+
self._check_value(action, value)
24822514
else:
2515+
# since arg_strings is always [] at this point
2516+
# there is no need to use self._check_value(action, value)
24832517
value = arg_strings
2484-
self._check_value(action, value)
24852518

24862519
# single argument or optional argument produces a single value
24872520
elif len(arg_strings) == 1 and action.nargs in [None, OPTIONAL]:
@@ -2523,7 +2556,6 @@ def _get_value(self, action, arg_string):
25232556

25242557
# ArgumentTypeErrors indicate errors
25252558
except ArgumentTypeError as err:
2526-
name = getattr(action.type, '__name__', repr(action.type))
25272559
msg = str(err)
25282560
raise ArgumentError(action, msg)
25292561

@@ -2595,9 +2627,11 @@ def print_help(self, file=None):
25952627

25962628
def _print_message(self, message, file=None):
25972629
if message:
2598-
if file is None:
2599-
file = _sys.stderr
2600-
file.write(message)
2630+
file = file or _sys.stderr
2631+
try:
2632+
file.write(message)
2633+
except (AttributeError, OSError):
2634+
pass
26012635

26022636
# ===============
26032637
# Exiting methods

0 commit comments

Comments
 (0)