-
-
Notifications
You must be signed in to change notification settings - Fork 34.5k
Expand file tree
/
Copy pathargparse.py
More file actions
2832 lines (2362 loc) · 107 KB
/
argparse.py
File metadata and controls
2832 lines (2362 loc) · 107 KB
Edit and raw actions
OlderNewer
1
# Author: Steven J. Bethard <[email protected]>.
2
# New maintainer as of 29 August 2019: Raymond Hettinger <[email protected]>
3
4
"""Command-line parsing library
5
6
This module is an optparse-inspired command-line parsing library that:
7
8
- handles both optional and positional arguments
9
- produces highly informative usage messages
10
- supports parsers that dispatch to sub-parsers
11
12
The following is a simple usage example that sums integers from the
13
command-line and writes the result to a file::
14
15
parser = argparse.ArgumentParser(
16
description='sum the integers at the command line')
17
parser.add_argument(
18
'integers', metavar='int', nargs='+', type=int,
19
help='an integer to be summed')
20
parser.add_argument(
21
'--log',
22
help='the file where the sum should be written')
23
args = parser.parse_args()
24
with (open(args.log, 'w') if args.log is not None
25
else contextlib.nullcontext(sys.stdout)) as log:
26
log.write('%s' % sum(args.integers))
27
28
The module contains the following public classes:
29
30
- ArgumentParser -- The main entry point for command-line parsing. As the
31
example above shows, the add_argument() method is used to populate
32
the parser with actions for optional and positional arguments. Then
33
the parse_args() method is invoked to convert the args at the
34
command-line into an object with attributes.
35
36
- ArgumentError -- The exception raised by ArgumentParser objects when
37
there are errors with the parser's actions. Errors raised while
38
parsing the command-line are caught by ArgumentParser and emitted
39
as command-line messages.
40
41
- FileType -- A factory for defining types of files to be created. As the
42
example above shows, instances of FileType are typically passed as
43
the type= argument of add_argument() calls. Deprecated since
44
Python 3.14.
45
46
- Action -- The base class for parser actions. Typically actions are
47
selected by passing strings like 'store_true' or 'append_const' to
48
the action= argument of add_argument(). However, for greater
49
customization of ArgumentParser actions, subclasses of Action may
50
be defined and passed as the action= argument.
51
52
- HelpFormatter, RawDescriptionHelpFormatter, RawTextHelpFormatter,
53
ArgumentDefaultsHelpFormatter -- Formatter classes which
54
may be passed as the formatter_class= argument to the
55
ArgumentParser constructor. HelpFormatter is the default,
56
RawDescriptionHelpFormatter and RawTextHelpFormatter tell the parser
57
not to change the formatting for help text, and
58
ArgumentDefaultsHelpFormatter adds information about argument defaults
59
to the help.
60
61
All other classes in this module are considered implementation details.
62
(Also note that HelpFormatter and RawDescriptionHelpFormatter are only
63
considered public as object names -- the API of the formatter objects is
64
still considered an implementation detail.)
65
"""
66
67
__all__ = [
68
'ArgumentParser',
69
'ArgumentError',
70
'ArgumentTypeError',
71
'BooleanOptionalAction',
72
'FileType',
73
'HelpFormatter',
74
'ArgumentDefaultsHelpFormatter',
75
'RawDescriptionHelpFormatter',
76
'RawTextHelpFormatter',
77
'MetavarTypeHelpFormatter',
78
'Namespace',
79
'Action',
80
'ONE_OR_MORE',
81
'OPTIONAL',
82
'PARSER',
83
'REMAINDER',
84
'SUPPRESS',
85
'ZERO_OR_MORE',
86
]
87
88
89
import os as _os
90
import re as _re
91
import sys as _sys
92
93
from gettext import gettext as _, ngettext
94
95
SUPPRESS = '==SUPPRESS=='
96
97
OPTIONAL = '?'
98
ZERO_OR_MORE = '*'
99
ONE_OR_MORE = '+'
100
PARSER = 'A...'
101
REMAINDER = '...'
102
_UNRECOGNIZED_ARGS_ATTR = '_unrecognized_args'
103
104
# =============================
105
# Utility functions and classes
106
# =============================
107
108
class _AttributeHolder(object):
109
"""Abstract base class that provides __repr__.
110
111
The __repr__ method returns a string in the format::
112
ClassName(attr=name, attr=name, ...)
113
The attributes are determined either by a class-level attribute,
114
'_kwarg_names', or by inspecting the instance __dict__.
115
"""
116
117
def __repr__(self):
118
type_name = type(self).__name__
119
arg_strings = []
120
star_args = {}
121
for arg in self._get_args():
122
arg_strings.append(repr(arg))
123
for name, value in self._get_kwargs():
124
if name.isidentifier():
125
arg_strings.append('%s=%r' % (name, value))
126
else:
127
star_args[name] = value
128
if star_args:
129
arg_strings.append('**%s' % repr(star_args))
130
return '%s(%s)' % (type_name, ', '.join(arg_strings))
131
132
def _get_kwargs(self):
133
return list(self.__dict__.items())
134
135
def _get_args(self):
136
return []
137
138
139
def _copy_items(items):
140
if items is None:
141
return []
142
# The copy module is used only in the 'append' and 'append_const'
143
# actions, and it is needed only when the default value isn't a list.
144
# Delay its import for speeding up the common case.
145
if type(items) is list:
146
return items[:]
147
import copy
148
return copy.copy(items)
149
150
151
# ===============
152
# Formatting Help
153
# ===============
154
155
156
class HelpFormatter(object):
157
"""Formatter for generating usage messages and argument help strings.
158
159
Only the name of this class is considered a public API. All the methods
160
provided by the class are considered an implementation detail.
161
"""
162
163
def __init__(
164
self,
165
prog,
166
indent_increment=2,
167
max_help_position=24,
168
width=None,
169
):
170
# default setting for width
171
if width is None:
172
import shutil
173
width = shutil.get_terminal_size().columns
174
width -= 2
175
176
self._prog = prog
177
self._indent_increment = indent_increment
178
self._max_help_position = min(max_help_position,
179
max(width - 20, indent_increment * 2))
180
self._width = width
181
182
self._current_indent = 0
183
self._level = 0
184
self._action_max_length = 0
185
186
self._root_section = self._Section(self, None)
187
self._current_section = self._root_section
188
189
self._whitespace_matcher = _re.compile(r'\s+', _re.ASCII)
190
self._long_break_matcher = _re.compile(r'\n\n\n+')
191
192
self._set_color(False)
193
194
def _set_color(self, color):
195
from _colorize import can_colorize, decolor, get_theme
196
197
if color and can_colorize():
198
self._theme = get_theme(force_color=True).argparse
199
self._decolor = decolor
200
else:
201
self._theme = get_theme(force_no_color=True).argparse
202
self._decolor = lambda text: text
203
204
# ===============================
205
# Section and indentation methods
206
# ===============================
207
208
def _indent(self):
209
self._current_indent += self._indent_increment
210
self._level += 1
211
212
def _dedent(self):
213
self._current_indent -= self._indent_increment
214
assert self._current_indent >= 0, 'Indent decreased below 0.'
215
self._level -= 1
216
217
class _Section(object):
218
219
def __init__(self, formatter, parent, heading=None):
220
self.formatter = formatter
221
self.parent = parent
222
self.heading = heading
223
self.items = []
224
225
def format_help(self):
226
# format the indented section
227
if self.parent is not None:
228
self.formatter._indent()
229
join = self.formatter._join_parts
230
item_help = join([func(*args) for func, args in self.items])
231
if self.parent is not None:
232
self.formatter._dedent()
233
234
# return nothing if the section was empty
235
if not item_help:
236
return ''
237
238
# add the heading if the section was non-empty
239
if self.heading is not SUPPRESS and self.heading is not None:
240
current_indent = self.formatter._current_indent
241
heading_text = _('%(heading)s:') % dict(heading=self.heading)
242
t = self.formatter._theme
243
heading = (
244
f'{" " * current_indent}'
245
f'{t.heading}{heading_text}{t.reset}\n'
246
)
247
else:
248
heading = ''
249
250
# join the section-initial newline, the heading and the help
251
return join(['\n', heading, item_help, '\n'])
252
253
def _add_item(self, func, args):
254
self._current_section.items.append((func, args))
255
256
# ========================
257
# Message building methods
258
# ========================
259
260
def start_section(self, heading):
261
self._indent()
262
section = self._Section(self, self._current_section, heading)
263
self._add_item(section.format_help, [])
264
self._current_section = section
265
266
def end_section(self):
267
self._current_section = self._current_section.parent
268
self._dedent()
269
270
def add_text(self, text):
271
if text is not SUPPRESS and text is not None:
272
self._add_item(self._format_text, [text])
273
274
def add_usage(self, usage, actions, groups, prefix=None):
275
if usage is not SUPPRESS:
276
args = usage, actions, groups, prefix
277
self._add_item(self._format_usage, args)
278
279
def add_argument(self, action):
280
if action.help is not SUPPRESS:
281
282
# find all invocations
283
get_invocation = lambda x: self._decolor(self._format_action_invocation(x))
284
invocation_lengths = [len(get_invocation(action)) + self._current_indent]
285
for subaction in self._iter_indented_subactions(action):
286
invocation_lengths.append(len(get_invocation(subaction)) + self._current_indent)
287
288
# update the maximum item length
289
action_length = max(invocation_lengths)
290
self._action_max_length = max(self._action_max_length,
291
action_length)
292
293
# add the item to the list
294
self._add_item(self._format_action, [action])
295
296
def add_arguments(self, actions):
297
for action in actions:
298
self.add_argument(action)
299
300
# =======================
301
# Help-formatting methods
302
# =======================
303
304
def format_help(self):
305
help = self._root_section.format_help()
306
if help:
307
help = self._long_break_matcher.sub('\n\n', help)
308
help = help.strip('\n') + '\n'
309
return help
310
311
def _join_parts(self, part_strings):
312
return ''.join([part
313
for part in part_strings
314
if part and part is not SUPPRESS])
315
316
def _format_usage(self, usage, actions, groups, prefix):
317
t = self._theme
318
319
if prefix is None:
320
prefix = _('usage: ')
321
322
# if usage is specified, use that
323
if usage is not None:
324
usage = (
325
t.prog_extra
326
+ usage
327
% {"prog": f"{t.prog}{self._prog}{t.reset}{t.prog_extra}"}
328
+ t.reset
329
)
330
331
# if no optionals or positionals are available, usage is just prog
332
elif usage is None and not actions:
333
usage = f"{t.prog}{self._prog}{t.reset}"
334
335
# if optionals and positionals are available, calculate usage
336
elif usage is None:
337
prog = '%(prog)s' % dict(prog=self._prog)
338
339
parts, pos_start = self._get_actions_usage_parts(actions, groups)
340
# build full usage string
341
usage = ' '.join(filter(None, [prog, *parts]))
342
343
# wrap the usage parts if it's too long
344
text_width = self._width - self._current_indent
345
if len(prefix) + len(self._decolor(usage)) > text_width:
346
347
# break usage into wrappable parts
348
opt_parts = parts[:pos_start]
349
pos_parts = parts[pos_start:]
350
351
# helper for wrapping lines
352
def get_lines(parts, indent, prefix=None):
353
lines = []
354
line = []
355
indent_length = len(indent)
356
if prefix is not None:
357
line_len = len(prefix) - 1
358
else:
359
line_len = indent_length - 1
360
for part in parts:
361
part_len = len(self._decolor(part))
362
if line_len + 1 + part_len > text_width and line:
363
lines.append(indent + ' '.join(line))
364
line = []
365
line_len = indent_length - 1
366
line.append(part)
367
line_len += part_len + 1
368
if line:
369
lines.append(indent + ' '.join(line))
370
if prefix is not None:
371
lines[0] = lines[0][indent_length:]
372
return lines
373
374
# if prog is short, follow it with optionals or positionals
375
prog_len = len(self._decolor(prog))
376
if len(prefix) + prog_len <= 0.75 * text_width:
377
indent = ' ' * (len(prefix) + prog_len + 1)
378
if opt_parts:
379
lines = get_lines([prog] + opt_parts, indent, prefix)
380
lines.extend(get_lines(pos_parts, indent))
381
elif pos_parts:
382
lines = get_lines([prog] + pos_parts, indent, prefix)
383
else:
384
lines = [prog]
385
386
# if prog is long, put it on its own line
387
else:
388
indent = ' ' * len(prefix)
389
parts = opt_parts + pos_parts
390
lines = get_lines(parts, indent)
391
if len(lines) > 1:
392
lines = []
393
lines.extend(get_lines(opt_parts, indent))
394
lines.extend(get_lines(pos_parts, indent))
395
lines = [prog] + lines
396
397
# join lines into usage
398
usage = '\n'.join(lines)
399
400
usage = usage.removeprefix(prog)
401
usage = f"{t.prog}{prog}{t.reset}{usage}"
402
403
# prefix with 'usage:'
404
return f'{t.usage}{prefix}{t.reset}{usage}\n\n'
405
406
def _is_long_option(self, string):
407
return len(string) > 2
408
409
def _get_actions_usage_parts(self, actions, groups):
410
"""Get usage parts with split index for optionals/positionals.
411
412
Returns (parts, pos_start) where pos_start is the index in parts
413
where positionals begin.
414
This preserves mutually exclusive group formatting across the
415
optionals/positionals boundary (gh-75949).
416
"""
417
actions = [action for action in actions if action.help is not SUPPRESS]
418
# group actions by mutually exclusive groups
419
action_groups = dict.fromkeys(actions)
420
for group in groups:
421
for action in group._group_actions:
422
if action in action_groups:
423
action_groups[action] = group
424
# positional arguments keep their position
425
positionals = []
426
for action in actions:
427
if not action.option_strings:
428
group = action_groups.pop(action)
429
if group:
430
group_actions = [
431
action2 for action2 in group._group_actions
432
if action2.option_strings and
433
action_groups.pop(action2, None)
434
] + [action]
435
positionals.append((group.required, group_actions))
436
else:
437
positionals.append((None, [action]))
438
# the remaining optional arguments are sorted by the position of
439
# the first option in the group
440
optionals = []
441
for action in actions:
442
if action.option_strings and action in action_groups:
443
group = action_groups.pop(action)
444
if group:
445
group_actions = [action] + [
446
action2 for action2 in group._group_actions
447
if action2.option_strings and
448
action_groups.pop(action2, None)
449
]
450
optionals.append((group.required, group_actions))
451
else:
452
optionals.append((None, [action]))
453
454
# collect all actions format strings
455
parts = []
456
t = self._theme
457
pos_start = None
458
for i, (required, group) in enumerate(optionals + positionals):
459
start = len(parts)
460
if i == len(optionals):
461
pos_start = start
462
in_group = len(group) > 1
463
for action in group:
464
# produce all arg strings
465
if not action.option_strings:
466
default = self._get_default_metavar_for_positional(action)
467
part = self._format_args(action, default)
468
# if it's in a group, strip the outer []
469
if in_group:
470
if part[0] == '[' and part[-1] == ']':
471
part = part[1:-1]
472
part = t.summary_action + part + t.reset
473
474
# produce the first way to invoke the option in brackets
475
else:
476
option_string = action.option_strings[0]
477
if self._is_long_option(option_string):
478
option_color = t.summary_long_option
479
else:
480
option_color = t.summary_short_option
481
482
# if the Optional doesn't take a value, format is:
483
# -s or --long
484
if action.nargs == 0:
485
part = action.format_usage()
486
part = f"{option_color}{part}{t.reset}"
487
488
# if the Optional takes a value, format is:
489
# -s ARGS or --long ARGS
490
else:
491
default = self._get_default_metavar_for_optional(action)
492
args_string = self._format_args(action, default)
493
part = (
494
f"{option_color}{option_string} "
495
f"{t.summary_label}{args_string}{t.reset}"
496
)
497
498
# make it look optional if it's not required or in a group
499
if not (action.required or required or in_group):
500
part = '[%s]' % part
501
502
# add the action string to the list
503
parts.append(part)
504
505
if in_group:
506
parts[start] = ('(' if required else '[') + parts[start]
507
for i in range(start, len(parts) - 1):
508
parts[i] += ' |'
509
parts[-1] += ')' if required else ']'
510
511
if pos_start is None:
512
pos_start = len(parts)
513
return parts, pos_start
514
515
def _format_text(self, text):
516
if '%(prog)' in text:
517
text = text % dict(prog=self._prog)
518
text_width = max(self._width - self._current_indent, 11)
519
indent = ' ' * self._current_indent
520
return self._fill_text(text, text_width, indent) + '\n\n'
521
522
def _format_action(self, action):
523
# determine the required width and the entry label
524
help_position = min(self._action_max_length + 2,
525
self._max_help_position)
526
help_width = max(self._width - help_position, 11)
527
action_width = help_position - self._current_indent - 2
528
action_header = self._format_action_invocation(action)
529
action_header_no_color = self._decolor(action_header)
530
531
# no help; start on same line and add a final newline
532
if not action.help:
533
tup = self._current_indent, '', action_header
534
action_header = '%*s%s\n' % tup
535
536
# short action name; start on the same line and pad two spaces
537
elif len(action_header_no_color) <= action_width:
538
# calculate widths without color codes
539
action_header_color = action_header
540
tup = self._current_indent, '', action_width, action_header_no_color
541
action_header = '%*s%-*s ' % tup
542
# swap in the colored header
543
action_header = action_header.replace(
544
action_header_no_color, action_header_color
545
)
546
indent_first = 0
547
548
# long action name; start on the next line
549
else:
550
tup = self._current_indent, '', action_header
551
action_header = '%*s%s\n' % tup
552
indent_first = help_position
553
554
# collect the pieces of the action help
555
parts = [action_header]
556
557
# if there was help for the action, add lines of help text
558
if action.help and action.help.strip():
559
help_text = self._expand_help(action)
560
if help_text:
561
help_lines = self._split_lines(help_text, help_width)
562
parts.append('%*s%s\n' % (indent_first, '', help_lines[0]))
563
for line in help_lines[1:]:
564
parts.append('%*s%s\n' % (help_position, '', line))
565
566
# or add a newline if the description doesn't end with one
567
elif not action_header.endswith('\n'):
568
parts.append('\n')
569
570
# if there are any sub-actions, add their help as well
571
for subaction in self._iter_indented_subactions(action):
572
parts.append(self._format_action(subaction))
573
574
# return a single string
575
return self._join_parts(parts)
576
577
def _format_action_invocation(self, action):
578
t = self._theme
579
580
if not action.option_strings:
581
default = self._get_default_metavar_for_positional(action)
582
return (
583
t.action
584
+ ' '.join(self._metavar_formatter(action, default)(1))
585
+ t.reset
586
)
587
588
else:
589
590
def color_option_strings(strings):
591
parts = []
592
for s in strings:
593
if self._is_long_option(s):
594
parts.append(f"{t.long_option}{s}{t.reset}")
595
else:
596
parts.append(f"{t.short_option}{s}{t.reset}")
597
return parts
598
599
# if the Optional doesn't take a value, format is:
600
# -s, --long
601
if action.nargs == 0:
602
option_strings = color_option_strings(action.option_strings)
603
return ', '.join(option_strings)
604
605
# if the Optional takes a value, format is:
606
# -s, --long ARGS
607
else:
608
default = self._get_default_metavar_for_optional(action)
609
option_strings = color_option_strings(action.option_strings)
610
args_string = (
611
f"{t.label}{self._format_args(action, default)}{t.reset}"
612
)
613
return ', '.join(option_strings) + ' ' + args_string
614
615
def _metavar_formatter(self, action, default_metavar):
616
if action.metavar is not None:
617
result = action.metavar
618
elif action.choices is not None:
619
result = '{%s}' % ','.join(map(str, action.choices))
620
else:
621
result = default_metavar
622
623
def format(tuple_size):
624
if isinstance(result, tuple):
625
return result
626
else:
627
return (result, ) * tuple_size
628
return format
629
630
def _format_args(self, action, default_metavar):
631
get_metavar = self._metavar_formatter(action, default_metavar)
632
if action.nargs is None:
633
result = '%s' % get_metavar(1)
634
elif action.nargs == OPTIONAL:
635
result = '[%s]' % get_metavar(1)
636
elif action.nargs == ZERO_OR_MORE:
637
metavar = get_metavar(1)
638
if len(metavar) == 2:
639
result = '[%s [%s ...]]' % metavar
640
else:
641
result = '[%s ...]' % metavar
642
elif action.nargs == ONE_OR_MORE:
643
result = '%s [%s ...]' % get_metavar(2)
644
elif action.nargs == REMAINDER:
645
result = '...'
646
elif action.nargs == PARSER:
647
result = '%s ...' % get_metavar(1)
648
elif action.nargs == SUPPRESS:
649
result = ''
650
else:
651
try:
652
formats = ['%s' for _ in range(action.nargs)]
653
except TypeError:
654
raise ValueError("invalid nargs value") from None
655
result = ' '.join(formats) % get_metavar(action.nargs)
656
return result
657
658
def _expand_help(self, action):
659
help_string = self._get_help_string(action)
660
if '%' not in help_string:
661
return help_string
662
params = dict(vars(action), prog=self._prog)
663
for name in list(params):
664
value = params[name]
665
if value is SUPPRESS:
666
del params[name]
667
elif hasattr(value, '__name__'):
668
params[name] = value.__name__
669
if params.get('choices') is not None:
670
params['choices'] = ', '.join(map(str, params['choices']))
671
return help_string % params
672
673
def _iter_indented_subactions(self, action):
674
try:
675
get_subactions = action._get_subactions
676
except AttributeError:
677
pass
678
else:
679
self._indent()
680
yield from get_subactions()
681
self._dedent()
682
683
def _split_lines(self, text, width):
684
text = self._whitespace_matcher.sub(' ', text).strip()
685
# The textwrap module is used only for formatting help.
686
# Delay its import for speeding up the common usage of argparse.
687
import textwrap
688
return textwrap.wrap(text, width)
689
690
def _fill_text(self, text, width, indent):
691
text = self._whitespace_matcher.sub(' ', text).strip()
692
import textwrap
693
return textwrap.fill(text, width,
694
initial_indent=indent,
695
subsequent_indent=indent)
696
697
def _get_help_string(self, action):
698
return action.help
699
700
def _get_default_metavar_for_optional(self, action):
701
return action.dest.upper()
702
703
def _get_default_metavar_for_positional(self, action):
704
return action.dest
705
706
707
class RawDescriptionHelpFormatter(HelpFormatter):
708
"""Help message formatter which retains any formatting in descriptions.
709
710
Only the name of this class is considered a public API. All the methods
711
provided by the class are considered an implementation detail.
712
"""
713
714
def _fill_text(self, text, width, indent):
715
return ''.join(indent + line for line in text.splitlines(keepends=True))
716
717
718
class RawTextHelpFormatter(RawDescriptionHelpFormatter):
719
"""Help message formatter which retains formatting of all help text.
720
721
Only the name of this class is considered a public API. All the methods
722
provided by the class are considered an implementation detail.
723
"""
724
725
def _split_lines(self, text, width):
726
return text.splitlines()
727
728
729
class ArgumentDefaultsHelpFormatter(HelpFormatter):
730
"""Help message formatter which adds default values to argument help.
731
732
Only the name of this class is considered a public API. All the methods
733
provided by the class are considered an implementation detail.
734
"""
735
736
def _get_help_string(self, action):
737
help = action.help
738
if help is None:
739
help = ''
740
741
if '%(default)' not in help:
742
if action.default is not SUPPRESS:
743
defaulting_nargs = [OPTIONAL, ZERO_OR_MORE]
744
if action.option_strings or action.nargs in defaulting_nargs:
745
t = self._theme
746
default_str = _(" (default: %(default)s)")
747
prefix, suffix = default_str.split("%(default)s")
748
help += (
749
f" {t.default}{prefix.lstrip()}"
750
f"{t.default_value}%(default)s"
751
f"{t.default}{suffix}{t.reset}"
752
)
753
return help
754
755
756
757
class MetavarTypeHelpFormatter(HelpFormatter):
758
"""Help message formatter which uses the argument 'type' as the default
759
metavar value (instead of the argument 'dest')
760
761
Only the name of this class is considered a public API. All the methods
762
provided by the class are considered an implementation detail.
763
"""
764
765
def _get_default_metavar_for_optional(self, action):
766
return action.type.__name__
767
768
def _get_default_metavar_for_positional(self, action):
769
return action.type.__name__
770
771
772
# =====================
773
# Options and Arguments
774
# =====================
775
776
def _get_action_name(argument):
777
if argument is None:
778
return None
779
elif argument.option_strings:
780
return '/'.join(argument.option_strings)
781
elif argument.metavar not in (None, SUPPRESS):
782
metavar = argument.metavar
783
if not isinstance(metavar, tuple):
784
return metavar
785
if argument.nargs == ZERO_OR_MORE and len(metavar) == 2:
786
return '%s[, %s]' % metavar
787
elif argument.nargs == ONE_OR_MORE:
788
return '%s[, %s]' % metavar
789
else:
790
return ', '.join(metavar)
791
elif argument.dest not in (None, SUPPRESS):
792
return argument.dest
793
elif argument.choices:
794
return '{%s}' % ','.join(map(str, argument.choices))
795
else:
796
return None
797
798
799
class ArgumentError(Exception):
800
"""An error from creating or using an argument (optional or positional).
801
802
The string value of this exception is the message, augmented with
803
information about the argument that caused it.
804
"""
805
806
def __init__(self, argument, message):
807
self.argument_name = _get_action_name(argument)
808
self.message = message
809
810
def __str__(self):
811
if self.argument_name is None:
812
format = '%(message)s'
813
else:
814
format = _('argument %(argument_name)s: %(message)s')
815
return format % dict(message=self.message,
816
argument_name=self.argument_name)
817
818
819
class ArgumentTypeError(Exception):
820
"""An error from trying to convert a command line string to a type."""
821
pass
822
823
824
# ==============
825
# Action classes
826
# ==============
827
828
class Action(_AttributeHolder):
829
"""Information about how to convert command line strings to Python objects.
830
831
Action objects are used by an ArgumentParser to represent the information
832
needed to parse a single argument from one or more strings from the
833
command line. The keyword arguments to the Action constructor are also
834
all attributes of Action instances.
835
836
Keyword Arguments:
837
838
- option_strings -- A list of command-line option strings which
839
should be associated with this action.
840
841
- dest -- The name of the attribute to hold the created object(s)
842
843
- nargs -- The number of command-line arguments that should be
844
consumed. By default, one argument will be consumed and a single
845
value will be produced. Other values include:
846
- N (an integer) consumes N arguments (and produces a list)
847
- '?' consumes zero or one arguments
848
- '*' consumes zero or more arguments (and produces a list)
849
- '+' consumes one or more arguments (and produces a list)
850
Note that the difference between the default and nargs=1 is that
851
with the default, a single value will be produced, while with
852
nargs=1, a list containing a single value will be produced.
853
854
- const -- The value to be produced if the option is specified and the
855
option uses an action that takes no values.
856
857
- default -- The value to be produced if the option is not specified.
858
859
- type -- A callable that accepts a single string argument, and
860
returns the converted value. The standard Python types str, int,
861
float, and complex are useful examples of such callables. If None,
862
str is used.
863
864
- choices -- A container of values that should be allowed. If not None,
865
after a command-line argument has been converted to the appropriate
866
type, an exception will be raised if it is not a member of this
867
collection.
868
869
- required -- True if the action must always be specified at the
870
command line. This is only meaningful for optional command-line
871
arguments.
872
873
- help -- The help string describing the argument.
874
875
- metavar -- The name to be used for the option's argument with the
876
help string. If None, the 'dest' value will be used as the name.
877
"""
878
879
def __init__(self,
880
option_strings,
881
dest,
882
nargs=None,
883
const=None,
884
default=None,
885
type=None,
886
choices=None,
887
required=False,
888
help=None,
889
metavar=None,
890
deprecated=False):
891
self.option_strings = option_strings
892
self.dest = dest
893
self.nargs = nargs
894
self.const = const
895
self.default = default
896
self.type = type
897
self.choices = choices
898
self.required = required
899
self.help = help
900
self.metavar = metavar
901
self.deprecated = deprecated
902
903
def _get_kwargs(self):
904
names = [
905
'option_strings',
906
'dest',
907
'nargs',
908
'const',
909
'default',
910
'type',
911
'choices',
912
'required',
913
'help',
914
'metavar',
915
'deprecated',
916
]
917
return [(name, getattr(self, name)) for name in names]
918
919
def format_usage(self):
920
return self.option_strings[0]
921
922
def __call__(self, parser, namespace, values, option_string=None):
923
raise NotImplementedError('.__call__() not defined')
924
925
926
class BooleanOptionalAction(Action):
927
def __init__(self,
928
option_strings,
929
dest,
930
default=None,
931
required=False,
932
help=None,
933
deprecated=False):
934
935
_option_strings = []
936
neg_option_strings = []
937
for option_string in option_strings:
938
_option_strings.append(option_string)
939
940
if len(option_string) > 2 and option_string[0] == option_string[1]:
941
# two-dash long option: '--foo' -> '--no-foo'
942
if option_string.startswith('no-', 2):
943
raise ValueError(f'invalid option name {option_string!r} '
944
f'for BooleanOptionalAction')
945
option_string = option_string[:2] + 'no-' + option_string[2:]
946
_option_strings.append(option_string)
947
neg_option_strings.append(option_string)
948
elif len(option_string) > 2 and option_string[0] != option_string[1]:
949
# single-dash long option: '-foo' -> '-nofoo'
950
if option_string.startswith('no', 1):
951
raise ValueError(f'invalid option name {option_string!r} '
952
f'for BooleanOptionalAction')
953
option_string = option_string[:1] + 'no' + option_string[1:]
954
_option_strings.append(option_string)
955
neg_option_strings.append(option_string)
956
957
super().__init__(
958
option_strings=_option_strings,
959
dest=dest,
960
nargs=0,
961
default=default,
962
required=required,
963
help=help,
964
deprecated=deprecated)
965
self.neg_option_strings = neg_option_strings
966
967
968
def __call__(self, parser, namespace, values, option_string=None):
969
if option_string in self.option_strings:
970
setattr(namespace, self.dest, option_string not in self.neg_option_strings)
971
972
def format_usage(self):
973
return ' | '.join(self.option_strings)
974
975
976
class _StoreAction(Action):
977
978
def __init__(self,
979
option_strings,
980
dest,
981
nargs=None,
982
const=None,
983
default=None,
984
type=None,
985
choices=None,
986
required=False,
987
help=None,
988
metavar=None,
989
deprecated=False):
990
if nargs == 0:
991
raise ValueError('nargs for store actions must be != 0; if you '
992
'have nothing to store, actions such as store '
993
'true or store const may be more appropriate')
994
if const is not None and nargs != OPTIONAL:
995
raise ValueError('nargs must be %r to supply const' % OPTIONAL)
996
super(_StoreAction, self).__init__(
997
option_strings=option_strings,
998
dest=dest,
999
nargs=nargs,
1000
const=const,