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