1 """distutils.fancy_getopt
3 Wrapper around the standard getopt module that provides the following
5 * short and long options are tied together
6 * options have help strings, so fancy_getopt could potentially
7 create a complete usage summary
8 * options set attributes of a passed-in object
11 # created 1999/03/03, Greg Ward
18 from distutils
.errors
import *
20 # Much like command_re in distutils.core, this is close to but not quite
21 # the same as a Python NAME -- except, in the spirit of most GNU
22 # utilities, we use '-' in place of '_'. (The spirit of LISP lives on!)
23 # The similarities to NAME are again not a coincidence...
24 longopt_re
= re
.compile (r
'^[a-zA-Z]([a-zA-Z0-9-]*)$')
26 # This is used to translate long options to legitimate Python identifiers
27 # (for use as attributes of some object).
28 longopt_xlate
= string
.maketrans ('-', '_')
31 def fancy_getopt (options
, object, args
):
33 # The 'options' table is a list of 3-tuples:
34 # (long_option, short_option, help_string)
35 # if an option takes an argument, its long_option should have '='
36 # appended; short_option should just be a single character, no ':' in
37 # any case. If a long_option doesn't have a corresponding
38 # short_option, short_option should be None. All option tuples must
41 # Build the short_opts string and long_opts list, remembering how
42 # the two are tied together
44 short_opts
= [] # we'll join 'em when done
50 for (long, short
, help) in options
:
51 # Type-check the option names
52 if type (long) is not StringType
or len (long) < 2:
53 raise DistutilsGetoptError
, \
54 "long option must be a string of length >= 2"
56 if (not ((short
is None) or
57 (type (short
) is StringType
and len (short
) == 1))):
58 raise DistutilsGetoptError
, \
59 "short option must be None or string of length 1"
61 long_opts
.append (long)
63 if long[-1] == '=': # option takes an argument?
64 if short
: short
= short
+ ':'
70 # Now enforce some bondage on the long option name, so we can later
71 # translate it to an attribute name in 'object'. Have to do this a
72 # bit late to make sure we've removed any trailing '='.
73 if not longopt_re
.match (long):
74 raise DistutilsGetoptError
, \
75 ("invalid long option name '%s' " +
76 "(must be letters, numbers, hyphens only") % long
78 attr_name
[long] = string
.translate (long, longopt_xlate
)
80 short_opts
.append (short
)
81 short2long
[short
[0]] = long
83 # end loop over 'options'
85 short_opts
= string
.join (short_opts
)
87 (opts
, args
) = getopt
.getopt (args
, short_opts
, long_opts
)
88 except getopt
.error
, msg
:
89 raise DistutilsArgError
, msg
91 for (opt
, val
) in opts
:
92 if len (opt
) == 2 and opt
[0] == '-': # it's a short option
93 opt
= short2long
[opt
[1]]
95 elif len (opt
) > 2 and opt
[0:2] == '--':
99 raise RuntimeError, "getopt lies! (bad option string '%s')" % \
102 attr
= attr_name
[opt
]
104 setattr (object, attr
, val
)
107 setattr (object, attr
, 1)
109 raise RuntimeError, "getopt lies! (bad value '%s')" % value
111 # end loop over options found in 'args'