blob: 4285cbb284bb79c62624e2f5657c19ab856f60a7 [file] [log] [blame]
Martin v. Löwis09776b72002-08-04 17:22:59 +00001# -*- coding: iso-8859-1 -*-
Guido van Rossum4b8c6ea2000-02-04 15:39:30 +00002"""Parser for command line options.
Guido van Rossumc6360141990-10-13 19:23:40 +00003
Guido van Rossum6d060941998-11-17 04:16:37 +00004This module helps scripts to parse the command line arguments in
5sys.argv. It supports the same conventions as the Unix getopt()
6function (including the special meanings of arguments of the form `-'
7and `--'). Long options similar to those supported by GNU software
8may be used as well via an optional third argument. This module
Martin v. Löwis446a25f2002-06-06 10:58:36 +00009provides two functions and an exception:
Guido van Rossumc6360141990-10-13 19:23:40 +000010
Guido van Rossum6d060941998-11-17 04:16:37 +000011getopt() -- Parse command line options
Martin v. Löwis446a25f2002-06-06 10:58:36 +000012gnu_getopt() -- Like getopt(), but allow option and non-option arguments
Tim Petersc411dba2002-07-16 21:35:23 +000013to be intermixed.
Guido van Rossum80c33e51999-12-21 22:38:40 +000014GetoptError -- exception (class) raised with 'opt' attribute, which is the
15option involved with the exception.
Guido van Rossum6d060941998-11-17 04:16:37 +000016"""
Guido van Rossum1550ff71996-09-11 19:43:52 +000017
Guido van Rossum6d060941998-11-17 04:16:37 +000018# Long option support added by Lars Wirzenius <liw@iki.fi>.
Martin v. Löwis446a25f2002-06-06 10:58:36 +000019#
Fred Drakea395ced2000-02-25 16:14:08 +000020# Gerrit Holl <gerrit@nl.linux.org> moved the string-based exceptions
21# to class-based exceptions.
Martin v. Löwis446a25f2002-06-06 10:58:36 +000022#
23# Peter Åstrand <astrand@lysator.liu.se> added gnu_getopt().
24#
25# TODO for gnu_getopt():
26#
27# - GNU getopt_long_only mechanism
28# - allow the caller to specify ordering
29# - RETURN_IN_ORDER option
30# - GNU extension with '-' as first character of option string
31# - optional arguments, specified by double colons
32# - a option string with a W followed by semicolon should
33# treat "-W foo" as "--foo"
Fred Drakea395ced2000-02-25 16:14:08 +000034
Skip Montanaro96803b22002-06-07 03:26:43 +000035__all__ = ["GetoptError","error","getopt","gnu_getopt"]
Skip Montanaroeccd02a2001-01-20 23:34:12 +000036
Martin v. Löwis446a25f2002-06-06 10:58:36 +000037import os
38
Guido van Rossum80c33e51999-12-21 22:38:40 +000039class GetoptError(Exception):
40 opt = ''
41 msg = ''
Fred Drakee1fd5262001-01-08 15:39:32 +000042 def __init__(self, msg, opt):
43 self.msg = msg
44 self.opt = opt
45 Exception.__init__(self, msg, opt)
Guido van Rossum80c33e51999-12-21 22:38:40 +000046
47 def __str__(self):
48 return self.msg
49
50error = GetoptError # backward compatibility
Guido van Rossumc6360141990-10-13 19:23:40 +000051
Guido van Rossum2c349bb1996-09-09 15:48:24 +000052def getopt(args, shortopts, longopts = []):
Guido van Rossum6d060941998-11-17 04:16:37 +000053 """getopt(args, options[, long_options]) -> opts, args
54
55 Parses command line options and parameter list. args is the
56 argument list to be parsed, without the leading reference to the
57 running program. Typically, this means "sys.argv[1:]". shortopts
58 is the string of option letters that the script wants to
59 recognize, with options that require an argument followed by a
60 colon (i.e., the same format that Unix getopt() uses). If
61 specified, longopts is a list of strings with the names of the
62 long options which should be supported. The leading '--'
63 characters should not be included in the option name. Options
64 which require an argument should be followed by an equal sign
65 ('=').
66
67 The return value consists of two elements: the first is a list of
68 (option, value) pairs; the second is the list of program arguments
69 left after the option list was stripped (this is a trailing slice
70 of the first argument). Each option-and-value pair returned has
71 the option as its first element, prefixed with a hyphen (e.g.,
72 '-x'), and the option argument as its second element, or an empty
73 string if the option has no argument. The options occur in the
74 list in the same order in which they were found, thus allowing
75 multiple occurrences. Long and short options may be mixed.
76
77 """
78
79 opts = []
80 if type(longopts) == type(""):
81 longopts = [longopts]
82 else:
83 longopts = list(longopts)
Tim Petersdd699b62000-12-27 08:05:05 +000084 while args and args[0].startswith('-') and args[0] != '-':
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000085 if args[0] == '--':
86 args = args[1:]
87 break
Fred Drake1e7dfd32001-12-12 06:20:34 +000088 if args[0].startswith('--'):
Guido van Rossum6d060941998-11-17 04:16:37 +000089 opts, args = do_longs(opts, args[0][2:], longopts, args[1:])
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000090 else:
Guido van Rossum6d060941998-11-17 04:16:37 +000091 opts, args = do_shorts(opts, args[0][1:], shortopts, args[1:])
Guido van Rossumc6360141990-10-13 19:23:40 +000092
Guido van Rossum6d060941998-11-17 04:16:37 +000093 return opts, args
Guido van Rossum2c349bb1996-09-09 15:48:24 +000094
Martin v. Löwis446a25f2002-06-06 10:58:36 +000095def gnu_getopt(args, shortopts, longopts = []):
96 """getopt(args, options[, long_options]) -> opts, args
97
98 This function works like getopt(), except that GNU style scanning
99 mode is used by default. This means that option and non-option
100 arguments may be intermixed. The getopt() function stops
101 processing options as soon as a non-option argument is
102 encountered.
103
104 If the first character of the option string is `+', or if the
105 environment variable POSIXLY_CORRECT is set, then option
106 processing stops as soon as a non-option argument is encountered.
Tim Petersc411dba2002-07-16 21:35:23 +0000107
Martin v. Löwis446a25f2002-06-06 10:58:36 +0000108 """
109
110 opts = []
111 prog_args = []
Martin v. Löwis33b77de2002-06-06 18:14:50 +0000112 if isinstance(longopts, str):
Martin v. Löwis446a25f2002-06-06 10:58:36 +0000113 longopts = [longopts]
114 else:
115 longopts = list(longopts)
116
117 # Allow options after non-option arguments?
118 if shortopts.startswith('+'):
119 shortopts = shortopts[1:]
Martin v. Löwis33b77de2002-06-06 18:14:50 +0000120 all_options_first = True
Jack Jansenf03c6922002-07-26 11:34:49 +0000121 elif os.environ.get("POSIXLY_CORRECT"):
Martin v. Löwis33b77de2002-06-06 18:14:50 +0000122 all_options_first = True
Martin v. Löwis446a25f2002-06-06 10:58:36 +0000123 else:
Martin v. Löwis33b77de2002-06-06 18:14:50 +0000124 all_options_first = False
Martin v. Löwis446a25f2002-06-06 10:58:36 +0000125
126 while args:
127 if args[0] == '--':
128 prog_args += args[1:]
129 break
130
131 if args[0][:2] == '--':
132 opts, args = do_longs(opts, args[0][2:], longopts, args[1:])
133 elif args[0][:1] == '-':
134 opts, args = do_shorts(opts, args[0][1:], shortopts, args[1:])
135 else:
136 if all_options_first:
137 prog_args += args
138 break
139 else:
140 prog_args.append(args[0])
141 args = args[1:]
142
143 return opts, prog_args
144
Guido van Rossum6d060941998-11-17 04:16:37 +0000145def do_longs(opts, opt, longopts, args):
Guido van Rossum1550ff71996-09-11 19:43:52 +0000146 try:
Fred Drakea395ced2000-02-25 16:14:08 +0000147 i = opt.index('=')
Guido van Rossum1550ff71996-09-11 19:43:52 +0000148 except ValueError:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000149 optarg = None
Tim Petersdd699b62000-12-27 08:05:05 +0000150 else:
151 opt, optarg = opt[:i], opt[i+1:]
Guido van Rossum2c349bb1996-09-09 15:48:24 +0000152
Guido van Rossum1550ff71996-09-11 19:43:52 +0000153 has_arg, opt = long_has_args(opt, longopts)
154 if has_arg:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000155 if optarg is None:
156 if not args:
Guido van Rossum80c33e51999-12-21 22:38:40 +0000157 raise GetoptError('option --%s requires argument' % opt, opt)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000158 optarg, args = args[0], args[1:]
Guido van Rossum1550ff71996-09-11 19:43:52 +0000159 elif optarg:
Guido van Rossum80c33e51999-12-21 22:38:40 +0000160 raise GetoptError('option --%s must not have an argument' % opt, opt)
Guido van Rossum6d060941998-11-17 04:16:37 +0000161 opts.append(('--' + opt, optarg or ''))
162 return opts, args
Guido van Rossum2c349bb1996-09-09 15:48:24 +0000163
164# Return:
165# has_arg?
166# full option name
167def long_has_args(opt, longopts):
Tim Petersd31b6322000-12-29 02:17:56 +0000168 possibilities = [o for o in longopts if o.startswith(opt)]
169 if not possibilities:
Tim Petersdd699b62000-12-27 08:05:05 +0000170 raise GetoptError('option --%s not recognized' % opt, opt)
Tim Petersdd699b62000-12-27 08:05:05 +0000171 # Is there an exact match?
172 if opt in possibilities:
Tim Petersbc0e9102002-04-04 22:55:58 +0000173 return False, opt
Tim Petersdd699b62000-12-27 08:05:05 +0000174 elif opt + '=' in possibilities:
Tim Petersbc0e9102002-04-04 22:55:58 +0000175 return True, opt
Tim Petersdd699b62000-12-27 08:05:05 +0000176 # No exact match, so better be unique.
177 if len(possibilities) > 1:
178 # XXX since possibilities contains all valid continuations, might be
179 # nice to work them into the error msg
180 raise GetoptError('option --%s not a unique prefix' % opt, opt)
181 assert len(possibilities) == 1
182 unique_match = possibilities[0]
183 has_arg = unique_match.endswith('=')
184 if has_arg:
185 unique_match = unique_match[:-1]
186 return has_arg, unique_match
Guido van Rossum2c349bb1996-09-09 15:48:24 +0000187
Guido van Rossum6d060941998-11-17 04:16:37 +0000188def do_shorts(opts, optstring, shortopts, args):
Guido van Rossum1550ff71996-09-11 19:43:52 +0000189 while optstring != '':
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000190 opt, optstring = optstring[0], optstring[1:]
191 if short_has_arg(opt, shortopts):
192 if optstring == '':
193 if not args:
Fred Drake1e7dfd32001-12-12 06:20:34 +0000194 raise GetoptError('option -%s requires argument' % opt,
195 opt)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000196 optstring, args = args[0], args[1:]
197 optarg, optstring = optstring, ''
198 else:
199 optarg = ''
Guido van Rossum6d060941998-11-17 04:16:37 +0000200 opts.append(('-' + opt, optarg))
201 return opts, args
Guido van Rossum2c349bb1996-09-09 15:48:24 +0000202
203def short_has_arg(opt, shortopts):
Guido van Rossum1550ff71996-09-11 19:43:52 +0000204 for i in range(len(shortopts)):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000205 if opt == shortopts[i] != ':':
Fred Drake1e7dfd32001-12-12 06:20:34 +0000206 return shortopts.startswith(':', i+1)
Guido van Rossum80c33e51999-12-21 22:38:40 +0000207 raise GetoptError('option -%s not recognized' % opt, opt)
Guido van Rossum2c349bb1996-09-09 15:48:24 +0000208
209if __name__ == '__main__':
Guido van Rossum1550ff71996-09-11 19:43:52 +0000210 import sys
211 print getopt(sys.argv[1:], "a:b", ["alpha=", "beta"])