1 # -*- coding: iso-8859-1 -*-
\r
2 """Parser for command line options.
\r
4 This module helps scripts to parse the command line arguments in
\r
5 sys.argv. It supports the same conventions as the Unix getopt()
\r
6 function (including the special meanings of arguments of the form `-'
\r
7 and `--'). Long options similar to those supported by GNU software
\r
8 may be used as well via an optional third argument. This module
\r
9 provides two functions and an exception:
\r
11 getopt() -- Parse command line options
\r
12 gnu_getopt() -- Like getopt(), but allow option and non-option arguments
\r
14 GetoptError -- exception (class) raised with 'opt' attribute, which is the
\r
15 option involved with the exception.
\r
18 # Long option support added by Lars Wirzenius <liw@iki.fi>.
\r
20 # Gerrit Holl <gerrit@nl.linux.org> moved the string-based exceptions
\r
21 # to class-based exceptions.
\r
23 # Peter Åstrand <astrand@lysator.liu.se> added gnu_getopt().
\r
25 # TODO for gnu_getopt():
\r
27 # - GNU getopt_long_only mechanism
\r
28 # - allow the caller to specify ordering
\r
29 # - RETURN_IN_ORDER option
\r
30 # - GNU extension with '-' as first character of option string
\r
31 # - optional arguments, specified by double colons
\r
32 # - a option string with a W followed by semicolon should
\r
33 # treat "-W foo" as "--foo"
\r
35 __all__ = ["GetoptError","error","getopt","gnu_getopt"]
\r
39 class GetoptError(Exception):
\r
42 def __init__(self, msg, opt=''):
\r
45 Exception.__init__(self, msg, opt)
\r
50 error = GetoptError # backward compatibility
\r
52 def getopt(args, shortopts, longopts = []):
\r
53 """getopt(args, options[, long_options]) -> opts, args
\r
55 Parses command line options and parameter list. args is the
\r
56 argument list to be parsed, without the leading reference to the
\r
57 running program. Typically, this means "sys.argv[1:]". shortopts
\r
58 is the string of option letters that the script wants to
\r
59 recognize, with options that require an argument followed by a
\r
60 colon (i.e., the same format that Unix getopt() uses). If
\r
61 specified, longopts is a list of strings with the names of the
\r
62 long options which should be supported. The leading '--'
\r
63 characters should not be included in the option name. Options
\r
64 which require an argument should be followed by an equal sign
\r
67 The return value consists of two elements: the first is a list of
\r
68 (option, value) pairs; the second is the list of program arguments
\r
69 left after the option list was stripped (this is a trailing slice
\r
70 of the first argument). Each option-and-value pair returned has
\r
71 the option as its first element, prefixed with a hyphen (e.g.,
\r
72 '-x'), and the option argument as its second element, or an empty
\r
73 string if the option has no argument. The options occur in the
\r
74 list in the same order in which they were found, thus allowing
\r
75 multiple occurrences. Long and short options may be mixed.
\r
80 if type(longopts) == type(""):
\r
81 longopts = [longopts]
\r
83 longopts = list(longopts)
\r
84 while args and args[0].startswith('-') and args[0] != '-':
\r
88 if args[0].startswith('--'):
\r
89 opts, args = do_longs(opts, args[0][2:], longopts, args[1:])
\r
91 opts, args = do_shorts(opts, args[0][1:], shortopts, args[1:])
\r
95 def gnu_getopt(args, shortopts, longopts = []):
\r
96 """getopt(args, options[, long_options]) -> opts, args
\r
98 This function works like getopt(), except that GNU style scanning
\r
99 mode is used by default. This means that option and non-option
\r
100 arguments may be intermixed. The getopt() function stops
\r
101 processing options as soon as a non-option argument is
\r
104 If the first character of the option string is `+', or if the
\r
105 environment variable POSIXLY_CORRECT is set, then option
\r
106 processing stops as soon as a non-option argument is encountered.
\r
112 if isinstance(longopts, str):
\r
113 longopts = [longopts]
\r
115 longopts = list(longopts)
\r
117 # Allow options after non-option arguments?
\r
118 if shortopts.startswith('+'):
\r
119 shortopts = shortopts[1:]
\r
120 all_options_first = True
\r
121 elif os.environ.get("POSIXLY_CORRECT"):
\r
122 all_options_first = True
\r
124 all_options_first = False
\r
127 if args[0] == '--':
\r
128 prog_args += args[1:]
\r
131 if args[0][:2] == '--':
\r
132 opts, args = do_longs(opts, args[0][2:], longopts, args[1:])
\r
133 elif args[0][:1] == '-':
\r
134 opts, args = do_shorts(opts, args[0][1:], shortopts, args[1:])
\r
136 if all_options_first:
\r
140 prog_args.append(args[0])
\r
143 return opts, prog_args
\r
145 def do_longs(opts, opt, longopts, args):
\r
151 opt, optarg = opt[:i], opt[i+1:]
\r
153 has_arg, opt = long_has_args(opt, longopts)
\r
157 raise GetoptError('option --%s requires argument' % opt, opt)
\r
158 optarg, args = args[0], args[1:]
\r
160 raise GetoptError('option --%s must not have an argument' % opt, opt)
\r
161 opts.append(('--' + opt, optarg or ''))
\r
167 def long_has_args(opt, longopts):
\r
168 possibilities = [o for o in longopts if o.startswith(opt)]
\r
169 if not possibilities:
\r
170 raise GetoptError('option --%s not recognized' % opt, opt)
\r
171 # Is there an exact match?
\r
172 if opt in possibilities:
\r
174 elif opt + '=' in possibilities:
\r
176 # No exact match, so better be unique.
\r
177 if len(possibilities) > 1:
\r
178 # XXX since possibilities contains all valid continuations, might be
\r
179 # nice to work them into the error msg
\r
180 raise GetoptError('option --%s not a unique prefix' % opt, opt)
\r
181 assert len(possibilities) == 1
\r
182 unique_match = possibilities[0]
\r
183 has_arg = unique_match.endswith('=')
\r
185 unique_match = unique_match[:-1]
\r
186 return has_arg, unique_match
\r
188 def do_shorts(opts, optstring, shortopts, args):
\r
189 while optstring != '':
\r
190 opt, optstring = optstring[0], optstring[1:]
\r
191 if short_has_arg(opt, shortopts):
\r
192 if optstring == '':
\r
194 raise GetoptError('option -%s requires argument' % opt,
\r
196 optstring, args = args[0], args[1:]
\r
197 optarg, optstring = optstring, ''
\r
200 opts.append(('-' + opt, optarg))
\r
203 def short_has_arg(opt, shortopts):
\r
204 for i in range(len(shortopts)):
\r
205 if opt == shortopts[i] != ':':
\r
206 return shortopts.startswith(':', i+1)
\r
207 raise GetoptError('option -%s not recognized' % opt, opt)
\r
209 if __name__ == '__main__':
\r
211 print getopt(sys.argv[1:], "a:b", ["alpha=", "beta"])
\r