3
Defines the Option class and some standard value-checking functions.
6
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Optik/option.py 0.96.1.D001 2004/08/23 09:55:29 knight"
8
# Original Optik revision this is based on:
9
__Optik_revision__ = "option.py,v 1.19.2.1 2002/07/23 01:51:14 gward Exp"
11
# Copyright (c) 2001 Gregory P. Ward. All rights reserved.
12
# See the README.txt distributed with Optik for licensing terms.
14
# created 2001/10/17, GPW (from optik.py)
18
from types import TupleType, ListType, DictType
19
from SCons.Optik.errors import OptionError, OptionValueError
21
_builtin_cvt = { "int" : (int, "integer"),
22
"long" : (long, "long integer"),
23
"float" : (float, "floating-point"),
24
"complex" : (complex, "complex") }
26
def check_builtin (option, opt, value):
27
(cvt, what) = _builtin_cvt[option.type]
31
raise OptionValueError(
32
#"%s: invalid %s argument %s" % (opt, what, repr(value)))
33
"option %s: invalid %s value: %s" % (opt, what, repr(value)))
35
def check_choice(option, opt, value):
36
if value in option.choices:
39
choices = string.join(map(repr, option.choices),", ")
40
raise OptionValueError(
41
"option %s: invalid choice: %s (choose from %s)"
42
% (opt, repr(value), choices))
44
# Not supplying a default is different from a default of None,
45
# so we need an explicit "not supplied" value.
46
NO_DEFAULT = "NO"+"DEFAULT"
52
_short_opts : [string]
63
callback_args : (any*)
64
callback_kwargs : { string : any }
69
# The list of instance attributes that may be set through
70
# keyword args to the constructor.
84
# The set of actions allowed by option parsers. Explicitly listed
85
# here so the constructor can validate its arguments.
96
# The set of actions that involve storing a value somewhere;
97
# also listed just for constructor argument validation. (If
98
# the action is one of these, there must be a destination.)
99
STORE_ACTIONS = ("store",
106
# The set of actions for which it makes sense to supply a value
107
# type, ie. where we expect an argument to this option.
108
TYPED_ACTIONS = ("store",
112
# The set of known types for option parsers. Again, listed here for
113
# constructor argument validation.
114
TYPES = ("string", "int", "long", "float", "complex", "choice")
116
# Dictionary of argument checking functions, which convert and
117
# validate option arguments according to the option type.
119
# Signature of checking functions is:
120
# check(option : Option, opt : string, value : string) -> any
122
# option is the Option instance calling the checker
123
# opt is the actual option seen on the command-line
124
# (eg. "-a", "--file")
125
# value is the option argument seen on the command-line
127
# The return value should be in the appropriate Python type
128
# for option.type -- eg. an integer if option.type == "int".
130
# If no checker is defined for a type, arguments will be
131
# unchecked and remain strings.
132
TYPE_CHECKER = { "int" : check_builtin,
133
"long" : check_builtin,
134
"float" : check_builtin,
135
"complex" : check_builtin,
136
"choice" : check_choice,
140
# CHECK_METHODS is a list of unbound method objects; they are called
141
# by the constructor, in order, after all attributes are
142
# initialized. The list is created and filled in later, after all
143
# the methods are actually defined. (I just put it here because I
144
# like to define and document all class attributes in the same
145
# place.) Subclasses that add another _check_*() method should
146
# define their own CHECK_METHODS list that adds their check method
147
# to those from this class.
151
# -- Constructor/initialization methods ----------------------------
153
def __init__ (self, *opts, **attrs):
154
# Set _short_opts, _long_opts attrs from 'opts' tuple
155
opts = self._check_opt_strings(opts)
156
self._set_opt_strings(opts)
158
# Set all other attrs (action, type, etc.) from 'attrs' dict
159
self._set_attrs(attrs)
161
# Check all the attributes we just set. There are lots of
162
# complicated interdependencies, but luckily they can be farmed
163
# out to the _check_*() methods listed in CHECK_METHODS -- which
164
# could be handy for subclasses! The one thing these all share
165
# is that they raise OptionError if they discover a problem.
166
for checker in self.CHECK_METHODS:
169
def _check_opt_strings (self, opts):
170
# Filter out None because early versions of Optik had exactly
171
# one short option and one long option, either of which
173
opts = filter(None, opts)
175
raise OptionError("at least one option string must be supplied",
179
def _set_opt_strings (self, opts):
180
self._short_opts = []
185
"invalid option string %s: "
186
"must be at least two characters long" % (`opt`,), self)
188
if not (opt[0] == "-" and opt[1] != "-"):
190
"invalid short option string %s: "
191
"must be of the form -x, (x any non-dash char)" % (`opt`,),
193
self._short_opts.append(opt)
195
if not (opt[0:2] == "--" and opt[2] != "-"):
197
"invalid long option string %s: "
198
"must start with --, followed by non-dash" % (`opt`,),
200
self._long_opts.append(opt)
202
def _set_attrs (self, attrs):
203
for attr in self.ATTRS:
204
if attrs.has_key(attr):
205
setattr(self, attr, attrs[attr])
208
if attr == 'default':
209
setattr(self, attr, NO_DEFAULT)
211
setattr(self, attr, None)
214
"invalid keyword arguments: %s" % string.join(attrs.keys(),", "),
218
# -- Constructor validation methods --------------------------------
220
def _check_action (self):
221
if self.action is None:
222
self.action = "store"
223
elif self.action not in self.ACTIONS:
224
raise OptionError("invalid action: %s" % (`self.action`,), self)
226
def _check_type (self):
227
if self.type is None:
228
# XXX should factor out another class attr here: list of
229
# actions that *require* a type
230
if self.action in ("store", "append"):
231
if self.choices is not None:
232
# The "choices" attribute implies "choice" type.
235
# No type given? "string" is the most sensible default.
238
if self.type not in self.TYPES:
239
raise OptionError("invalid option type: %s" % (`self.type`,), self)
240
if self.action not in self.TYPED_ACTIONS:
242
"must not supply a type for action %s" % (`self.action`,), self)
244
def _check_choice(self):
245
if self.type == "choice":
246
if self.choices is None:
248
"must supply a list of choices for type 'choice'", self)
249
elif type(self.choices) not in (TupleType, ListType):
251
"choices must be a list of strings ('%s' supplied)"
252
% string.split(str(type(self.choices)),"'")[1], self)
253
elif self.choices is not None:
255
"must not supply choices for type %s" % (repr(self.type),), self)
257
def _check_dest (self):
258
if self.action in self.STORE_ACTIONS and self.dest is None:
259
# No destination given, and we need one for this action.
260
# Glean a destination from the first long option string,
261
# or from the first short option string if no long options.
263
# eg. "--foo-bar" -> "foo_bar"
264
self.dest = string.replace(self._long_opts[0][2:],'-', '_')
266
self.dest = self._short_opts[0][1]
268
def _check_const (self):
269
if self.action != "store_const" and self.const is not None:
271
"'const' must not be supplied for action %s" % (repr(self.action),),
274
def _check_nargs (self):
275
if self.action in self.TYPED_ACTIONS:
276
if self.nargs is None:
278
elif self.nargs is not None:
280
"'nargs' must not be supplied for action %s" % (repr(self.action),),
283
def _check_callback (self):
284
if self.action == "callback":
285
if not callable(self.callback):
287
"callback not callable: %s" % (repr(self.callback),), self)
288
if (self.callback_args is not None and
289
type(self.callback_args) is not TupleType):
291
"callback_args, if supplied, must be a tuple: not %s"
292
% (repr(self.callback_args),), self)
293
if (self.callback_kwargs is not None and
294
type(self.callback_kwargs) is not DictType):
296
"callback_kwargs, if supplied, must be a dict: not %s"
297
% (repr(self.callback_kwargs),), self)
299
if self.callback is not None:
301
"callback supplied (%s) for non-callback option"
302
% (repr(self.callback),), self)
303
if self.callback_args is not None:
305
"callback_args supplied for non-callback option", self)
306
if self.callback_kwargs is not None:
308
"callback_kwargs supplied for non-callback option", self)
311
CHECK_METHODS = [_check_action,
320
# -- Miscellaneous methods -----------------------------------------
323
if self._short_opts or self._long_opts:
324
return string.join(self._short_opts + self._long_opts,"/")
326
raise RuntimeError, "short_opts and long_opts both empty!"
328
def takes_value (self):
329
return self.type is not None
332
# -- Processing methods --------------------------------------------
334
def check_value (self, opt, value):
335
checker = self.TYPE_CHECKER.get(self.type)
339
return checker(self, opt, value)
341
def process (self, opt, value, values, parser):
343
# First, convert the value(s) to the right type. Howl if any
344
# value(s) are bogus.
345
if value is not None:
347
value = self.check_value(opt, value)
349
def cv(v,check=self.check_value,o=opt):
352
value = tuple(map(cv,value))
354
# And then take whatever action is expected of us.
355
# This is a separate method to make life easier for
356
# subclasses to add new actions.
357
return self.take_action(
358
self.action, self.dest, opt, value, values, parser)
360
def take_action (self, action, dest, opt, value, values, parser):
361
if action == "store":
362
setattr(values, dest, value)
363
elif action == "store_const":
364
setattr(values, dest, self.const)
365
elif action == "store_true":
366
setattr(values, dest, 1)
367
elif action == "store_false":
368
setattr(values, dest, 0)
369
elif action == "append":
370
values.ensure_value(dest, []).append(value)
371
elif action == "count":
372
setattr(values, dest, values.ensure_value(dest, 0) + 1)
373
elif action == "callback":
374
args = self.callback_args or ()
375
kwargs = self.callback_kwargs or {}
376
apply( self.callback, (self, opt, value, parser,)+ args, kwargs)
377
elif action == "help":
380
elif action == "version":
381
parser.print_version()
384
raise RuntimeError, "unknown action %s" % (repr(self.action),)