| """distutils.fancy_getopt | 
 |  | 
 | Wrapper around the standard getopt module that provides the following | 
 | additional features: | 
 |   * short and long options are tied together | 
 |   * options have help strings, so fancy_getopt could potentially | 
 |     create a complete usage summary | 
 |   * options set attributes of a passed-in object | 
 | """ | 
 |  | 
 | # created 1999/03/03, Greg Ward | 
 |  | 
 | __rcsid__ = "$Id$" | 
 |  | 
 | import string, re | 
 | from types import * | 
 | import getopt | 
 | from distutils.errors import * | 
 |  | 
 | # Much like command_re in distutils.core, this is close to but not quite | 
 | # the same as a Python NAME -- except, in the spirit of most GNU | 
 | # utilities, we use '-' in place of '_'.  (The spirit of LISP lives on!) | 
 | # The similarities to NAME are again not a coincidence... | 
 | longopt_re = re.compile (r'^[a-zA-Z]([a-zA-Z0-9-]*)$') | 
 |  | 
 | # This is used to translate long options to legitimate Python identifiers | 
 | # (for use as attributes of some object). | 
 | longopt_xlate = string.maketrans ('-', '_') | 
 |  | 
 |  | 
 | def fancy_getopt (options, object, args): | 
 |  | 
 |     # The 'options' table is a list of 3-tuples: | 
 |     #   (long_option, short_option, help_string) | 
 |     # if an option takes an argument, its long_option should have '=' | 
 |     # appended; short_option should just be a single character, no ':' in | 
 |     # any case.  If a long_option doesn't have a corresponding | 
 |     # short_option, short_option should be None.  All option tuples must | 
 |     # have long options. | 
 |  | 
 |     # Build the short_opts string and long_opts list, remembering how | 
 |     # the two are tied together | 
 |  | 
 |     short_opts = []                     # we'll join 'em when done | 
 |     long_opts = [] | 
 |     short2long = {} | 
 |     attr_name = {} | 
 |     takes_arg = {} | 
 |  | 
 |     for (long, short, help) in options: | 
 |         # Type-check the option names | 
 |         if type (long) is not StringType or len (long) < 2: | 
 |             raise DistutilsGetoptError, \ | 
 |                   "long option must be a string of length >= 2" | 
 |  | 
 |         if (not ((short is None) or | 
 |                  (type (short) is StringType and len (short) == 1))): | 
 |             raise DistutilsGetoptError, \ | 
 |                   "short option must be None or string of length 1" | 
 |  | 
 |         long_opts.append (long) | 
 |  | 
 |         if long[-1] == '=':             # option takes an argument? | 
 |             if short: short = short + ':' | 
 |             long = long[0:-1] | 
 |             takes_arg[long] = 1 | 
 |         else: | 
 |             takes_arg[long] = 0 | 
 |  | 
 |         # Now enforce some bondage on the long option name, so we can later | 
 |         # translate it to an attribute name in 'object'.  Have to do this a | 
 |         # bit late to make sure we've removed any trailing '='. | 
 |         if not longopt_re.match (long): | 
 |             raise DistutilsGetoptError, \ | 
 |                   ("invalid long option name '%s' " + | 
 |                    "(must be letters, numbers, hyphens only") % long | 
 |  | 
 |         attr_name[long] = string.translate (long, longopt_xlate) | 
 |         if short: | 
 |             short_opts.append (short) | 
 |             short2long[short[0]] = long | 
 |  | 
 |     # end loop over 'options' | 
 |  | 
 |     short_opts = string.join (short_opts) | 
 |     try: | 
 |         (opts, args) = getopt.getopt (args, short_opts, long_opts) | 
 |     except getopt.error, msg: | 
 |         raise DistutilsArgError, msg | 
 |  | 
 |     for (opt, val) in opts: | 
 |         if len (opt) == 2 and opt[0] == '-': # it's a short option | 
 |             opt = short2long[opt[1]] | 
 |  | 
 |         elif len (opt) > 2 and opt[0:2] == '--': | 
 |             opt = opt[2:] | 
 |  | 
 |         else: | 
 |             raise RuntimeError, "getopt lies! (bad option string '%s')" % \ | 
 |                   opt | 
 |  | 
 |         attr = attr_name[opt] | 
 |         if takes_arg[opt]: | 
 |             setattr (object, attr, val) | 
 |         else: | 
 |             if val == '': | 
 |                 setattr (object, attr, 1) | 
 |             else: | 
 |                 raise RuntimeError, "getopt lies! (bad value '%s')" % value | 
 |  | 
 |     # end loop over options found in 'args' | 
 |  | 
 |     return args | 
 |  | 
 | # end fancy_getopt() |