Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
allendowney
GitHub Repository: allendowney/cpython
Path: blob/main/Lib/argparse.py
12 views
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', default=sys.stdout, type=argparse.FileType('w'),
22
help='the file where the sum should be written')
23
args = parser.parse_args()
24
args.log.write('%s' % sum(args.integers))
25
args.log.close()
26
27
The module contains the following public classes:
28
29
- ArgumentParser -- The main entry point for command-line parsing. As the
30
example above shows, the add_argument() method is used to populate
31
the parser with actions for optional and positional arguments. Then
32
the parse_args() method is invoked to convert the args at the
33
command-line into an object with attributes.
34
35
- ArgumentError -- The exception raised by ArgumentParser objects when
36
there are errors with the parser's actions. Errors raised while
37
parsing the command-line are caught by ArgumentParser and emitted
38
as command-line messages.
39
40
- FileType -- A factory for defining types of files to be created. As the
41
example above shows, instances of FileType are typically passed as
42
the type= argument of add_argument() calls.
43
44
- Action -- The base class for parser actions. Typically actions are
45
selected by passing strings like 'store_true' or 'append_const' to
46
the action= argument of add_argument(). However, for greater
47
customization of ArgumentParser actions, subclasses of Action may
48
be defined and passed as the action= argument.
49
50
- HelpFormatter, RawDescriptionHelpFormatter, RawTextHelpFormatter,
51
ArgumentDefaultsHelpFormatter -- Formatter classes which
52
may be passed as the formatter_class= argument to the
53
ArgumentParser constructor. HelpFormatter is the default,
54
RawDescriptionHelpFormatter and RawTextHelpFormatter tell the parser
55
not to change the formatting for help text, and
56
ArgumentDefaultsHelpFormatter adds information about argument defaults
57
to the help.
58
59
All other classes in this module are considered implementation details.
60
(Also note that HelpFormatter and RawDescriptionHelpFormatter are only
61
considered public as object names -- the API of the formatter objects is
62
still considered an implementation detail.)
63
"""
64
65
__version__ = '1.1'
66
__all__ = [
67
'ArgumentParser',
68
'ArgumentError',
69
'ArgumentTypeError',
70
'BooleanOptionalAction',
71
'FileType',
72
'HelpFormatter',
73
'ArgumentDefaultsHelpFormatter',
74
'RawDescriptionHelpFormatter',
75
'RawTextHelpFormatter',
76
'MetavarTypeHelpFormatter',
77
'Namespace',
78
'Action',
79
'ONE_OR_MORE',
80
'OPTIONAL',
81
'PARSER',
82
'REMAINDER',
83
'SUPPRESS',
84
'ZERO_OR_MORE',
85
]
86
87
88
import os as _os
89
import re as _re
90
import sys as _sys
91
92
import warnings
93
94
from gettext import gettext as _, ngettext
95
96
SUPPRESS = '==SUPPRESS=='
97
98
OPTIONAL = '?'
99
ZERO_OR_MORE = '*'
100
ONE_OR_MORE = '+'
101
PARSER = 'A...'
102
REMAINDER = '...'
103
_UNRECOGNIZED_ARGS_ATTR = '_unrecognized_args'
104
105
# =============================
106
# Utility functions and classes
107
# =============================
108
109
class _AttributeHolder(object):
110
"""Abstract base class that provides __repr__.
111
112
The __repr__ method returns a string in the format::
113
ClassName(attr=name, attr=name, ...)
114
The attributes are determined either by a class-level attribute,
115
'_kwarg_names', or by inspecting the instance __dict__.
116
"""
117
118
def __repr__(self):
119
type_name = type(self).__name__
120
arg_strings = []
121
star_args = {}
122
for arg in self._get_args():
123
arg_strings.append(repr(arg))
124
for name, value in self._get_kwargs():
125
if name.isidentifier():
126
arg_strings.append('%s=%r' % (name, value))
127
else:
128
star_args[name] = value
129
if star_args:
130
arg_strings.append('**%s' % repr(star_args))
131
return '%s(%s)' % (type_name, ', '.join(arg_strings))
132
133
def _get_kwargs(self):
134
return list(self.__dict__.items())
135
136
def _get_args(self):
137
return []
138
139
140
def _copy_items(items):
141
if items is None:
142
return []
143
# The copy module is used only in the 'append' and 'append_const'
144
# actions, and it is needed only when the default value isn't a list.
145
# Delay its import for speeding up the common case.
146
if type(items) is list:
147
return items[:]
148
import copy
149
return copy.copy(items)
150
151
152
# ===============
153
# Formatting Help
154
# ===============
155
156
157
class HelpFormatter(object):
158
"""Formatter for generating usage messages and argument help strings.
159
160
Only the name of this class is considered a public API. All the methods
161
provided by the class are considered an implementation detail.
162
"""
163
164
def __init__(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
# ===============================
193
# Section and indentation methods
194
# ===============================
195
def _indent(self):
196
self._current_indent += self._indent_increment
197
self._level += 1
198
199
def _dedent(self):
200
self._current_indent -= self._indent_increment
201
assert self._current_indent >= 0, 'Indent decreased below 0.'
202
self._level -= 1
203
204
class _Section(object):
205
206
def __init__(self, formatter, parent, heading=None):
207
self.formatter = formatter
208
self.parent = parent
209
self.heading = heading
210
self.items = []
211
212
def format_help(self):
213
# format the indented section
214
if self.parent is not None:
215
self.formatter._indent()
216
join = self.formatter._join_parts
217
item_help = join([func(*args) for func, args in self.items])
218
if self.parent is not None:
219
self.formatter._dedent()
220
221
# return nothing if the section was empty
222
if not item_help:
223
return ''
224
225
# add the heading if the section was non-empty
226
if self.heading is not SUPPRESS and self.heading is not None:
227
current_indent = self.formatter._current_indent
228
heading = '%*s%s:\n' % (current_indent, '', self.heading)
229
else:
230
heading = ''
231
232
# join the section-initial newline, the heading and the help
233
return join(['\n', heading, item_help, '\n'])
234
235
def _add_item(self, func, args):
236
self._current_section.items.append((func, args))
237
238
# ========================
239
# Message building methods
240
# ========================
241
def start_section(self, heading):
242
self._indent()
243
section = self._Section(self, self._current_section, heading)
244
self._add_item(section.format_help, [])
245
self._current_section = section
246
247
def end_section(self):
248
self._current_section = self._current_section.parent
249
self._dedent()
250
251
def add_text(self, text):
252
if text is not SUPPRESS and text is not None:
253
self._add_item(self._format_text, [text])
254
255
def add_usage(self, usage, actions, groups, prefix=None):
256
if usage is not SUPPRESS:
257
args = usage, actions, groups, prefix
258
self._add_item(self._format_usage, args)
259
260
def add_argument(self, action):
261
if action.help is not SUPPRESS:
262
263
# find all invocations
264
get_invocation = self._format_action_invocation
265
invocations = [get_invocation(action)]
266
for subaction in self._iter_indented_subactions(action):
267
invocations.append(get_invocation(subaction))
268
269
# update the maximum item length
270
invocation_length = max(map(len, invocations))
271
action_length = invocation_length + self._current_indent
272
self._action_max_length = max(self._action_max_length,
273
action_length)
274
275
# add the item to the list
276
self._add_item(self._format_action, [action])
277
278
def add_arguments(self, actions):
279
for action in actions:
280
self.add_argument(action)
281
282
# =======================
283
# Help-formatting methods
284
# =======================
285
def format_help(self):
286
help = self._root_section.format_help()
287
if help:
288
help = self._long_break_matcher.sub('\n\n', help)
289
help = help.strip('\n') + '\n'
290
return help
291
292
def _join_parts(self, part_strings):
293
return ''.join([part
294
for part in part_strings
295
if part and part is not SUPPRESS])
296
297
def _format_usage(self, usage, actions, groups, prefix):
298
if prefix is None:
299
prefix = _('usage: ')
300
301
# if usage is specified, use that
302
if usage is not None:
303
usage = usage % dict(prog=self._prog)
304
305
# if no optionals or positionals are available, usage is just prog
306
elif usage is None and not actions:
307
usage = '%(prog)s' % dict(prog=self._prog)
308
309
# if optionals and positionals are available, calculate usage
310
elif usage is None:
311
prog = '%(prog)s' % dict(prog=self._prog)
312
313
# split optionals from positionals
314
optionals = []
315
positionals = []
316
for action in actions:
317
if action.option_strings:
318
optionals.append(action)
319
else:
320
positionals.append(action)
321
322
# build full usage string
323
format = self._format_actions_usage
324
action_usage = format(optionals + positionals, groups)
325
usage = ' '.join([s for s in [prog, action_usage] if s])
326
327
# wrap the usage parts if it's too long
328
text_width = self._width - self._current_indent
329
if len(prefix) + len(usage) > text_width:
330
331
# break usage into wrappable parts
332
part_regexp = (
333
r'\(.*?\)+(?=\s|$)|'
334
r'\[.*?\]+(?=\s|$)|'
335
r'\S+'
336
)
337
opt_usage = format(optionals, groups)
338
pos_usage = format(positionals, groups)
339
opt_parts = _re.findall(part_regexp, opt_usage)
340
pos_parts = _re.findall(part_regexp, pos_usage)
341
assert ' '.join(opt_parts) == opt_usage
342
assert ' '.join(pos_parts) == pos_usage
343
344
# helper for wrapping lines
345
def get_lines(parts, indent, prefix=None):
346
lines = []
347
line = []
348
indent_length = len(indent)
349
if prefix is not None:
350
line_len = len(prefix) - 1
351
else:
352
line_len = indent_length - 1
353
for part in parts:
354
if line_len + 1 + len(part) > text_width and line:
355
lines.append(indent + ' '.join(line))
356
line = []
357
line_len = indent_length - 1
358
line.append(part)
359
line_len += len(part) + 1
360
if line:
361
lines.append(indent + ' '.join(line))
362
if prefix is not None:
363
lines[0] = lines[0][indent_length:]
364
return lines
365
366
# if prog is short, follow it with optionals or positionals
367
if len(prefix) + len(prog) <= 0.75 * text_width:
368
indent = ' ' * (len(prefix) + len(prog) + 1)
369
if opt_parts:
370
lines = get_lines([prog] + opt_parts, indent, prefix)
371
lines.extend(get_lines(pos_parts, indent))
372
elif pos_parts:
373
lines = get_lines([prog] + pos_parts, indent, prefix)
374
else:
375
lines = [prog]
376
377
# if prog is long, put it on its own line
378
else:
379
indent = ' ' * len(prefix)
380
parts = opt_parts + pos_parts
381
lines = get_lines(parts, indent)
382
if len(lines) > 1:
383
lines = []
384
lines.extend(get_lines(opt_parts, indent))
385
lines.extend(get_lines(pos_parts, indent))
386
lines = [prog] + lines
387
388
# join lines into usage
389
usage = '\n'.join(lines)
390
391
# prefix with 'usage:'
392
return '%s%s\n\n' % (prefix, usage)
393
394
def _format_actions_usage(self, actions, groups):
395
# find group indices and identify actions in groups
396
group_actions = set()
397
inserts = {}
398
for group in groups:
399
if not group._group_actions:
400
raise ValueError(f'empty group {group}')
401
402
try:
403
start = actions.index(group._group_actions[0])
404
except ValueError:
405
continue
406
else:
407
group_action_count = len(group._group_actions)
408
end = start + group_action_count
409
if actions[start:end] == group._group_actions:
410
411
suppressed_actions_count = 0
412
for action in group._group_actions:
413
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
419
if not group.required:
420
if start in inserts:
421
inserts[start] += ' ['
422
else:
423
inserts[start] = '['
424
if end in inserts:
425
inserts[end] += ']'
426
else:
427
inserts[end] = ']'
428
elif exposed_actions_count > 1:
429
if start in inserts:
430
inserts[start] += ' ('
431
else:
432
inserts[start] = '('
433
if end in inserts:
434
inserts[end] += ')'
435
else:
436
inserts[end] = ')'
437
for i in range(start + 1, end):
438
inserts[i] = '|'
439
440
# collect all actions format strings
441
parts = []
442
for i, action in enumerate(actions):
443
444
# suppressed arguments are marked with None
445
# remove | separators for suppressed arguments
446
if action.help is SUPPRESS:
447
parts.append(None)
448
if inserts.get(i) == '|':
449
inserts.pop(i)
450
elif inserts.get(i + 1) == '|':
451
inserts.pop(i + 1)
452
453
# produce all arg strings
454
elif not action.option_strings:
455
default = self._get_default_metavar_for_positional(action)
456
part = self._format_args(action, default)
457
458
# if it's in a group, strip the outer []
459
if action in group_actions:
460
if part[0] == '[' and part[-1] == ']':
461
part = part[1:-1]
462
463
# add the action string to the list
464
parts.append(part)
465
466
# produce the first way to invoke the option in brackets
467
else:
468
option_string = action.option_strings[0]
469
470
# if the Optional doesn't take a value, format is:
471
# -s or --long
472
if action.nargs == 0:
473
part = action.format_usage()
474
475
# if the Optional takes a value, format is:
476
# -s ARGS or --long ARGS
477
else:
478
default = self._get_default_metavar_for_optional(action)
479
args_string = self._format_args(action, default)
480
part = '%s %s' % (option_string, args_string)
481
482
# make it look optional if it's not required or in a group
483
if not action.required and action not in group_actions:
484
part = '[%s]' % part
485
486
# add the action string to the list
487
parts.append(part)
488
489
# insert things at the necessary indices
490
for i in sorted(inserts, reverse=True):
491
parts[i:i] = [inserts[i]]
492
493
# join all the action items with spaces
494
text = ' '.join([item for item in parts if item is not None])
495
496
# clean up separators for mutually exclusive groups
497
open = r'[\[(]'
498
close = r'[\])]'
499
text = _re.sub(r'(%s) ' % open, r'\1', text)
500
text = _re.sub(r' (%s)' % close, r'\1', text)
501
text = _re.sub(r'%s *%s' % (open, close), r'', text)
502
text = text.strip()
503
504
# return the text
505
return text
506
507
def _format_text(self, text):
508
if '%(prog)' in text:
509
text = text % dict(prog=self._prog)
510
text_width = max(self._width - self._current_indent, 11)
511
indent = ' ' * self._current_indent
512
return self._fill_text(text, text_width, indent) + '\n\n'
513
514
def _format_action(self, action):
515
# determine the required width and the entry label
516
help_position = min(self._action_max_length + 2,
517
self._max_help_position)
518
help_width = max(self._width - help_position, 11)
519
action_width = help_position - self._current_indent - 2
520
action_header = self._format_action_invocation(action)
521
522
# no help; start on same line and add a final newline
523
if not action.help:
524
tup = self._current_indent, '', action_header
525
action_header = '%*s%s\n' % tup
526
527
# short action name; start on the same line and pad two spaces
528
elif len(action_header) <= action_width:
529
tup = self._current_indent, '', action_width, action_header
530
action_header = '%*s%-*s ' % tup
531
indent_first = 0
532
533
# long action name; start on the next line
534
else:
535
tup = self._current_indent, '', action_header
536
action_header = '%*s%s\n' % tup
537
indent_first = help_position
538
539
# collect the pieces of the action help
540
parts = [action_header]
541
542
# if there was help for the action, add lines of help text
543
if action.help and action.help.strip():
544
help_text = self._expand_help(action)
545
if help_text:
546
help_lines = self._split_lines(help_text, help_width)
547
parts.append('%*s%s\n' % (indent_first, '', help_lines[0]))
548
for line in help_lines[1:]:
549
parts.append('%*s%s\n' % (help_position, '', line))
550
551
# or add a newline if the description doesn't end with one
552
elif not action_header.endswith('\n'):
553
parts.append('\n')
554
555
# if there are any sub-actions, add their help as well
556
for subaction in self._iter_indented_subactions(action):
557
parts.append(self._format_action(subaction))
558
559
# return a single string
560
return self._join_parts(parts)
561
562
def _format_action_invocation(self, action):
563
if not action.option_strings:
564
default = self._get_default_metavar_for_positional(action)
565
metavar, = self._metavar_formatter(action, default)(1)
566
return metavar
567
568
else:
569
parts = []
570
571
# if the Optional doesn't take a value, format is:
572
# -s, --long
573
if action.nargs == 0:
574
parts.extend(action.option_strings)
575
576
# if the Optional takes a value, format is:
577
# -s ARGS, --long ARGS
578
else:
579
default = self._get_default_metavar_for_optional(action)
580
args_string = self._format_args(action, default)
581
for option_string in action.option_strings:
582
parts.append('%s %s' % (option_string, args_string))
583
584
return ', '.join(parts)
585
586
def _metavar_formatter(self, action, default_metavar):
587
if action.metavar is not None:
588
result = action.metavar
589
elif action.choices is not None:
590
choice_strs = [str(choice) for choice in action.choices]
591
result = '{%s}' % ','.join(choice_strs)
592
else:
593
result = default_metavar
594
595
def format(tuple_size):
596
if isinstance(result, tuple):
597
return result
598
else:
599
return (result, ) * tuple_size
600
return format
601
602
def _format_args(self, action, default_metavar):
603
get_metavar = self._metavar_formatter(action, default_metavar)
604
if action.nargs is None:
605
result = '%s' % get_metavar(1)
606
elif action.nargs == OPTIONAL:
607
result = '[%s]' % get_metavar(1)
608
elif action.nargs == ZERO_OR_MORE:
609
metavar = get_metavar(1)
610
if len(metavar) == 2:
611
result = '[%s [%s ...]]' % metavar
612
else:
613
result = '[%s ...]' % metavar
614
elif action.nargs == ONE_OR_MORE:
615
result = '%s [%s ...]' % get_metavar(2)
616
elif action.nargs == REMAINDER:
617
result = '...'
618
elif action.nargs == PARSER:
619
result = '%s ...' % get_metavar(1)
620
elif action.nargs == SUPPRESS:
621
result = ''
622
else:
623
try:
624
formats = ['%s' for _ in range(action.nargs)]
625
except TypeError:
626
raise ValueError("invalid nargs value") from None
627
result = ' '.join(formats) % get_metavar(action.nargs)
628
return result
629
630
def _expand_help(self, action):
631
params = dict(vars(action), prog=self._prog)
632
for name in list(params):
633
if params[name] is SUPPRESS:
634
del params[name]
635
for name in list(params):
636
if hasattr(params[name], '__name__'):
637
params[name] = params[name].__name__
638
if params.get('choices') is not None:
639
choices_str = ', '.join([str(c) for c in params['choices']])
640
params['choices'] = choices_str
641
return self._get_help_string(action) % params
642
643
def _iter_indented_subactions(self, action):
644
try:
645
get_subactions = action._get_subactions
646
except AttributeError:
647
pass
648
else:
649
self._indent()
650
yield from get_subactions()
651
self._dedent()
652
653
def _split_lines(self, text, width):
654
text = self._whitespace_matcher.sub(' ', text).strip()
655
# The textwrap module is used only for formatting help.
656
# Delay its import for speeding up the common usage of argparse.
657
import textwrap
658
return textwrap.wrap(text, width)
659
660
def _fill_text(self, text, width, indent):
661
text = self._whitespace_matcher.sub(' ', text).strip()
662
import textwrap
663
return textwrap.fill(text, width,
664
initial_indent=indent,
665
subsequent_indent=indent)
666
667
def _get_help_string(self, action):
668
return action.help
669
670
def _get_default_metavar_for_optional(self, action):
671
return action.dest.upper()
672
673
def _get_default_metavar_for_positional(self, action):
674
return action.dest
675
676
677
class RawDescriptionHelpFormatter(HelpFormatter):
678
"""Help message formatter which retains any formatting in descriptions.
679
680
Only the name of this class is considered a public API. All the methods
681
provided by the class are considered an implementation detail.
682
"""
683
684
def _fill_text(self, text, width, indent):
685
return ''.join(indent + line for line in text.splitlines(keepends=True))
686
687
688
class RawTextHelpFormatter(RawDescriptionHelpFormatter):
689
"""Help message formatter which retains formatting of all help text.
690
691
Only the name of this class is considered a public API. All the methods
692
provided by the class are considered an implementation detail.
693
"""
694
695
def _split_lines(self, text, width):
696
return text.splitlines()
697
698
699
class ArgumentDefaultsHelpFormatter(HelpFormatter):
700
"""Help message formatter which adds default values to argument help.
701
702
Only the name of this class is considered a public API. All the methods
703
provided by the class are considered an implementation detail.
704
"""
705
706
def _get_help_string(self, action):
707
"""
708
Add the default value to the option help message.
709
710
ArgumentDefaultsHelpFormatter and BooleanOptionalAction when it isn't
711
already present. This code will do that, detecting cornercases to
712
prevent duplicates or cases where it wouldn't make sense to the end
713
user.
714
"""
715
help = action.help
716
if help is None:
717
help = ''
718
719
if '%(default)' not in help:
720
if action.default is not SUPPRESS:
721
defaulting_nargs = [OPTIONAL, ZERO_OR_MORE]
722
if action.option_strings or action.nargs in defaulting_nargs:
723
help += ' (default: %(default)s)'
724
return help
725
726
727
728
class MetavarTypeHelpFormatter(HelpFormatter):
729
"""Help message formatter which uses the argument 'type' as the default
730
metavar value (instead of the argument 'dest')
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_default_metavar_for_optional(self, action):
737
return action.type.__name__
738
739
def _get_default_metavar_for_positional(self, action):
740
return action.type.__name__
741
742
743
# =====================
744
# Options and Arguments
745
# =====================
746
747
def _get_action_name(argument):
748
if argument is None:
749
return None
750
elif argument.option_strings:
751
return '/'.join(argument.option_strings)
752
elif argument.metavar not in (None, SUPPRESS):
753
return argument.metavar
754
elif argument.dest not in (None, SUPPRESS):
755
return argument.dest
756
elif argument.choices:
757
return '{' + ','.join(argument.choices) + '}'
758
else:
759
return None
760
761
762
class ArgumentError(Exception):
763
"""An error from creating or using an argument (optional or positional).
764
765
The string value of this exception is the message, augmented with
766
information about the argument that caused it.
767
"""
768
769
def __init__(self, argument, message):
770
self.argument_name = _get_action_name(argument)
771
self.message = message
772
773
def __str__(self):
774
if self.argument_name is None:
775
format = '%(message)s'
776
else:
777
format = _('argument %(argument_name)s: %(message)s')
778
return format % dict(message=self.message,
779
argument_name=self.argument_name)
780
781
782
class ArgumentTypeError(Exception):
783
"""An error from trying to convert a command line string to a type."""
784
pass
785
786
787
# ==============
788
# Action classes
789
# ==============
790
791
class Action(_AttributeHolder):
792
"""Information about how to convert command line strings to Python objects.
793
794
Action objects are used by an ArgumentParser to represent the information
795
needed to parse a single argument from one or more strings from the
796
command line. The keyword arguments to the Action constructor are also
797
all attributes of Action instances.
798
799
Keyword Arguments:
800
801
- option_strings -- A list of command-line option strings which
802
should be associated with this action.
803
804
- dest -- The name of the attribute to hold the created object(s)
805
806
- nargs -- The number of command-line arguments that should be
807
consumed. By default, one argument will be consumed and a single
808
value will be produced. Other values include:
809
- N (an integer) consumes N arguments (and produces a list)
810
- '?' consumes zero or one arguments
811
- '*' consumes zero or more arguments (and produces a list)
812
- '+' consumes one or more arguments (and produces a list)
813
Note that the difference between the default and nargs=1 is that
814
with the default, a single value will be produced, while with
815
nargs=1, a list containing a single value will be produced.
816
817
- const -- The value to be produced if the option is specified and the
818
option uses an action that takes no values.
819
820
- default -- The value to be produced if the option is not specified.
821
822
- type -- A callable that accepts a single string argument, and
823
returns the converted value. The standard Python types str, int,
824
float, and complex are useful examples of such callables. If None,
825
str is used.
826
827
- choices -- A container of values that should be allowed. If not None,
828
after a command-line argument has been converted to the appropriate
829
type, an exception will be raised if it is not a member of this
830
collection.
831
832
- required -- True if the action must always be specified at the
833
command line. This is only meaningful for optional command-line
834
arguments.
835
836
- help -- The help string describing the argument.
837
838
- metavar -- The name to be used for the option's argument with the
839
help string. If None, the 'dest' value will be used as the name.
840
"""
841
842
def __init__(self,
843
option_strings,
844
dest,
845
nargs=None,
846
const=None,
847
default=None,
848
type=None,
849
choices=None,
850
required=False,
851
help=None,
852
metavar=None):
853
self.option_strings = option_strings
854
self.dest = dest
855
self.nargs = nargs
856
self.const = const
857
self.default = default
858
self.type = type
859
self.choices = choices
860
self.required = required
861
self.help = help
862
self.metavar = metavar
863
864
def _get_kwargs(self):
865
names = [
866
'option_strings',
867
'dest',
868
'nargs',
869
'const',
870
'default',
871
'type',
872
'choices',
873
'required',
874
'help',
875
'metavar',
876
]
877
return [(name, getattr(self, name)) for name in names]
878
879
def format_usage(self):
880
return self.option_strings[0]
881
882
def __call__(self, parser, namespace, values, option_string=None):
883
raise NotImplementedError(_('.__call__() not defined'))
884
885
886
# FIXME: remove together with `BooleanOptionalAction` deprecated arguments.
887
_deprecated_default = object()
888
889
class BooleanOptionalAction(Action):
890
def __init__(self,
891
option_strings,
892
dest,
893
default=None,
894
type=_deprecated_default,
895
choices=_deprecated_default,
896
required=False,
897
help=None,
898
metavar=_deprecated_default):
899
900
_option_strings = []
901
for option_string in option_strings:
902
_option_strings.append(option_string)
903
904
if option_string.startswith('--'):
905
option_string = '--no-' + option_string[2:]
906
_option_strings.append(option_string)
907
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
926
super().__init__(
927
option_strings=_option_strings,
928
dest=dest,
929
nargs=0,
930
default=default,
931
type=type,
932
choices=choices,
933
required=required,
934
help=help,
935
metavar=metavar)
936
937
938
def __call__(self, parser, namespace, values, option_string=None):
939
if option_string in self.option_strings:
940
setattr(namespace, self.dest, not option_string.startswith('--no-'))
941
942
def format_usage(self):
943
return ' | '.join(self.option_strings)
944
945
946
class _StoreAction(Action):
947
948
def __init__(self,
949
option_strings,
950
dest,
951
nargs=None,
952
const=None,
953
default=None,
954
type=None,
955
choices=None,
956
required=False,
957
help=None,
958
metavar=None):
959
if nargs == 0:
960
raise ValueError('nargs for store actions must be != 0; if you '
961
'have nothing to store, actions such as store '
962
'true or store const may be more appropriate')
963
if const is not None and nargs != OPTIONAL:
964
raise ValueError('nargs must be %r to supply const' % OPTIONAL)
965
super(_StoreAction, self).__init__(
966
option_strings=option_strings,
967
dest=dest,
968
nargs=nargs,
969
const=const,
970
default=default,
971
type=type,
972
choices=choices,
973
required=required,
974
help=help,
975
metavar=metavar)
976
977
def __call__(self, parser, namespace, values, option_string=None):
978
setattr(namespace, self.dest, values)
979
980
981
class _StoreConstAction(Action):
982
983
def __init__(self,
984
option_strings,
985
dest,
986
const=None,
987
default=None,
988
required=False,
989
help=None,
990
metavar=None):
991
super(_StoreConstAction, self).__init__(
992
option_strings=option_strings,
993
dest=dest,
994
nargs=0,
995
const=const,
996
default=default,
997
required=required,
998
help=help)
999
1000
def __call__(self, parser, namespace, values, option_string=None):
1001
setattr(namespace, self.dest, self.const)
1002
1003
1004
class _StoreTrueAction(_StoreConstAction):
1005
1006
def __init__(self,
1007
option_strings,
1008
dest,
1009
default=False,
1010
required=False,
1011
help=None):
1012
super(_StoreTrueAction, self).__init__(
1013
option_strings=option_strings,
1014
dest=dest,
1015
const=True,
1016
default=default,
1017
required=required,
1018
help=help)
1019
1020
1021
class _StoreFalseAction(_StoreConstAction):
1022
1023
def __init__(self,
1024
option_strings,
1025
dest,
1026
default=True,
1027
required=False,
1028
help=None):
1029
super(_StoreFalseAction, self).__init__(
1030
option_strings=option_strings,
1031
dest=dest,
1032
const=False,
1033
default=default,
1034
required=required,
1035
help=help)
1036
1037
1038
class _AppendAction(Action):
1039
1040
def __init__(self,
1041
option_strings,
1042
dest,
1043
nargs=None,
1044
const=None,
1045
default=None,
1046
type=None,
1047
choices=None,
1048
required=False,
1049
help=None,
1050
metavar=None):
1051
if nargs == 0:
1052
raise ValueError('nargs for append actions must be != 0; if arg '
1053
'strings are not supplying the value to append, '
1054
'the append const action may be more appropriate')
1055
if const is not None and nargs != OPTIONAL:
1056
raise ValueError('nargs must be %r to supply const' % OPTIONAL)
1057
super(_AppendAction, self).__init__(
1058
option_strings=option_strings,
1059
dest=dest,
1060
nargs=nargs,
1061
const=const,
1062
default=default,
1063
type=type,
1064
choices=choices,
1065
required=required,
1066
help=help,
1067
metavar=metavar)
1068
1069
def __call__(self, parser, namespace, values, option_string=None):
1070
items = getattr(namespace, self.dest, None)
1071
items = _copy_items(items)
1072
items.append(values)
1073
setattr(namespace, self.dest, items)
1074
1075
1076
class _AppendConstAction(Action):
1077
1078
def __init__(self,
1079
option_strings,
1080
dest,
1081
const=None,
1082
default=None,
1083
required=False,
1084
help=None,
1085
metavar=None):
1086
super(_AppendConstAction, self).__init__(
1087
option_strings=option_strings,
1088
dest=dest,
1089
nargs=0,
1090
const=const,
1091
default=default,
1092
required=required,
1093
help=help,
1094
metavar=metavar)
1095
1096
def __call__(self, parser, namespace, values, option_string=None):
1097
items = getattr(namespace, self.dest, None)
1098
items = _copy_items(items)
1099
items.append(self.const)
1100
setattr(namespace, self.dest, items)
1101
1102
1103
class _CountAction(Action):
1104
1105
def __init__(self,
1106
option_strings,
1107
dest,
1108
default=None,
1109
required=False,
1110
help=None):
1111
super(_CountAction, self).__init__(
1112
option_strings=option_strings,
1113
dest=dest,
1114
nargs=0,
1115
default=default,
1116
required=required,
1117
help=help)
1118
1119
def __call__(self, parser, namespace, values, option_string=None):
1120
count = getattr(namespace, self.dest, None)
1121
if count is None:
1122
count = 0
1123
setattr(namespace, self.dest, count + 1)
1124
1125
1126
class _HelpAction(Action):
1127
1128
def __init__(self,
1129
option_strings,
1130
dest=SUPPRESS,
1131
default=SUPPRESS,
1132
help=None):
1133
super(_HelpAction, self).__init__(
1134
option_strings=option_strings,
1135
dest=dest,
1136
default=default,
1137
nargs=0,
1138
help=help)
1139
1140
def __call__(self, parser, namespace, values, option_string=None):
1141
parser.print_help()
1142
parser.exit()
1143
1144
1145
class _VersionAction(Action):
1146
1147
def __init__(self,
1148
option_strings,
1149
version=None,
1150
dest=SUPPRESS,
1151
default=SUPPRESS,
1152
help="show program's version number and exit"):
1153
super(_VersionAction, self).__init__(
1154
option_strings=option_strings,
1155
dest=dest,
1156
default=default,
1157
nargs=0,
1158
help=help)
1159
self.version = version
1160
1161
def __call__(self, parser, namespace, values, option_string=None):
1162
version = self.version
1163
if version is None:
1164
version = parser.version
1165
formatter = parser._get_formatter()
1166
formatter.add_text(version)
1167
parser._print_message(formatter.format_help(), _sys.stdout)
1168
parser.exit()
1169
1170
1171
class _SubParsersAction(Action):
1172
1173
class _ChoicesPseudoAction(Action):
1174
1175
def __init__(self, name, aliases, help):
1176
metavar = dest = name
1177
if aliases:
1178
metavar += ' (%s)' % ', '.join(aliases)
1179
sup = super(_SubParsersAction._ChoicesPseudoAction, self)
1180
sup.__init__(option_strings=[], dest=dest, help=help,
1181
metavar=metavar)
1182
1183
def __init__(self,
1184
option_strings,
1185
prog,
1186
parser_class,
1187
dest=SUPPRESS,
1188
required=False,
1189
help=None,
1190
metavar=None):
1191
1192
self._prog_prefix = prog
1193
self._parser_class = parser_class
1194
self._name_parser_map = {}
1195
self._choices_actions = []
1196
1197
super(_SubParsersAction, self).__init__(
1198
option_strings=option_strings,
1199
dest=dest,
1200
nargs=PARSER,
1201
choices=self._name_parser_map,
1202
required=required,
1203
help=help,
1204
metavar=metavar)
1205
1206
def add_parser(self, name, **kwargs):
1207
# set prog from the existing prefix
1208
if kwargs.get('prog') is None:
1209
kwargs['prog'] = '%s %s' % (self._prog_prefix, name)
1210
1211
aliases = kwargs.pop('aliases', ())
1212
1213
if name in self._name_parser_map:
1214
raise ArgumentError(self, _('conflicting subparser: %s') % name)
1215
for alias in aliases:
1216
if alias in self._name_parser_map:
1217
raise ArgumentError(
1218
self, _('conflicting subparser alias: %s') % alias)
1219
1220
# create a pseudo-action to hold the choice help
1221
if 'help' in kwargs:
1222
help = kwargs.pop('help')
1223
choice_action = self._ChoicesPseudoAction(name, aliases, help)
1224
self._choices_actions.append(choice_action)
1225
1226
# create the parser and add it to the map
1227
parser = self._parser_class(**kwargs)
1228
self._name_parser_map[name] = parser
1229
1230
# make parser available under aliases also
1231
for alias in aliases:
1232
self._name_parser_map[alias] = parser
1233
1234
return parser
1235
1236
def _get_subactions(self):
1237
return self._choices_actions
1238
1239
def __call__(self, parser, namespace, values, option_string=None):
1240
parser_name = values[0]
1241
arg_strings = values[1:]
1242
1243
# set the parser name if requested
1244
if self.dest is not SUPPRESS:
1245
setattr(namespace, self.dest, parser_name)
1246
1247
# select the parser
1248
try:
1249
parser = self._name_parser_map[parser_name]
1250
except KeyError:
1251
args = {'parser_name': parser_name,
1252
'choices': ', '.join(self._name_parser_map)}
1253
msg = _('unknown parser %(parser_name)r (choices: %(choices)s)') % args
1254
raise ArgumentError(self, msg)
1255
1256
# parse all the remaining options into the namespace
1257
# store any unrecognized options on the object, so that the top
1258
# level parser can decide what to do with them
1259
1260
# In case this subparser defines new defaults, we parse them
1261
# in a new namespace object and then update the original
1262
# namespace for the relevant parts.
1263
subnamespace, arg_strings = parser.parse_known_args(arg_strings, None)
1264
for key, value in vars(subnamespace).items():
1265
setattr(namespace, key, value)
1266
1267
if arg_strings:
1268
vars(namespace).setdefault(_UNRECOGNIZED_ARGS_ATTR, [])
1269
getattr(namespace, _UNRECOGNIZED_ARGS_ATTR).extend(arg_strings)
1270
1271
class _ExtendAction(_AppendAction):
1272
def __call__(self, parser, namespace, values, option_string=None):
1273
items = getattr(namespace, self.dest, None)
1274
items = _copy_items(items)
1275
items.extend(values)
1276
setattr(namespace, self.dest, items)
1277
1278
# ==============
1279
# Type classes
1280
# ==============
1281
1282
class FileType(object):
1283
"""Factory for creating file object types
1284
1285
Instances of FileType are typically passed as type= arguments to the
1286
ArgumentParser add_argument() method.
1287
1288
Keyword Arguments:
1289
- mode -- A string indicating how the file is to be opened. Accepts the
1290
same values as the builtin open() function.
1291
- bufsize -- The file's desired buffer size. Accepts the same values as
1292
the builtin open() function.
1293
- encoding -- The file's encoding. Accepts the same values as the
1294
builtin open() function.
1295
- errors -- A string indicating how encoding and decoding errors are to
1296
be handled. Accepts the same value as the builtin open() function.
1297
"""
1298
1299
def __init__(self, mode='r', bufsize=-1, encoding=None, errors=None):
1300
self._mode = mode
1301
self._bufsize = bufsize
1302
self._encoding = encoding
1303
self._errors = errors
1304
1305
def __call__(self, string):
1306
# the special argument "-" means sys.std{in,out}
1307
if string == '-':
1308
if 'r' in self._mode:
1309
return _sys.stdin.buffer if 'b' in self._mode else _sys.stdin
1310
elif any(c in self._mode for c in 'wax'):
1311
return _sys.stdout.buffer if 'b' in self._mode else _sys.stdout
1312
else:
1313
msg = _('argument "-" with mode %r') % self._mode
1314
raise ValueError(msg)
1315
1316
# all other arguments are used as file names
1317
try:
1318
return open(string, self._mode, self._bufsize, self._encoding,
1319
self._errors)
1320
except OSError as e:
1321
args = {'filename': string, 'error': e}
1322
message = _("can't open '%(filename)s': %(error)s")
1323
raise ArgumentTypeError(message % args)
1324
1325
def __repr__(self):
1326
args = self._mode, self._bufsize
1327
kwargs = [('encoding', self._encoding), ('errors', self._errors)]
1328
args_str = ', '.join([repr(arg) for arg in args if arg != -1] +
1329
['%s=%r' % (kw, arg) for kw, arg in kwargs
1330
if arg is not None])
1331
return '%s(%s)' % (type(self).__name__, args_str)
1332
1333
# ===========================
1334
# Optional and Positional Parsing
1335
# ===========================
1336
1337
class Namespace(_AttributeHolder):
1338
"""Simple object for storing attributes.
1339
1340
Implements equality by attribute names and values, and provides a simple
1341
string representation.
1342
"""
1343
1344
def __init__(self, **kwargs):
1345
for name in kwargs:
1346
setattr(self, name, kwargs[name])
1347
1348
def __eq__(self, other):
1349
if not isinstance(other, Namespace):
1350
return NotImplemented
1351
return vars(self) == vars(other)
1352
1353
def __contains__(self, key):
1354
return key in self.__dict__
1355
1356
1357
class _ActionsContainer(object):
1358
1359
def __init__(self,
1360
description,
1361
prefix_chars,
1362
argument_default,
1363
conflict_handler):
1364
super(_ActionsContainer, self).__init__()
1365
1366
self.description = description
1367
self.argument_default = argument_default
1368
self.prefix_chars = prefix_chars
1369
self.conflict_handler = conflict_handler
1370
1371
# set up registries
1372
self._registries = {}
1373
1374
# register actions
1375
self.register('action', None, _StoreAction)
1376
self.register('action', 'store', _StoreAction)
1377
self.register('action', 'store_const', _StoreConstAction)
1378
self.register('action', 'store_true', _StoreTrueAction)
1379
self.register('action', 'store_false', _StoreFalseAction)
1380
self.register('action', 'append', _AppendAction)
1381
self.register('action', 'append_const', _AppendConstAction)
1382
self.register('action', 'count', _CountAction)
1383
self.register('action', 'help', _HelpAction)
1384
self.register('action', 'version', _VersionAction)
1385
self.register('action', 'parsers', _SubParsersAction)
1386
self.register('action', 'extend', _ExtendAction)
1387
1388
# raise an exception if the conflict handler is invalid
1389
self._get_handler()
1390
1391
# action storage
1392
self._actions = []
1393
self._option_string_actions = {}
1394
1395
# groups
1396
self._action_groups = []
1397
self._mutually_exclusive_groups = []
1398
1399
# defaults storage
1400
self._defaults = {}
1401
1402
# determines whether an "option" looks like a negative number
1403
self._negative_number_matcher = _re.compile(r'^-\d+$|^-\d*\.\d+$')
1404
1405
# whether or not there are any optionals that look like negative
1406
# numbers -- uses a list so it can be shared and edited
1407
self._has_negative_number_optionals = []
1408
1409
# ====================
1410
# Registration methods
1411
# ====================
1412
def register(self, registry_name, value, object):
1413
registry = self._registries.setdefault(registry_name, {})
1414
registry[value] = object
1415
1416
def _registry_get(self, registry_name, value, default=None):
1417
return self._registries[registry_name].get(value, default)
1418
1419
# ==================================
1420
# Namespace default accessor methods
1421
# ==================================
1422
def set_defaults(self, **kwargs):
1423
self._defaults.update(kwargs)
1424
1425
# if these defaults match any existing arguments, replace
1426
# the previous default on the object with the new one
1427
for action in self._actions:
1428
if action.dest in kwargs:
1429
action.default = kwargs[action.dest]
1430
1431
def get_default(self, dest):
1432
for action in self._actions:
1433
if action.dest == dest and action.default is not None:
1434
return action.default
1435
return self._defaults.get(dest, None)
1436
1437
1438
# =======================
1439
# Adding argument actions
1440
# =======================
1441
def add_argument(self, *args, **kwargs):
1442
"""
1443
add_argument(dest, ..., name=value, ...)
1444
add_argument(option_string, option_string, ..., name=value, ...)
1445
"""
1446
1447
# if no positional args are supplied or only one is supplied and
1448
# it doesn't look like an option string, parse a positional
1449
# argument
1450
chars = self.prefix_chars
1451
if not args or len(args) == 1 and args[0][0] not in chars:
1452
if args and 'dest' in kwargs:
1453
raise ValueError('dest supplied twice for positional argument')
1454
kwargs = self._get_positional_kwargs(*args, **kwargs)
1455
1456
# otherwise, we're adding an optional argument
1457
else:
1458
kwargs = self._get_optional_kwargs(*args, **kwargs)
1459
1460
# if no default was supplied, use the parser-level default
1461
if 'default' not in kwargs:
1462
dest = kwargs['dest']
1463
if dest in self._defaults:
1464
kwargs['default'] = self._defaults[dest]
1465
elif self.argument_default is not None:
1466
kwargs['default'] = self.argument_default
1467
1468
# create the action object, and add it to the parser
1469
action_class = self._pop_action_class(kwargs)
1470
if not callable(action_class):
1471
raise ValueError('unknown action "%s"' % (action_class,))
1472
action = action_class(**kwargs)
1473
1474
# raise an error if the action type is not callable
1475
type_func = self._registry_get('type', action.type, action.type)
1476
if not callable(type_func):
1477
raise ValueError('%r is not callable' % (type_func,))
1478
1479
if type_func is FileType:
1480
raise ValueError('%r is a FileType class object, instance of it'
1481
' must be passed' % (type_func,))
1482
1483
# raise an error if the metavar does not match the type
1484
if hasattr(self, "_get_formatter"):
1485
try:
1486
self._get_formatter()._format_args(action, None)
1487
except TypeError:
1488
raise ValueError("length of metavar tuple does not match nargs")
1489
1490
return self._add_action(action)
1491
1492
def add_argument_group(self, *args, **kwargs):
1493
group = _ArgumentGroup(self, *args, **kwargs)
1494
self._action_groups.append(group)
1495
return group
1496
1497
def add_mutually_exclusive_group(self, **kwargs):
1498
group = _MutuallyExclusiveGroup(self, **kwargs)
1499
self._mutually_exclusive_groups.append(group)
1500
return group
1501
1502
def _add_action(self, action):
1503
# resolve any conflicts
1504
self._check_conflict(action)
1505
1506
# add to actions list
1507
self._actions.append(action)
1508
action.container = self
1509
1510
# index the action by any option strings it has
1511
for option_string in action.option_strings:
1512
self._option_string_actions[option_string] = action
1513
1514
# set the flag if any option strings look like negative numbers
1515
for option_string in action.option_strings:
1516
if self._negative_number_matcher.match(option_string):
1517
if not self._has_negative_number_optionals:
1518
self._has_negative_number_optionals.append(True)
1519
1520
# return the created action
1521
return action
1522
1523
def _remove_action(self, action):
1524
self._actions.remove(action)
1525
1526
def _add_container_actions(self, container):
1527
# collect groups by titles
1528
title_group_map = {}
1529
for group in self._action_groups:
1530
if group.title in title_group_map:
1531
# This branch could happen if a derived class added
1532
# groups with duplicated titles in __init__
1533
msg = _('cannot merge actions - two groups are named %r')
1534
raise ValueError(msg % (group.title))
1535
title_group_map[group.title] = group
1536
1537
# map each action to its group
1538
group_map = {}
1539
for group in container._action_groups:
1540
1541
# if a group with the title exists, use that, otherwise
1542
# create a new group matching the container's group
1543
if group.title not in title_group_map:
1544
title_group_map[group.title] = self.add_argument_group(
1545
title=group.title,
1546
description=group.description,
1547
conflict_handler=group.conflict_handler)
1548
1549
# map the actions to their new group
1550
for action in group._group_actions:
1551
group_map[action] = title_group_map[group.title]
1552
1553
# add container's mutually exclusive groups
1554
# NOTE: if add_mutually_exclusive_group ever gains title= and
1555
# description= then this code will need to be expanded as above
1556
for group in container._mutually_exclusive_groups:
1557
mutex_group = self.add_mutually_exclusive_group(
1558
required=group.required)
1559
1560
# map the actions to their new mutex group
1561
for action in group._group_actions:
1562
group_map[action] = mutex_group
1563
1564
# add all actions to this container or their group
1565
for action in container._actions:
1566
group_map.get(action, self)._add_action(action)
1567
1568
def _get_positional_kwargs(self, dest, **kwargs):
1569
# make sure required is not specified
1570
if 'required' in kwargs:
1571
msg = _("'required' is an invalid argument for positionals")
1572
raise TypeError(msg)
1573
1574
# mark positional arguments as required if at least one is
1575
# always required
1576
if kwargs.get('nargs') not in [OPTIONAL, ZERO_OR_MORE]:
1577
kwargs['required'] = True
1578
if kwargs.get('nargs') == ZERO_OR_MORE and 'default' not in kwargs:
1579
kwargs['required'] = True
1580
1581
# return the keyword arguments with no option strings
1582
return dict(kwargs, dest=dest, option_strings=[])
1583
1584
def _get_optional_kwargs(self, *args, **kwargs):
1585
# determine short and long option strings
1586
option_strings = []
1587
long_option_strings = []
1588
for option_string in args:
1589
# error on strings that don't start with an appropriate prefix
1590
if not option_string[0] in self.prefix_chars:
1591
args = {'option': option_string,
1592
'prefix_chars': self.prefix_chars}
1593
msg = _('invalid option string %(option)r: '
1594
'must start with a character %(prefix_chars)r')
1595
raise ValueError(msg % args)
1596
1597
# strings starting with two prefix characters are long options
1598
option_strings.append(option_string)
1599
if len(option_string) > 1 and option_string[1] in self.prefix_chars:
1600
long_option_strings.append(option_string)
1601
1602
# infer destination, '--foo-bar' -> 'foo_bar' and '-x' -> 'x'
1603
dest = kwargs.pop('dest', None)
1604
if dest is None:
1605
if long_option_strings:
1606
dest_option_string = long_option_strings[0]
1607
else:
1608
dest_option_string = option_strings[0]
1609
dest = dest_option_string.lstrip(self.prefix_chars)
1610
if not dest:
1611
msg = _('dest= is required for options like %r')
1612
raise ValueError(msg % option_string)
1613
dest = dest.replace('-', '_')
1614
1615
# return the updated keyword arguments
1616
return dict(kwargs, dest=dest, option_strings=option_strings)
1617
1618
def _pop_action_class(self, kwargs, default=None):
1619
action = kwargs.pop('action', default)
1620
return self._registry_get('action', action, action)
1621
1622
def _get_handler(self):
1623
# determine function from conflict handler string
1624
handler_func_name = '_handle_conflict_%s' % self.conflict_handler
1625
try:
1626
return getattr(self, handler_func_name)
1627
except AttributeError:
1628
msg = _('invalid conflict_resolution value: %r')
1629
raise ValueError(msg % self.conflict_handler)
1630
1631
def _check_conflict(self, action):
1632
1633
# find all options that conflict with this option
1634
confl_optionals = []
1635
for option_string in action.option_strings:
1636
if option_string in self._option_string_actions:
1637
confl_optional = self._option_string_actions[option_string]
1638
confl_optionals.append((option_string, confl_optional))
1639
1640
# resolve any conflicts
1641
if confl_optionals:
1642
conflict_handler = self._get_handler()
1643
conflict_handler(action, confl_optionals)
1644
1645
def _handle_conflict_error(self, action, conflicting_actions):
1646
message = ngettext('conflicting option string: %s',
1647
'conflicting option strings: %s',
1648
len(conflicting_actions))
1649
conflict_string = ', '.join([option_string
1650
for option_string, action
1651
in conflicting_actions])
1652
raise ArgumentError(action, message % conflict_string)
1653
1654
def _handle_conflict_resolve(self, action, conflicting_actions):
1655
1656
# remove all conflicting options
1657
for option_string, action in conflicting_actions:
1658
1659
# remove the conflicting option
1660
action.option_strings.remove(option_string)
1661
self._option_string_actions.pop(option_string, None)
1662
1663
# if the option now has no option string, remove it from the
1664
# container holding it
1665
if not action.option_strings:
1666
action.container._remove_action(action)
1667
1668
1669
class _ArgumentGroup(_ActionsContainer):
1670
1671
def __init__(self, container, title=None, description=None, **kwargs):
1672
# add any missing keyword arguments by checking the container
1673
update = kwargs.setdefault
1674
update('conflict_handler', container.conflict_handler)
1675
update('prefix_chars', container.prefix_chars)
1676
update('argument_default', container.argument_default)
1677
super_init = super(_ArgumentGroup, self).__init__
1678
super_init(description=description, **kwargs)
1679
1680
# group attributes
1681
self.title = title
1682
self._group_actions = []
1683
1684
# share most attributes with the container
1685
self._registries = container._registries
1686
self._actions = container._actions
1687
self._option_string_actions = container._option_string_actions
1688
self._defaults = container._defaults
1689
self._has_negative_number_optionals = \
1690
container._has_negative_number_optionals
1691
self._mutually_exclusive_groups = container._mutually_exclusive_groups
1692
1693
def _add_action(self, action):
1694
action = super(_ArgumentGroup, self)._add_action(action)
1695
self._group_actions.append(action)
1696
return action
1697
1698
def _remove_action(self, action):
1699
super(_ArgumentGroup, self)._remove_action(action)
1700
self._group_actions.remove(action)
1701
1702
def add_argument_group(self, *args, **kwargs):
1703
warnings.warn(
1704
"Nesting argument groups is deprecated.",
1705
category=DeprecationWarning,
1706
stacklevel=2
1707
)
1708
return super().add_argument_group(*args, **kwargs)
1709
1710
1711
class _MutuallyExclusiveGroup(_ArgumentGroup):
1712
1713
def __init__(self, container, required=False):
1714
super(_MutuallyExclusiveGroup, self).__init__(container)
1715
self.required = required
1716
self._container = container
1717
1718
def _add_action(self, action):
1719
if action.required:
1720
msg = _('mutually exclusive arguments must be optional')
1721
raise ValueError(msg)
1722
action = self._container._add_action(action)
1723
self._group_actions.append(action)
1724
return action
1725
1726
def _remove_action(self, action):
1727
self._container._remove_action(action)
1728
self._group_actions.remove(action)
1729
1730
def add_mutually_exclusive_group(self, *args, **kwargs):
1731
warnings.warn(
1732
"Nesting mutually exclusive groups is deprecated.",
1733
category=DeprecationWarning,
1734
stacklevel=2
1735
)
1736
return super().add_mutually_exclusive_group(*args, **kwargs)
1737
1738
1739
class ArgumentParser(_AttributeHolder, _ActionsContainer):
1740
"""Object for parsing command line strings into Python objects.
1741
1742
Keyword Arguments:
1743
- prog -- The name of the program (default:
1744
``os.path.basename(sys.argv[0])``)
1745
- usage -- A usage message (default: auto-generated from arguments)
1746
- description -- A description of what the program does
1747
- epilog -- Text following the argument descriptions
1748
- parents -- Parsers whose arguments should be copied into this one
1749
- formatter_class -- HelpFormatter class for printing help messages
1750
- prefix_chars -- Characters that prefix optional arguments
1751
- fromfile_prefix_chars -- Characters that prefix files containing
1752
additional arguments
1753
- argument_default -- The default value for all arguments
1754
- conflict_handler -- String indicating how to handle conflicts
1755
- add_help -- Add a -h/-help option
1756
- allow_abbrev -- Allow long options to be abbreviated unambiguously
1757
- exit_on_error -- Determines whether or not ArgumentParser exits with
1758
error info when an error occurs
1759
"""
1760
1761
def __init__(self,
1762
prog=None,
1763
usage=None,
1764
description=None,
1765
epilog=None,
1766
parents=[],
1767
formatter_class=HelpFormatter,
1768
prefix_chars='-',
1769
fromfile_prefix_chars=None,
1770
argument_default=None,
1771
conflict_handler='error',
1772
add_help=True,
1773
allow_abbrev=True,
1774
exit_on_error=True):
1775
1776
superinit = super(ArgumentParser, self).__init__
1777
superinit(description=description,
1778
prefix_chars=prefix_chars,
1779
argument_default=argument_default,
1780
conflict_handler=conflict_handler)
1781
1782
# default setting for prog
1783
if prog is None:
1784
prog = _os.path.basename(_sys.argv[0])
1785
1786
self.prog = prog
1787
self.usage = usage
1788
self.epilog = epilog
1789
self.formatter_class = formatter_class
1790
self.fromfile_prefix_chars = fromfile_prefix_chars
1791
self.add_help = add_help
1792
self.allow_abbrev = allow_abbrev
1793
self.exit_on_error = exit_on_error
1794
1795
add_group = self.add_argument_group
1796
self._positionals = add_group(_('positional arguments'))
1797
self._optionals = add_group(_('options'))
1798
self._subparsers = None
1799
1800
# register types
1801
def identity(string):
1802
return string
1803
self.register('type', None, identity)
1804
1805
# add help argument if necessary
1806
# (using explicit default to override global argument_default)
1807
default_prefix = '-' if '-' in prefix_chars else prefix_chars[0]
1808
if self.add_help:
1809
self.add_argument(
1810
default_prefix+'h', default_prefix*2+'help',
1811
action='help', default=SUPPRESS,
1812
help=_('show this help message and exit'))
1813
1814
# add parent arguments and defaults
1815
for parent in parents:
1816
if not isinstance(parent, ArgumentParser):
1817
raise TypeError('parents must be a list of ArgumentParser')
1818
self._add_container_actions(parent)
1819
defaults = parent._defaults
1820
self._defaults.update(defaults)
1821
1822
# =======================
1823
# Pretty __repr__ methods
1824
# =======================
1825
def _get_kwargs(self):
1826
names = [
1827
'prog',
1828
'usage',
1829
'description',
1830
'formatter_class',
1831
'conflict_handler',
1832
'add_help',
1833
]
1834
return [(name, getattr(self, name)) for name in names]
1835
1836
# ==================================
1837
# Optional/Positional adding methods
1838
# ==================================
1839
def add_subparsers(self, **kwargs):
1840
if self._subparsers is not None:
1841
self.error(_('cannot have multiple subparser arguments'))
1842
1843
# add the parser class to the arguments if it's not present
1844
kwargs.setdefault('parser_class', type(self))
1845
1846
if 'title' in kwargs or 'description' in kwargs:
1847
title = _(kwargs.pop('title', 'subcommands'))
1848
description = _(kwargs.pop('description', None))
1849
self._subparsers = self.add_argument_group(title, description)
1850
else:
1851
self._subparsers = self._positionals
1852
1853
# prog defaults to the usage message of this parser, skipping
1854
# optional arguments and with no "usage:" prefix
1855
if kwargs.get('prog') is None:
1856
formatter = self._get_formatter()
1857
positionals = self._get_positional_actions()
1858
groups = self._mutually_exclusive_groups
1859
formatter.add_usage(self.usage, positionals, groups, '')
1860
kwargs['prog'] = formatter.format_help().strip()
1861
1862
# create the parsers action and add it to the positionals list
1863
parsers_class = self._pop_action_class(kwargs, 'parsers')
1864
action = parsers_class(option_strings=[], **kwargs)
1865
self._subparsers._add_action(action)
1866
1867
# return the created parsers action
1868
return action
1869
1870
def _add_action(self, action):
1871
if action.option_strings:
1872
self._optionals._add_action(action)
1873
else:
1874
self._positionals._add_action(action)
1875
return action
1876
1877
def _get_optional_actions(self):
1878
return [action
1879
for action in self._actions
1880
if action.option_strings]
1881
1882
def _get_positional_actions(self):
1883
return [action
1884
for action in self._actions
1885
if not action.option_strings]
1886
1887
# =====================================
1888
# Command line argument parsing methods
1889
# =====================================
1890
def parse_args(self, args=None, namespace=None):
1891
args, argv = self.parse_known_args(args, namespace)
1892
if argv:
1893
msg = _('unrecognized arguments: %s')
1894
self.error(msg % ' '.join(argv))
1895
return args
1896
1897
def parse_known_args(self, args=None, namespace=None):
1898
if args is None:
1899
# args default to the system args
1900
args = _sys.argv[1:]
1901
else:
1902
# make sure that args are mutable
1903
args = list(args)
1904
1905
# default Namespace built from parser defaults
1906
if namespace is None:
1907
namespace = Namespace()
1908
1909
# add any action defaults that aren't present
1910
for action in self._actions:
1911
if action.dest is not SUPPRESS:
1912
if not hasattr(namespace, action.dest):
1913
if action.default is not SUPPRESS:
1914
setattr(namespace, action.dest, action.default)
1915
1916
# add any parser defaults that aren't present
1917
for dest in self._defaults:
1918
if not hasattr(namespace, dest):
1919
setattr(namespace, dest, self._defaults[dest])
1920
1921
# parse the arguments and exit if there are any errors
1922
if self.exit_on_error:
1923
try:
1924
namespace, args = self._parse_known_args(args, namespace)
1925
except ArgumentError as err:
1926
self.error(str(err))
1927
else:
1928
namespace, args = self._parse_known_args(args, namespace)
1929
1930
if hasattr(namespace, _UNRECOGNIZED_ARGS_ATTR):
1931
args.extend(getattr(namespace, _UNRECOGNIZED_ARGS_ATTR))
1932
delattr(namespace, _UNRECOGNIZED_ARGS_ATTR)
1933
return namespace, args
1934
1935
def _parse_known_args(self, arg_strings, namespace):
1936
# replace arg strings that are file references
1937
if self.fromfile_prefix_chars is not None:
1938
arg_strings = self._read_args_from_files(arg_strings)
1939
1940
# map all mutually exclusive arguments to the other arguments
1941
# they can't occur with
1942
action_conflicts = {}
1943
for mutex_group in self._mutually_exclusive_groups:
1944
group_actions = mutex_group._group_actions
1945
for i, mutex_action in enumerate(mutex_group._group_actions):
1946
conflicts = action_conflicts.setdefault(mutex_action, [])
1947
conflicts.extend(group_actions[:i])
1948
conflicts.extend(group_actions[i + 1:])
1949
1950
# find all option indices, and determine the arg_string_pattern
1951
# which has an 'O' if there is an option at an index,
1952
# an 'A' if there is an argument, or a '-' if there is a '--'
1953
option_string_indices = {}
1954
arg_string_pattern_parts = []
1955
arg_strings_iter = iter(arg_strings)
1956
for i, arg_string in enumerate(arg_strings_iter):
1957
1958
# all args after -- are non-options
1959
if arg_string == '--':
1960
arg_string_pattern_parts.append('-')
1961
for arg_string in arg_strings_iter:
1962
arg_string_pattern_parts.append('A')
1963
1964
# otherwise, add the arg to the arg strings
1965
# and note the index if it was an option
1966
else:
1967
option_tuple = self._parse_optional(arg_string)
1968
if option_tuple is None:
1969
pattern = 'A'
1970
else:
1971
option_string_indices[i] = option_tuple
1972
pattern = 'O'
1973
arg_string_pattern_parts.append(pattern)
1974
1975
# join the pieces together to form the pattern
1976
arg_strings_pattern = ''.join(arg_string_pattern_parts)
1977
1978
# converts arg strings to the appropriate and then takes the action
1979
seen_actions = set()
1980
seen_non_default_actions = set()
1981
1982
def take_action(action, argument_strings, option_string=None):
1983
seen_actions.add(action)
1984
argument_values = self._get_values(action, argument_strings)
1985
1986
# error if this argument is not allowed with other previously
1987
# seen arguments, assuming that actions that use the default
1988
# value don't really count as "present"
1989
if argument_values is not action.default:
1990
seen_non_default_actions.add(action)
1991
for conflict_action in action_conflicts.get(action, []):
1992
if conflict_action in seen_non_default_actions:
1993
msg = _('not allowed with argument %s')
1994
action_name = _get_action_name(conflict_action)
1995
raise ArgumentError(action, msg % action_name)
1996
1997
# take the action if we didn't receive a SUPPRESS value
1998
# (e.g. from a default)
1999
if argument_values is not SUPPRESS:
2000
action(self, namespace, argument_values, option_string)
2001
2002
# function to convert arg_strings into an optional action
2003
def consume_optional(start_index):
2004
2005
# get the optional identified at this index
2006
option_tuple = option_string_indices[start_index]
2007
action, option_string, explicit_arg = option_tuple
2008
2009
# identify additional optionals in the same arg string
2010
# (e.g. -xyz is the same as -x -y -z if no args are required)
2011
match_argument = self._match_argument
2012
action_tuples = []
2013
while True:
2014
2015
# if we found no optional action, skip it
2016
if action is None:
2017
extras.append(arg_strings[start_index])
2018
return start_index + 1
2019
2020
# if there is an explicit argument, try to match the
2021
# optional's string arguments to only this
2022
if explicit_arg is not None:
2023
arg_count = match_argument(action, 'A')
2024
2025
# if the action is a single-dash option and takes no
2026
# arguments, try to parse more single-dash options out
2027
# of the tail of the option string
2028
chars = self.prefix_chars
2029
if (
2030
arg_count == 0
2031
and option_string[1] not in chars
2032
and explicit_arg != ''
2033
):
2034
action_tuples.append((action, [], option_string))
2035
char = option_string[0]
2036
option_string = char + explicit_arg[0]
2037
new_explicit_arg = explicit_arg[1:] or None
2038
optionals_map = self._option_string_actions
2039
if option_string in optionals_map:
2040
action = optionals_map[option_string]
2041
explicit_arg = new_explicit_arg
2042
else:
2043
msg = _('ignored explicit argument %r')
2044
raise ArgumentError(action, msg % explicit_arg)
2045
2046
# if the action expect exactly one argument, we've
2047
# successfully matched the option; exit the loop
2048
elif arg_count == 1:
2049
stop = start_index + 1
2050
args = [explicit_arg]
2051
action_tuples.append((action, args, option_string))
2052
break
2053
2054
# error if a double-dash option did not use the
2055
# explicit argument
2056
else:
2057
msg = _('ignored explicit argument %r')
2058
raise ArgumentError(action, msg % explicit_arg)
2059
2060
# if there is no explicit argument, try to match the
2061
# optional's string arguments with the following strings
2062
# if successful, exit the loop
2063
else:
2064
start = start_index + 1
2065
selected_patterns = arg_strings_pattern[start:]
2066
arg_count = match_argument(action, selected_patterns)
2067
stop = start + arg_count
2068
args = arg_strings[start:stop]
2069
action_tuples.append((action, args, option_string))
2070
break
2071
2072
# add the Optional to the list and return the index at which
2073
# the Optional's string args stopped
2074
assert action_tuples
2075
for action, args, option_string in action_tuples:
2076
take_action(action, args, option_string)
2077
return stop
2078
2079
# the list of Positionals left to be parsed; this is modified
2080
# by consume_positionals()
2081
positionals = self._get_positional_actions()
2082
2083
# function to convert arg_strings into positional actions
2084
def consume_positionals(start_index):
2085
# match as many Positionals as possible
2086
match_partial = self._match_arguments_partial
2087
selected_pattern = arg_strings_pattern[start_index:]
2088
arg_counts = match_partial(positionals, selected_pattern)
2089
2090
# slice off the appropriate arg strings for each Positional
2091
# and add the Positional and its args to the list
2092
for action, arg_count in zip(positionals, arg_counts):
2093
args = arg_strings[start_index: start_index + arg_count]
2094
start_index += arg_count
2095
take_action(action, args)
2096
2097
# slice off the Positionals that we just parsed and return the
2098
# index at which the Positionals' string args stopped
2099
positionals[:] = positionals[len(arg_counts):]
2100
return start_index
2101
2102
# consume Positionals and Optionals alternately, until we have
2103
# passed the last option string
2104
extras = []
2105
start_index = 0
2106
if option_string_indices:
2107
max_option_string_index = max(option_string_indices)
2108
else:
2109
max_option_string_index = -1
2110
while start_index <= max_option_string_index:
2111
2112
# consume any Positionals preceding the next option
2113
next_option_string_index = min([
2114
index
2115
for index in option_string_indices
2116
if index >= start_index])
2117
if start_index != next_option_string_index:
2118
positionals_end_index = consume_positionals(start_index)
2119
2120
# only try to parse the next optional if we didn't consume
2121
# the option string during the positionals parsing
2122
if positionals_end_index > start_index:
2123
start_index = positionals_end_index
2124
continue
2125
else:
2126
start_index = positionals_end_index
2127
2128
# if we consumed all the positionals we could and we're not
2129
# at the index of an option string, there were extra arguments
2130
if start_index not in option_string_indices:
2131
strings = arg_strings[start_index:next_option_string_index]
2132
extras.extend(strings)
2133
start_index = next_option_string_index
2134
2135
# consume the next optional and any arguments for it
2136
start_index = consume_optional(start_index)
2137
2138
# consume any positionals following the last Optional
2139
stop_index = consume_positionals(start_index)
2140
2141
# if we didn't consume all the argument strings, there were extras
2142
extras.extend(arg_strings[stop_index:])
2143
2144
# make sure all required actions were present and also convert
2145
# action defaults which were not given as arguments
2146
required_actions = []
2147
for action in self._actions:
2148
if action not in seen_actions:
2149
if action.required:
2150
required_actions.append(_get_action_name(action))
2151
else:
2152
# Convert action default now instead of doing it before
2153
# parsing arguments to avoid calling convert functions
2154
# twice (which may fail) if the argument was given, but
2155
# only if it was defined already in the namespace
2156
if (action.default is not None and
2157
isinstance(action.default, str) and
2158
hasattr(namespace, action.dest) and
2159
action.default is getattr(namespace, action.dest)):
2160
setattr(namespace, action.dest,
2161
self._get_value(action, action.default))
2162
2163
if required_actions:
2164
self.error(_('the following arguments are required: %s') %
2165
', '.join(required_actions))
2166
2167
# make sure all required groups had one option present
2168
for group in self._mutually_exclusive_groups:
2169
if group.required:
2170
for action in group._group_actions:
2171
if action in seen_non_default_actions:
2172
break
2173
2174
# if no actions were used, report the error
2175
else:
2176
names = [_get_action_name(action)
2177
for action in group._group_actions
2178
if action.help is not SUPPRESS]
2179
msg = _('one of the arguments %s is required')
2180
self.error(msg % ' '.join(names))
2181
2182
# return the updated namespace and the extra arguments
2183
return namespace, extras
2184
2185
def _read_args_from_files(self, arg_strings):
2186
# expand arguments referencing files
2187
new_arg_strings = []
2188
for arg_string in arg_strings:
2189
2190
# for regular arguments, just add them back into the list
2191
if not arg_string or arg_string[0] not in self.fromfile_prefix_chars:
2192
new_arg_strings.append(arg_string)
2193
2194
# replace arguments referencing files with the file content
2195
else:
2196
try:
2197
with open(arg_string[1:],
2198
encoding=_sys.getfilesystemencoding(),
2199
errors=_sys.getfilesystemencodeerrors()) as args_file:
2200
arg_strings = []
2201
for arg_line in args_file.read().splitlines():
2202
for arg in self.convert_arg_line_to_args(arg_line):
2203
arg_strings.append(arg)
2204
arg_strings = self._read_args_from_files(arg_strings)
2205
new_arg_strings.extend(arg_strings)
2206
except OSError as err:
2207
self.error(str(err))
2208
2209
# return the modified argument list
2210
return new_arg_strings
2211
2212
def convert_arg_line_to_args(self, arg_line):
2213
return [arg_line]
2214
2215
def _match_argument(self, action, arg_strings_pattern):
2216
# match the pattern for this action to the arg strings
2217
nargs_pattern = self._get_nargs_pattern(action)
2218
match = _re.match(nargs_pattern, arg_strings_pattern)
2219
2220
# raise an exception if we weren't able to find a match
2221
if match is None:
2222
nargs_errors = {
2223
None: _('expected one argument'),
2224
OPTIONAL: _('expected at most one argument'),
2225
ONE_OR_MORE: _('expected at least one argument'),
2226
}
2227
msg = nargs_errors.get(action.nargs)
2228
if msg is None:
2229
msg = ngettext('expected %s argument',
2230
'expected %s arguments',
2231
action.nargs) % action.nargs
2232
raise ArgumentError(action, msg)
2233
2234
# return the number of arguments matched
2235
return len(match.group(1))
2236
2237
def _match_arguments_partial(self, actions, arg_strings_pattern):
2238
# progressively shorten the actions list by slicing off the
2239
# final actions until we find a match
2240
result = []
2241
for i in range(len(actions), 0, -1):
2242
actions_slice = actions[:i]
2243
pattern = ''.join([self._get_nargs_pattern(action)
2244
for action in actions_slice])
2245
match = _re.match(pattern, arg_strings_pattern)
2246
if match is not None:
2247
result.extend([len(string) for string in match.groups()])
2248
break
2249
2250
# return the list of arg string counts
2251
return result
2252
2253
def _parse_optional(self, arg_string):
2254
# if it's an empty string, it was meant to be a positional
2255
if not arg_string:
2256
return None
2257
2258
# if it doesn't start with a prefix, it was meant to be positional
2259
if not arg_string[0] in self.prefix_chars:
2260
return None
2261
2262
# if the option string is present in the parser, return the action
2263
if arg_string in self._option_string_actions:
2264
action = self._option_string_actions[arg_string]
2265
return action, arg_string, None
2266
2267
# if it's just a single character, it was meant to be positional
2268
if len(arg_string) == 1:
2269
return None
2270
2271
# if the option string before the "=" is present, return the action
2272
if '=' in arg_string:
2273
option_string, explicit_arg = arg_string.split('=', 1)
2274
if option_string in self._option_string_actions:
2275
action = self._option_string_actions[option_string]
2276
return action, option_string, explicit_arg
2277
2278
# search through all possible prefixes of the option string
2279
# and all actions in the parser for possible interpretations
2280
option_tuples = self._get_option_tuples(arg_string)
2281
2282
# if multiple actions match, the option string was ambiguous
2283
if len(option_tuples) > 1:
2284
options = ', '.join([option_string
2285
for action, option_string, explicit_arg in option_tuples])
2286
args = {'option': arg_string, 'matches': options}
2287
msg = _('ambiguous option: %(option)s could match %(matches)s')
2288
self.error(msg % args)
2289
2290
# if exactly one action matched, this segmentation is good,
2291
# so return the parsed action
2292
elif len(option_tuples) == 1:
2293
option_tuple, = option_tuples
2294
return option_tuple
2295
2296
# if it was not found as an option, but it looks like a negative
2297
# number, it was meant to be positional
2298
# unless there are negative-number-like options
2299
if self._negative_number_matcher.match(arg_string):
2300
if not self._has_negative_number_optionals:
2301
return None
2302
2303
# if it contains a space, it was meant to be a positional
2304
if ' ' in arg_string:
2305
return None
2306
2307
# it was meant to be an optional but there is no such option
2308
# in this parser (though it might be a valid option in a subparser)
2309
return None, arg_string, None
2310
2311
def _get_option_tuples(self, option_string):
2312
result = []
2313
2314
# option strings starting with two prefix characters are only
2315
# split at the '='
2316
chars = self.prefix_chars
2317
if option_string[0] in chars and option_string[1] in chars:
2318
if self.allow_abbrev:
2319
if '=' in option_string:
2320
option_prefix, explicit_arg = option_string.split('=', 1)
2321
else:
2322
option_prefix = option_string
2323
explicit_arg = None
2324
for option_string in self._option_string_actions:
2325
if option_string.startswith(option_prefix):
2326
action = self._option_string_actions[option_string]
2327
tup = action, option_string, explicit_arg
2328
result.append(tup)
2329
2330
# single character options can be concatenated with their arguments
2331
# but multiple character options always have to have their argument
2332
# separate
2333
elif option_string[0] in chars and option_string[1] not in chars:
2334
option_prefix = option_string
2335
explicit_arg = None
2336
short_option_prefix = option_string[:2]
2337
short_explicit_arg = option_string[2:]
2338
2339
for option_string in self._option_string_actions:
2340
if option_string == short_option_prefix:
2341
action = self._option_string_actions[option_string]
2342
tup = action, option_string, short_explicit_arg
2343
result.append(tup)
2344
elif option_string.startswith(option_prefix):
2345
action = self._option_string_actions[option_string]
2346
tup = action, option_string, explicit_arg
2347
result.append(tup)
2348
2349
# shouldn't ever get here
2350
else:
2351
self.error(_('unexpected option string: %s') % option_string)
2352
2353
# return the collected option tuples
2354
return result
2355
2356
def _get_nargs_pattern(self, action):
2357
# in all examples below, we have to allow for '--' args
2358
# which are represented as '-' in the pattern
2359
nargs = action.nargs
2360
2361
# the default (None) is assumed to be a single argument
2362
if nargs is None:
2363
nargs_pattern = '(-*A-*)'
2364
2365
# allow zero or one arguments
2366
elif nargs == OPTIONAL:
2367
nargs_pattern = '(-*A?-*)'
2368
2369
# allow zero or more arguments
2370
elif nargs == ZERO_OR_MORE:
2371
nargs_pattern = '(-*[A-]*)'
2372
2373
# allow one or more arguments
2374
elif nargs == ONE_OR_MORE:
2375
nargs_pattern = '(-*A[A-]*)'
2376
2377
# allow any number of options or arguments
2378
elif nargs == REMAINDER:
2379
nargs_pattern = '([-AO]*)'
2380
2381
# allow one argument followed by any number of options or arguments
2382
elif nargs == PARSER:
2383
nargs_pattern = '(-*A[-AO]*)'
2384
2385
# suppress action, like nargs=0
2386
elif nargs == SUPPRESS:
2387
nargs_pattern = '(-*-*)'
2388
2389
# all others should be integers
2390
else:
2391
nargs_pattern = '(-*%s-*)' % '-*'.join('A' * nargs)
2392
2393
# if this is an optional action, -- is not allowed
2394
if action.option_strings:
2395
nargs_pattern = nargs_pattern.replace('-*', '')
2396
nargs_pattern = nargs_pattern.replace('-', '')
2397
2398
# return the pattern
2399
return nargs_pattern
2400
2401
# ========================
2402
# Alt command line argument parsing, allowing free intermix
2403
# ========================
2404
2405
def parse_intermixed_args(self, args=None, namespace=None):
2406
args, argv = self.parse_known_intermixed_args(args, namespace)
2407
if argv:
2408
msg = _('unrecognized arguments: %s')
2409
self.error(msg % ' '.join(argv))
2410
return args
2411
2412
def parse_known_intermixed_args(self, args=None, namespace=None):
2413
# returns a namespace and list of extras
2414
#
2415
# positional can be freely intermixed with optionals. optionals are
2416
# first parsed with all positional arguments deactivated. The 'extras'
2417
# are then parsed. If the parser definition is incompatible with the
2418
# intermixed assumptions (e.g. use of REMAINDER, subparsers) a
2419
# TypeError is raised.
2420
#
2421
# positionals are 'deactivated' by setting nargs and default to
2422
# SUPPRESS. This blocks the addition of that positional to the
2423
# namespace
2424
2425
positionals = self._get_positional_actions()
2426
a = [action for action in positionals
2427
if action.nargs in [PARSER, REMAINDER]]
2428
if a:
2429
raise TypeError('parse_intermixed_args: positional arg'
2430
' with nargs=%s'%a[0].nargs)
2431
2432
if [action.dest for group in self._mutually_exclusive_groups
2433
for action in group._group_actions if action in positionals]:
2434
raise TypeError('parse_intermixed_args: positional in'
2435
' mutuallyExclusiveGroup')
2436
2437
try:
2438
save_usage = self.usage
2439
try:
2440
if self.usage is None:
2441
# capture the full usage for use in error messages
2442
self.usage = self.format_usage()[7:]
2443
for action in positionals:
2444
# deactivate positionals
2445
action.save_nargs = action.nargs
2446
# action.nargs = 0
2447
action.nargs = SUPPRESS
2448
action.save_default = action.default
2449
action.default = SUPPRESS
2450
namespace, remaining_args = self.parse_known_args(args,
2451
namespace)
2452
for action in positionals:
2453
# remove the empty positional values from namespace
2454
if (hasattr(namespace, action.dest)
2455
and getattr(namespace, action.dest)==[]):
2456
from warnings import warn
2457
warn('Do not expect %s in %s' % (action.dest, namespace))
2458
delattr(namespace, action.dest)
2459
finally:
2460
# restore nargs and usage before exiting
2461
for action in positionals:
2462
action.nargs = action.save_nargs
2463
action.default = action.save_default
2464
optionals = self._get_optional_actions()
2465
try:
2466
# parse positionals. optionals aren't normally required, but
2467
# they could be, so make sure they aren't.
2468
for action in optionals:
2469
action.save_required = action.required
2470
action.required = False
2471
for group in self._mutually_exclusive_groups:
2472
group.save_required = group.required
2473
group.required = False
2474
namespace, extras = self.parse_known_args(remaining_args,
2475
namespace)
2476
finally:
2477
# restore parser values before exiting
2478
for action in optionals:
2479
action.required = action.save_required
2480
for group in self._mutually_exclusive_groups:
2481
group.required = group.save_required
2482
finally:
2483
self.usage = save_usage
2484
return namespace, extras
2485
2486
# ========================
2487
# Value conversion methods
2488
# ========================
2489
def _get_values(self, action, arg_strings):
2490
# for everything but PARSER, REMAINDER args, strip out first '--'
2491
if action.nargs not in [PARSER, REMAINDER]:
2492
try:
2493
arg_strings.remove('--')
2494
except ValueError:
2495
pass
2496
2497
# optional argument produces a default when not present
2498
if not arg_strings and action.nargs == OPTIONAL:
2499
if action.option_strings:
2500
value = action.const
2501
else:
2502
value = action.default
2503
if isinstance(value, str):
2504
value = self._get_value(action, value)
2505
self._check_value(action, value)
2506
2507
# when nargs='*' on a positional, if there were no command-line
2508
# args, use the default if it is anything other than None
2509
elif (not arg_strings and action.nargs == ZERO_OR_MORE and
2510
not action.option_strings):
2511
if action.default is not None:
2512
value = action.default
2513
self._check_value(action, value)
2514
else:
2515
# since arg_strings is always [] at this point
2516
# there is no need to use self._check_value(action, value)
2517
value = arg_strings
2518
2519
# single argument or optional argument produces a single value
2520
elif len(arg_strings) == 1 and action.nargs in [None, OPTIONAL]:
2521
arg_string, = arg_strings
2522
value = self._get_value(action, arg_string)
2523
self._check_value(action, value)
2524
2525
# REMAINDER arguments convert all values, checking none
2526
elif action.nargs == REMAINDER:
2527
value = [self._get_value(action, v) for v in arg_strings]
2528
2529
# PARSER arguments convert all values, but check only the first
2530
elif action.nargs == PARSER:
2531
value = [self._get_value(action, v) for v in arg_strings]
2532
self._check_value(action, value[0])
2533
2534
# SUPPRESS argument does not put anything in the namespace
2535
elif action.nargs == SUPPRESS:
2536
value = SUPPRESS
2537
2538
# all other types of nargs produce a list
2539
else:
2540
value = [self._get_value(action, v) for v in arg_strings]
2541
for v in value:
2542
self._check_value(action, v)
2543
2544
# return the converted value
2545
return value
2546
2547
def _get_value(self, action, arg_string):
2548
type_func = self._registry_get('type', action.type, action.type)
2549
if not callable(type_func):
2550
msg = _('%r is not callable')
2551
raise ArgumentError(action, msg % type_func)
2552
2553
# convert the value to the appropriate type
2554
try:
2555
result = type_func(arg_string)
2556
2557
# ArgumentTypeErrors indicate errors
2558
except ArgumentTypeError as err:
2559
msg = str(err)
2560
raise ArgumentError(action, msg)
2561
2562
# TypeErrors or ValueErrors also indicate errors
2563
except (TypeError, ValueError):
2564
name = getattr(action.type, '__name__', repr(action.type))
2565
args = {'type': name, 'value': arg_string}
2566
msg = _('invalid %(type)s value: %(value)r')
2567
raise ArgumentError(action, msg % args)
2568
2569
# return the converted value
2570
return result
2571
2572
def _check_value(self, action, value):
2573
# converted value must be one of the choices (if specified)
2574
if action.choices is not None and value not in action.choices:
2575
args = {'value': value,
2576
'choices': ', '.join(map(repr, action.choices))}
2577
msg = _('invalid choice: %(value)r (choose from %(choices)s)')
2578
raise ArgumentError(action, msg % args)
2579
2580
# =======================
2581
# Help-formatting methods
2582
# =======================
2583
def format_usage(self):
2584
formatter = self._get_formatter()
2585
formatter.add_usage(self.usage, self._actions,
2586
self._mutually_exclusive_groups)
2587
return formatter.format_help()
2588
2589
def format_help(self):
2590
formatter = self._get_formatter()
2591
2592
# usage
2593
formatter.add_usage(self.usage, self._actions,
2594
self._mutually_exclusive_groups)
2595
2596
# description
2597
formatter.add_text(self.description)
2598
2599
# positionals, optionals and user-defined groups
2600
for action_group in self._action_groups:
2601
formatter.start_section(action_group.title)
2602
formatter.add_text(action_group.description)
2603
formatter.add_arguments(action_group._group_actions)
2604
formatter.end_section()
2605
2606
# epilog
2607
formatter.add_text(self.epilog)
2608
2609
# determine help from format above
2610
return formatter.format_help()
2611
2612
def _get_formatter(self):
2613
return self.formatter_class(prog=self.prog)
2614
2615
# =====================
2616
# Help-printing methods
2617
# =====================
2618
def print_usage(self, file=None):
2619
if file is None:
2620
file = _sys.stdout
2621
self._print_message(self.format_usage(), file)
2622
2623
def print_help(self, file=None):
2624
if file is None:
2625
file = _sys.stdout
2626
self._print_message(self.format_help(), file)
2627
2628
def _print_message(self, message, file=None):
2629
if message:
2630
file = file or _sys.stderr
2631
try:
2632
file.write(message)
2633
except (AttributeError, OSError):
2634
pass
2635
2636
# ===============
2637
# Exiting methods
2638
# ===============
2639
def exit(self, status=0, message=None):
2640
if message:
2641
self._print_message(message, _sys.stderr)
2642
_sys.exit(status)
2643
2644
def error(self, message):
2645
"""error(message: string)
2646
2647
Prints a usage message incorporating the message to stderr and
2648
exits.
2649
2650
If you override this in a subclass, it should not return -- it
2651
should either exit or raise an exception.
2652
"""
2653
self.print_usage(_sys.stderr)
2654
args = {'prog': self.prog, 'message': message}
2655
self.exit(2, _('%(prog)s: error: %(message)s\n') % args)
2656
2657