1 class CommandParser(ArgumentParser):
2 """
3 Customized ArgumentParser class to improve some error messages and prevent
4 SystemExit in several occasions, as SystemExit is unacceptable when a
5 command is called programmatically.
6 """
7 def __init__(self, cmd, **kwargs):
8 self.cmd = cmd
9 super(CommandParser, self).__init__(**kwargs)
10
11 def parse_args(self, args=None, namespace=None):
12 # Catch missing argument for a better error message
13 if (hasattr(self.cmd, 'missing_args_message') and
14 not (args or any(not arg.startswith('-') for arg in args))):
15 self.error(self.cmd.missing_args_message)
16 return super(CommandParser, self).parse_args(args, namespace)
17
18 class ArgumentParser(_AttributeHolder, _ActionsContainer):
19 """Object for parsing command line strings into Python objects.
20
21 Keyword Arguments:
22 - prog -- The name of the program (default: sys.argv[0])
23 - usage -- A usage message (default: auto-generated from arguments)
24 - description -- A description of what the program does
25 - epilog -- Text following the argument descriptions
26 - parents -- Parsers whose arguments should be copied into this one
27 - formatter_class -- HelpFormatter class for printing help messages
28 - prefix_chars -- Characters that prefix optional arguments
29 - fromfile_prefix_chars -- Characters that prefix files containing
30 additional arguments
31 - argument_default -- The default value for all arguments
32 - conflict_handler -- String indicating how to handle conflicts
33 - add_help -- Add a -h/-help option
34 - allow_abbrev -- Allow long options to be abbreviated unambiguously
35 """
36
37 def __init__(self,
38 prog=None,
39 usage=None,
40 description=None,
41 epilog=None,
42 parents=[],
43 formatter_class=HelpFormatter,
44 prefix_chars='-',
45 fromfile_prefix_chars=None,
46 argument_default=None,
47 conflict_handler='error',
48 add_help=True,
49 allow_abbrev=True):
50
51 superinit = super(ArgumentParser, self).__init__
52 superinit(description=description,
53 prefix_chars=prefix_chars,
54 argument_default=argument_default,
55 conflict_handler=conflict_handler)
56
57
58 # default setting for prog
59 if prog is None:
60 prog = _os.path.basename(_sys.argv[0])
61
62 self.prog = prog
63 self.usage = usage
64 self.epilog = epilog
65 self.formatter_class = formatter_class
66 self.fromfile_prefix_chars = fromfile_prefix_chars
67 self.add_help = add_help
68 self.allow_abbrev = allow_abbrev
69
70 add_group = self.add_argument_group
71 self._positionals = add_group(_('positional arguments'))
72 self._optionals = add_group(_('optional arguments'))
73 self._subparsers = None
74
75 # register types
76 def identity(string):
77 return string
78 self.register('type', None, identity)
79
80 # add help argument if necessary
81 # (using explicit default to override global argument_default) 显式覆盖全局
82 default_prefix = '-' if '-' in prefix_chars else prefix_chars[0]
83 if self.add_help:
84 self.add_argument(
85 default_prefix+'h', default_prefix*2+'help',
86 action='help', default=SUPPRESS,
87 help=_('show this help message and exit'))
88
89 # add parent arguments and defaults
90 for parent in parents:
91 self._add_container_actions(parent)
92 try:
93 defaults = parent._defaults
94 except AttributeError:
95 pass
96 else:
97 self._defaults.update(defaults)
98
99 def parse_args(self, args=None, namespace=None):
100 args, argv = self.parse_known_args(args, namespace)
101 if argv:
102 msg = _('unrecognized arguments: %s')
103 self.error(msg % ' '.join(argv))
104 return args