blob: 3d6ecbddb99cd752ed027c589ee79db0527201bf [file] [log] [blame]
Guido van Rossum4b8c6ea2000-02-04 15:39:30 +00001"""Parser for command line options.
Guido van Rossumc6360141990-10-13 19:23:40 +00002
Guido van Rossum6d060941998-11-17 04:16:37 +00003This module helps scripts to parse the command line arguments in
4sys.argv. It supports the same conventions as the Unix getopt()
5function (including the special meanings of arguments of the form `-'
6and `--'). Long options similar to those supported by GNU software
7may be used as well via an optional third argument. This module
Martin v. Löwis446a25f2002-06-06 10:58:36 +00008provides two functions and an exception:
Guido van Rossumc6360141990-10-13 19:23:40 +00009
Guido van Rossum6d060941998-11-17 04:16:37 +000010getopt() -- Parse command line options
Martin v. Löwis446a25f2002-06-06 10:58:36 +000011gnu_getopt() -- Like getopt(), but allow option and non-option arguments
Tim Petersc411dba2002-07-16 21:35:23 +000012to be intermixed.
Guido van Rossum80c33e51999-12-21 22:38:40 +000013GetoptError -- exception (class) raised with 'opt' attribute, which is the
14option involved with the exception.
Guido van Rossum6d060941998-11-17 04:16:37 +000015"""
Guido van Rossum1550ff71996-09-11 19:43:52 +000016
Guido van Rossum6d060941998-11-17 04:16:37 +000017# Long option support added by Lars Wirzenius <liw@iki.fi>.
Martin v. Löwis446a25f2002-06-06 10:58:36 +000018#
Fred Drakea395ced2000-02-25 16:14:08 +000019# Gerrit Holl <gerrit@nl.linux.org> moved the string-based exceptions
20# to class-based exceptions.
Martin v. Löwis446a25f2002-06-06 10:58:36 +000021#
Éric Araujoeda55832011-03-21 00:09:07 +010022# Peter Åstrand <astrand@lysator.liu.se> added gnu_getopt().
Martin v. Löwis446a25f2002-06-06 10:58:36 +000023#
24# TODO for gnu_getopt():
25#
26# - GNU getopt_long_only mechanism
27# - allow the caller to specify ordering
28# - RETURN_IN_ORDER option
29# - GNU extension with '-' as first character of option string
30# - optional arguments, specified by double colons
31# - a option string with a W followed by semicolon should
32# treat "-W foo" as "--foo"
Fred Drakea395ced2000-02-25 16:14:08 +000033
Skip Montanaro96803b22002-06-07 03:26:43 +000034__all__ = ["GetoptError","error","getopt","gnu_getopt"]
Skip Montanaroeccd02a2001-01-20 23:34:12 +000035
Martin v. Löwis446a25f2002-06-06 10:58:36 +000036import os
Antoine Pitrou0fd59ac2011-03-21 16:04:06 +010037try:
38 from gettext import gettext as _
39except ImportError:
40 # Bootstrapping Python: gettext's dependencies not built yet
41 def _(s): return s
Martin v. Löwis446a25f2002-06-06 10:58:36 +000042
Guido van Rossum80c33e51999-12-21 22:38:40 +000043class GetoptError(Exception):
44 opt = ''
45 msg = ''
Andrew M. Kuchling01892662003-02-06 19:52:56 +000046 def __init__(self, msg, opt=''):
Fred Drakee1fd5262001-01-08 15:39:32 +000047 self.msg = msg
48 self.opt = opt
49 Exception.__init__(self, msg, opt)
Guido van Rossum80c33e51999-12-21 22:38:40 +000050
51 def __str__(self):
52 return self.msg
53
54error = GetoptError # backward compatibility
Guido van Rossumc6360141990-10-13 19:23:40 +000055
Guido van Rossum2c349bb1996-09-09 15:48:24 +000056def getopt(args, shortopts, longopts = []):
Guido van Rossum6d060941998-11-17 04:16:37 +000057 """getopt(args, options[, long_options]) -> opts, args
58
59 Parses command line options and parameter list. args is the
60 argument list to be parsed, without the leading reference to the
61 running program. Typically, this means "sys.argv[1:]". shortopts
62 is the string of option letters that the script wants to
63 recognize, with options that require an argument followed by a
64 colon (i.e., the same format that Unix getopt() uses). If
65 specified, longopts is a list of strings with the names of the
66 long options which should be supported. The leading '--'
67 characters should not be included in the option name. Options
68 which require an argument should be followed by an equal sign
69 ('=').
70
71 The return value consists of two elements: the first is a list of
72 (option, value) pairs; the second is the list of program arguments
73 left after the option list was stripped (this is a trailing slice
74 of the first argument). Each option-and-value pair returned has
75 the option as its first element, prefixed with a hyphen (e.g.,
76 '-x'), and the option argument as its second element, or an empty
77 string if the option has no argument. The options occur in the
78 list in the same order in which they were found, thus allowing
79 multiple occurrences. Long and short options may be mixed.
80
81 """
82
83 opts = []
84 if type(longopts) == type(""):
85 longopts = [longopts]
86 else:
87 longopts = list(longopts)
Tim Petersdd699b62000-12-27 08:05:05 +000088 while args and args[0].startswith('-') and args[0] != '-':
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000089 if args[0] == '--':
90 args = args[1:]
91 break
Fred Drake1e7dfd32001-12-12 06:20:34 +000092 if args[0].startswith('--'):
Guido van Rossum6d060941998-11-17 04:16:37 +000093 opts, args = do_longs(opts, args[0][2:], longopts, args[1:])
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000094 else:
Guido van Rossum6d060941998-11-17 04:16:37 +000095 opts, args = do_shorts(opts, args[0][1:], shortopts, args[1:])
Guido van Rossumc6360141990-10-13 19:23:40 +000096
Guido van Rossum6d060941998-11-17 04:16:37 +000097 return opts, args
Guido van Rossum2c349bb1996-09-09 15:48:24 +000098
Martin v. Löwis446a25f2002-06-06 10:58:36 +000099def gnu_getopt(args, shortopts, longopts = []):
100 """getopt(args, options[, long_options]) -> opts, args
101
102 This function works like getopt(), except that GNU style scanning
103 mode is used by default. This means that option and non-option
104 arguments may be intermixed. The getopt() function stops
105 processing options as soon as a non-option argument is
106 encountered.
107
108 If the first character of the option string is `+', or if the
109 environment variable POSIXLY_CORRECT is set, then option
110 processing stops as soon as a non-option argument is encountered.
Tim Petersc411dba2002-07-16 21:35:23 +0000111
Martin v. Löwis446a25f2002-06-06 10:58:36 +0000112 """
113
114 opts = []
115 prog_args = []
Martin v. Löwis33b77de2002-06-06 18:14:50 +0000116 if isinstance(longopts, str):
Martin v. Löwis446a25f2002-06-06 10:58:36 +0000117 longopts = [longopts]
118 else:
119 longopts = list(longopts)
120
121 # Allow options after non-option arguments?
122 if shortopts.startswith('+'):
123 shortopts = shortopts[1:]
Martin v. Löwis33b77de2002-06-06 18:14:50 +0000124 all_options_first = True
Jack Jansenf03c6922002-07-26 11:34:49 +0000125 elif os.environ.get("POSIXLY_CORRECT"):
Martin v. Löwis33b77de2002-06-06 18:14:50 +0000126 all_options_first = True
Martin v. Löwis446a25f2002-06-06 10:58:36 +0000127 else:
Martin v. Löwis33b77de2002-06-06 18:14:50 +0000128 all_options_first = False
Martin v. Löwis446a25f2002-06-06 10:58:36 +0000129
130 while args:
131 if args[0] == '--':
132 prog_args += args[1:]
133 break
134
135 if args[0][:2] == '--':
136 opts, args = do_longs(opts, args[0][2:], longopts, args[1:])
Georg Brandleee31162008-12-07 15:15:22 +0000137 elif args[0][:1] == '-' and args[0] != '-':
Martin v. Löwis446a25f2002-06-06 10:58:36 +0000138 opts, args = do_shorts(opts, args[0][1:], shortopts, args[1:])
139 else:
140 if all_options_first:
141 prog_args += args
142 break
143 else:
144 prog_args.append(args[0])
145 args = args[1:]
146
147 return opts, prog_args
148
Guido van Rossum6d060941998-11-17 04:16:37 +0000149def do_longs(opts, opt, longopts, args):
Guido van Rossum1550ff71996-09-11 19:43:52 +0000150 try:
Fred Drakea395ced2000-02-25 16:14:08 +0000151 i = opt.index('=')
Guido van Rossum1550ff71996-09-11 19:43:52 +0000152 except ValueError:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000153 optarg = None
Tim Petersdd699b62000-12-27 08:05:05 +0000154 else:
155 opt, optarg = opt[:i], opt[i+1:]
Guido van Rossum2c349bb1996-09-09 15:48:24 +0000156
Guido van Rossum1550ff71996-09-11 19:43:52 +0000157 has_arg, opt = long_has_args(opt, longopts)
158 if has_arg:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000159 if optarg is None:
160 if not args:
Éric Araujoeda55832011-03-21 00:09:07 +0100161 raise GetoptError(_('option --%s requires argument') % opt, opt)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000162 optarg, args = args[0], args[1:]
Victor Stinnereccc5fa2010-07-24 00:49:20 +0000163 elif optarg is not None:
Éric Araujoeda55832011-03-21 00:09:07 +0100164 raise GetoptError(_('option --%s must not have an argument') % opt, opt)
Guido van Rossum6d060941998-11-17 04:16:37 +0000165 opts.append(('--' + opt, optarg or ''))
166 return opts, args
Guido van Rossum2c349bb1996-09-09 15:48:24 +0000167
168# Return:
169# has_arg?
170# full option name
171def long_has_args(opt, longopts):
Tim Petersd31b6322000-12-29 02:17:56 +0000172 possibilities = [o for o in longopts if o.startswith(opt)]
173 if not possibilities:
Éric Araujoeda55832011-03-21 00:09:07 +0100174 raise GetoptError(_('option --%s not recognized') % opt, opt)
Tim Petersdd699b62000-12-27 08:05:05 +0000175 # Is there an exact match?
176 if opt in possibilities:
Tim Petersbc0e9102002-04-04 22:55:58 +0000177 return False, opt
Tim Petersdd699b62000-12-27 08:05:05 +0000178 elif opt + '=' in possibilities:
Tim Petersbc0e9102002-04-04 22:55:58 +0000179 return True, opt
Tim Petersdd699b62000-12-27 08:05:05 +0000180 # No exact match, so better be unique.
181 if len(possibilities) > 1:
182 # XXX since possibilities contains all valid continuations, might be
183 # nice to work them into the error msg
Éric Araujoeda55832011-03-21 00:09:07 +0100184 raise GetoptError(_('option --%s not a unique prefix') % opt, opt)
Tim Petersdd699b62000-12-27 08:05:05 +0000185 assert len(possibilities) == 1
186 unique_match = possibilities[0]
187 has_arg = unique_match.endswith('=')
188 if has_arg:
189 unique_match = unique_match[:-1]
190 return has_arg, unique_match
Guido van Rossum2c349bb1996-09-09 15:48:24 +0000191
Guido van Rossum6d060941998-11-17 04:16:37 +0000192def do_shorts(opts, optstring, shortopts, args):
Guido van Rossum1550ff71996-09-11 19:43:52 +0000193 while optstring != '':
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000194 opt, optstring = optstring[0], optstring[1:]
195 if short_has_arg(opt, shortopts):
196 if optstring == '':
197 if not args:
Éric Araujoeda55832011-03-21 00:09:07 +0100198 raise GetoptError(_('option -%s requires argument') % opt,
Fred Drake1e7dfd32001-12-12 06:20:34 +0000199 opt)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000200 optstring, args = args[0], args[1:]
201 optarg, optstring = optstring, ''
202 else:
203 optarg = ''
Guido van Rossum6d060941998-11-17 04:16:37 +0000204 opts.append(('-' + opt, optarg))
205 return opts, args
Guido van Rossum2c349bb1996-09-09 15:48:24 +0000206
207def short_has_arg(opt, shortopts):
Guido van Rossum1550ff71996-09-11 19:43:52 +0000208 for i in range(len(shortopts)):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000209 if opt == shortopts[i] != ':':
Fred Drake1e7dfd32001-12-12 06:20:34 +0000210 return shortopts.startswith(':', i+1)
Éric Araujoeda55832011-03-21 00:09:07 +0100211 raise GetoptError(_('option -%s not recognized') % opt, opt)
Guido van Rossum2c349bb1996-09-09 15:48:24 +0000212
213if __name__ == '__main__':
Guido van Rossum1550ff71996-09-11 19:43:52 +0000214 import sys
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000215 print(getopt(sys.argv[1:], "a:b", ["alpha=", "beta"]))