PageRenderTime 172ms CodeModel.GetById 160ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 0ms

/Lib/getopt.py

http://unladen-swallow.googlecode.com/
Python | 211 lines | 195 code | 1 blank | 15 comment | 7 complexity | 499c95136209dcdfa5a26e9ef0429ad0 MD5 | raw file
  1# -*- coding: iso-8859-1 -*-
  2"""Parser for command line options.
  3
  4This 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
  9provides two functions and an exception:
 10
 11getopt() -- Parse command line options
 12gnu_getopt() -- Like getopt(), but allow option and non-option arguments
 13to be intermixed.
 14GetoptError -- exception (class) raised with 'opt' attribute, which is the
 15option involved with the exception.
 16"""
 17
 18# Long option support added by Lars Wirzenius <liw@iki.fi>.
 19#
 20# Gerrit Holl <gerrit@nl.linux.org> moved the string-based exceptions
 21# to class-based exceptions.
 22#
 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"
 34
 35__all__ = ["GetoptError","error","getopt","gnu_getopt"]
 36
 37import os
 38
 39class GetoptError(Exception):
 40    opt = ''
 41    msg = ''
 42    def __init__(self, msg, opt=''):
 43        self.msg = msg
 44        self.opt = opt
 45        Exception.__init__(self, msg, opt)
 46
 47    def __str__(self):
 48        return self.msg
 49
 50error = GetoptError # backward compatibility
 51
 52def getopt(args, shortopts, longopts = []):
 53    """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)
 84    while args and args[0].startswith('-') and args[0] != '-':
 85        if args[0] == '--':
 86            args = args[1:]
 87            break
 88        if args[0].startswith('--'):
 89            opts, args = do_longs(opts, args[0][2:], longopts, args[1:])
 90        else:
 91            opts, args = do_shorts(opts, args[0][1:], shortopts, args[1:])
 92
 93    return opts, args
 94
 95def 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.
107
108    """
109
110    opts = []
111    prog_args = []
112    if isinstance(longopts, str):
113        longopts = [longopts]
114    else:
115        longopts = list(longopts)
116
117    # Allow options after non-option arguments?
118    if shortopts.startswith('+'):
119        shortopts = shortopts[1:]
120        all_options_first = True
121    elif os.environ.get("POSIXLY_CORRECT"):
122        all_options_first = True
123    else:
124        all_options_first = False
125
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
145def do_longs(opts, opt, longopts, args):
146    try:
147        i = opt.index('=')
148    except ValueError:
149        optarg = None
150    else:
151        opt, optarg = opt[:i], opt[i+1:]
152
153    has_arg, opt = long_has_args(opt, longopts)
154    if has_arg:
155        if optarg is None:
156            if not args:
157                raise GetoptError('option --%s requires argument' % opt, opt)
158            optarg, args = args[0], args[1:]
159    elif optarg:
160        raise GetoptError('option --%s must not have an argument' % opt, opt)
161    opts.append(('--' + opt, optarg or ''))
162    return opts, args
163
164# Return:
165#   has_arg?
166#   full option name
167def long_has_args(opt, longopts):
168    possibilities = [o for o in longopts if o.startswith(opt)]
169    if not possibilities:
170        raise GetoptError('option --%s not recognized' % opt, opt)
171    # Is there an exact match?
172    if opt in possibilities:
173        return False, opt
174    elif opt + '=' in possibilities:
175        return True, opt
176    # 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
187
188def do_shorts(opts, optstring, shortopts, args):
189    while optstring != '':
190        opt, optstring = optstring[0], optstring[1:]
191        if short_has_arg(opt, shortopts):
192            if optstring == '':
193                if not args:
194                    raise GetoptError('option -%s requires argument' % opt,
195                                      opt)
196                optstring, args = args[0], args[1:]
197            optarg, optstring = optstring, ''
198        else:
199            optarg = ''
200        opts.append(('-' + opt, optarg))
201    return opts, args
202
203def short_has_arg(opt, shortopts):
204    for i in range(len(shortopts)):
205        if opt == shortopts[i] != ':':
206            return shortopts.startswith(':', i+1)
207    raise GetoptError('option -%s not recognized' % opt, opt)
208
209if __name__ == '__main__':
210    import sys
211    print getopt(sys.argv[1:], "a:b", ["alpha=", "beta"])