##// END OF EJS Templates
run reindent.py
vivainio -
Show More
This diff has been collapsed as it changes many lines, (1142 lines changed) Show them Hide them
@@ -1,7 +1,7 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """DPyGetOpt -- Demiurge Python GetOptions Module
2 """DPyGetOpt -- Demiurge Python GetOptions Module
3
3
4 $Id: DPyGetOpt.py 958 2005-12-27 23:17:51Z fperez $
4 $Id: DPyGetOpt.py 1980 2006-12-12 21:48:46Z vivainio $
5
5
6 This module is modeled after perl's Getopt::Long module-- which
6 This module is modeled after perl's Getopt::Long module-- which
7 is, in turn, modeled after GNU's extended getopt() function.
7 is, in turn, modeled after GNU's extended getopt() function.
@@ -33,7 +33,7 b' and -baz options that appear on within the parsed argument list'
33 must have a real number argument and that the accumulated list
33 must have a real number argument and that the accumulated list
34 of values will be available under the name 'foo'
34 of values will be available under the name 'foo'
35
35
36 $Id: DPyGetOpt.py 958 2005-12-27 23:17:51Z fperez $"""
36 $Id: DPyGetOpt.py 1980 2006-12-12 21:48:46Z vivainio $"""
37
37
38 #*****************************************************************************
38 #*****************************************************************************
39 #
39 #
@@ -80,592 +80,592 b" term_error = 'DPyGetOpt Termination Error'"
80
80
81 specificationExpr = re.compile('(?P<required>.)(?P<type>.)(?P<multi>@?)')
81 specificationExpr = re.compile('(?P<required>.)(?P<type>.)(?P<multi>@?)')
82
82
83 ArgRequired = 'Requires an Argument'
83 ArgRequired = 'Requires an Argument'
84 ArgOptional = 'Argument Optional'
84 ArgOptional = 'Argument Optional'
85
85
86 # The types modules is not used for these identifiers because there
86 # The types modules is not used for these identifiers because there
87 # is no identifier for 'boolean' or 'generic'
87 # is no identifier for 'boolean' or 'generic'
88 StringArgType = 'String Argument Type'
88 StringArgType = 'String Argument Type'
89 IntegerArgType = 'Integer Argument Type'
89 IntegerArgType = 'Integer Argument Type'
90 RealArgType = 'Real Argument Type'
90 RealArgType = 'Real Argument Type'
91 BooleanArgType = 'Boolean Argument Type'
91 BooleanArgType = 'Boolean Argument Type'
92 GenericArgType = 'Generic Argument Type'
92 GenericArgType = 'Generic Argument Type'
93
93
94 # dictionary of conversion functions-- boolean and generic options
94 # dictionary of conversion functions-- boolean and generic options
95 # do not accept arguments and do not need conversion functions;
95 # do not accept arguments and do not need conversion functions;
96 # the identity function is used purely for convenience.
96 # the identity function is used purely for convenience.
97 ConversionFunctions = {
97 ConversionFunctions = {
98 StringArgType : lambda x: x,
98 StringArgType : lambda x: x,
99 IntegerArgType : string.atoi,
99 IntegerArgType : string.atoi,
100 RealArgType : string.atof,
100 RealArgType : string.atof,
101 BooleanArgType : lambda x: x,
101 BooleanArgType : lambda x: x,
102 GenericArgType : lambda x: x,
102 GenericArgType : lambda x: x,
103 }
103 }
104
104
105 class DPyGetOpt:
105 class DPyGetOpt:
106
106
107 def __init__(self, spec = None, terminators = ['--']):
107 def __init__(self, spec = None, terminators = ['--']):
108 """
108 """
109 Declare and intialize instance variables
109 Declare and intialize instance variables
110
110
111 Yes, declaration is not necessary... but one of the things
111 Yes, declaration is not necessary... but one of the things
112 I sorely miss from C/Obj-C is the concept of having an
112 I sorely miss from C/Obj-C is the concept of having an
113 interface definition that clearly declares all instance
113 interface definition that clearly declares all instance
114 variables and methods without providing any implementation
114 variables and methods without providing any implementation
115 details. it is a useful reference!
115 details. it is a useful reference!
116
116
117 all instance variables are initialized to 0/Null/None of
117 all instance variables are initialized to 0/Null/None of
118 the appropriate type-- not even the default value...
118 the appropriate type-- not even the default value...
119 """
119 """
120
120
121 # sys.stderr.write(string.join(spec) + "\n")
121 # sys.stderr.write(string.join(spec) + "\n")
122
122
123 self.allowAbbreviations = 1 # boolean, 1 if abbreviations will
123 self.allowAbbreviations = 1 # boolean, 1 if abbreviations will
124 # be expanded
124 # be expanded
125 self.freeValues = [] # list, contains free values
125 self.freeValues = [] # list, contains free values
126 self.ignoreCase = 0 # boolean, YES if ignoring case
126 self.ignoreCase = 0 # boolean, YES if ignoring case
127 self.needsParse = 0 # boolean, YES if need to reparse parameter spec
127 self.needsParse = 0 # boolean, YES if need to reparse parameter spec
128 self.optionNames = {} # dict, all option names-- value is index of tuple
128 self.optionNames = {} # dict, all option names-- value is index of tuple
129 self.optionStartExpr = None # regexp defining the start of an option (ie; '-', '--')
129 self.optionStartExpr = None # regexp defining the start of an option (ie; '-', '--')
130 self.optionTuples = [] # list o' tuples containing defn of options AND aliases
130 self.optionTuples = [] # list o' tuples containing defn of options AND aliases
131 self.optionValues = {} # dict, option names (after alias expansion) -> option value(s)
131 self.optionValues = {} # dict, option names (after alias expansion) -> option value(s)
132 self.orderMixed = 0 # boolean, YES if options can be mixed with args
132 self.orderMixed = 0 # boolean, YES if options can be mixed with args
133 self.posixCompliance = 0 # boolean, YES indicates posix like behaviour
133 self.posixCompliance = 0 # boolean, YES indicates posix like behaviour
134 self.spec = [] # list, raw specs (in case it must be reparsed)
134 self.spec = [] # list, raw specs (in case it must be reparsed)
135 self.terminators = terminators # list, strings that terminate argument processing
135 self.terminators = terminators # list, strings that terminate argument processing
136 self.termValues = [] # list, values after terminator
136 self.termValues = [] # list, values after terminator
137 self.terminator = None # full name of terminator that ended
137 self.terminator = None # full name of terminator that ended
138 # option processing
138 # option processing
139
139
140 # set up defaults
140 # set up defaults
141 self.setPosixCompliance()
141 self.setPosixCompliance()
142 self.setIgnoreCase()
142 self.setIgnoreCase()
143 self.setAllowAbbreviations()
143 self.setAllowAbbreviations()
144
144
145 # parse spec-- if present
145 # parse spec-- if present
146 if spec:
146 if spec:
147 self.parseConfiguration(spec)
147 self.parseConfiguration(spec)
148
148
149 def setPosixCompliance(self, aFlag = 0):
149 def setPosixCompliance(self, aFlag = 0):
150 """
150 """
151 Enables and disables posix compliance.
151 Enables and disables posix compliance.
152
152
153 When enabled, '+' can be used as an option prefix and free
153 When enabled, '+' can be used as an option prefix and free
154 values can be mixed with options.
154 values can be mixed with options.
155 """
155 """
156 self.posixCompliance = aFlag
156 self.posixCompliance = aFlag
157 self.needsParse = 1
157 self.needsParse = 1
158
158
159 if self.posixCompliance:
159 if self.posixCompliance:
160 self.optionStartExpr = re.compile('(--|-)(?P<option>[A-Za-z0-9_-]+)(?P<arg>=.*)?')
160 self.optionStartExpr = re.compile('(--|-)(?P<option>[A-Za-z0-9_-]+)(?P<arg>=.*)?')
161 self.orderMixed = 0
161 self.orderMixed = 0
162 else:
162 else:
163 self.optionStartExpr = re.compile('(--|-|\+)(?P<option>[A-Za-z0-9_-]+)(?P<arg>=.*)?')
163 self.optionStartExpr = re.compile('(--|-|\+)(?P<option>[A-Za-z0-9_-]+)(?P<arg>=.*)?')
164 self.orderMixed = 1
164 self.orderMixed = 1
165
165
166 def isPosixCompliant(self):
166 def isPosixCompliant(self):
167 """
167 """
168 Returns the value of the posix compliance flag.
168 Returns the value of the posix compliance flag.
169 """
169 """
170 return self.posixCompliance
170 return self.posixCompliance
171
171
172 def setIgnoreCase(self, aFlag = 1):
172 def setIgnoreCase(self, aFlag = 1):
173 """
173 """
174 Enables and disables ignoring case during option processing.
174 Enables and disables ignoring case during option processing.
175 """
175 """
176 self.needsParse = 1
176 self.needsParse = 1
177 self.ignoreCase = aFlag
177 self.ignoreCase = aFlag
178
178
179 def ignoreCase(self):
179 def ignoreCase(self):
180 """
180 """
181 Returns 1 if the option processor will ignore case when
181 Returns 1 if the option processor will ignore case when
182 processing options.
182 processing options.
183 """
183 """
184 return self.ignoreCase
184 return self.ignoreCase
185
185
186 def setAllowAbbreviations(self, aFlag = 1):
186 def setAllowAbbreviations(self, aFlag = 1):
187 """
187 """
188 Enables and disables the expansion of abbreviations during
188 Enables and disables the expansion of abbreviations during
189 option processing.
189 option processing.
190 """
190 """
191 self.allowAbbreviations = aFlag
191 self.allowAbbreviations = aFlag
192
192
193 def willAllowAbbreviations(self):
193 def willAllowAbbreviations(self):
194 """
194 """
195 Returns 1 if abbreviated options will be automatically
195 Returns 1 if abbreviated options will be automatically
196 expanded to the non-abbreviated form (instead of causing an
196 expanded to the non-abbreviated form (instead of causing an
197 unrecognized option error).
197 unrecognized option error).
198 """
198 """
199 return self.allowAbbreviations
199 return self.allowAbbreviations
200
200
201 def addTerminator(self, newTerm):
201 def addTerminator(self, newTerm):
202 """
202 """
203 Adds newTerm as terminator of option processing.
203 Adds newTerm as terminator of option processing.
204
204
205 Whenever the option processor encounters one of the terminators
205 Whenever the option processor encounters one of the terminators
206 during option processing, the processing of options terminates
206 during option processing, the processing of options terminates
207 immediately, all remaining options are stored in the termValues
207 immediately, all remaining options are stored in the termValues
208 instance variable and the full name of the terminator is stored
208 instance variable and the full name of the terminator is stored
209 in the terminator instance variable.
209 in the terminator instance variable.
210 """
210 """
211 self.terminators = self.terminators + [newTerm]
211 self.terminators = self.terminators + [newTerm]
212
212
213 def _addOption(self, oTuple):
213 def _addOption(self, oTuple):
214 """
214 """
215 Adds the option described by oTuple (name, (type, mode,
215 Adds the option described by oTuple (name, (type, mode,
216 default), alias) to optionTuples. Adds index keyed under name
216 default), alias) to optionTuples. Adds index keyed under name
217 to optionNames. Raises spec_error if name already in
217 to optionNames. Raises spec_error if name already in
218 optionNames
218 optionNames
219 """
219 """
220 (name, (type, mode, default, multi), realName) = oTuple
220 (name, (type, mode, default, multi), realName) = oTuple
221
221
222 # verify name and add to option names dictionary
222 # verify name and add to option names dictionary
223 if self.optionNames.has_key(name):
223 if self.optionNames.has_key(name):
224 if realName:
224 if realName:
225 raise spec_error, 'Alias \'' + name + '\' for \'' + realName + \
225 raise spec_error, 'Alias \'' + name + '\' for \'' + realName + \
226 '\' already used for another option or alias.'
226 '\' already used for another option or alias.'
227 else:
227 else:
228 raise spec_error, 'Option named \'' + name + \
228 raise spec_error, 'Option named \'' + name + \
229 '\' specified more than once. Specification: ' + option
229 '\' specified more than once. Specification: ' + option
230
230
231 # validated. add to optionNames
231 # validated. add to optionNames
232 self.optionNames[name] = self.tupleIndex
232 self.optionNames[name] = self.tupleIndex
233 self.tupleIndex = self.tupleIndex + 1
233 self.tupleIndex = self.tupleIndex + 1
234
234
235 # add to optionTuples
235 # add to optionTuples
236 self.optionTuples = self.optionTuples + [oTuple]
236 self.optionTuples = self.optionTuples + [oTuple]
237
237
238 # if type is boolean, add negation
238 # if type is boolean, add negation
239 if type == BooleanArgType:
239 if type == BooleanArgType:
240 alias = 'no' + name
240 alias = 'no' + name
241 specTuple = (type, mode, 0, multi)
241 specTuple = (type, mode, 0, multi)
242 oTuple = (alias, specTuple, name)
242 oTuple = (alias, specTuple, name)
243
243
244 # verify name and add to option names dictionary
244 # verify name and add to option names dictionary
245 if self.optionNames.has_key(alias):
245 if self.optionNames.has_key(alias):
246 if realName:
246 if realName:
247 raise spec_error, 'Negated alias \'' + name + '\' for \'' + realName + \
247 raise spec_error, 'Negated alias \'' + name + '\' for \'' + realName + \
248 '\' already used for another option or alias.'
248 '\' already used for another option or alias.'
249 else:
249 else:
250 raise spec_error, 'Negated option named \'' + name + \
250 raise spec_error, 'Negated option named \'' + name + \
251 '\' specified more than once. Specification: ' + option
251 '\' specified more than once. Specification: ' + option
252
252
253 # validated. add to optionNames
253 # validated. add to optionNames
254 self.optionNames[alias] = self.tupleIndex
254 self.optionNames[alias] = self.tupleIndex
255 self.tupleIndex = self.tupleIndex + 1
255 self.tupleIndex = self.tupleIndex + 1
256
256
257 # add to optionTuples
257 # add to optionTuples
258 self.optionTuples = self.optionTuples + [oTuple]
258 self.optionTuples = self.optionTuples + [oTuple]
259
259
260 def addOptionConfigurationTuple(self, oTuple):
260 def addOptionConfigurationTuple(self, oTuple):
261 (name, argSpec, realName) = oTuple
261 (name, argSpec, realName) = oTuple
262 if self.ignoreCase:
262 if self.ignoreCase:
263 name = string.lower(name)
263 name = string.lower(name)
264 if realName:
264 if realName:
265 realName = string.lower(realName)
265 realName = string.lower(realName)
266 else:
266 else:
267 realName = name
267 realName = name
268
268
269 oTuple = (name, argSpec, realName)
269 oTuple = (name, argSpec, realName)
270
270
271 # add option
271 # add option
272 self._addOption(oTuple)
272 self._addOption(oTuple)
273
273
274 def addOptionConfigurationTuples(self, oTuple):
274 def addOptionConfigurationTuples(self, oTuple):
275 if type(oTuple) is ListType:
275 if type(oTuple) is ListType:
276 for t in oTuple:
276 for t in oTuple:
277 self.addOptionConfigurationTuple(t)
277 self.addOptionConfigurationTuple(t)
278 else:
278 else:
279 self.addOptionConfigurationTuple(oTuple)
279 self.addOptionConfigurationTuple(oTuple)
280
280
281 def parseConfiguration(self, spec):
281 def parseConfiguration(self, spec):
282 # destroy previous stored information + store raw spec
282 # destroy previous stored information + store raw spec
283 self.spec = spec
283 self.spec = spec
284 self.optionTuples = []
284 self.optionTuples = []
285 self.optionNames = {}
285 self.optionNames = {}
286 self.tupleIndex = 0
286 self.tupleIndex = 0
287
287
288 tupleIndex = 0
288 tupleIndex = 0
289
289
290 # create some regex's for parsing each spec
290 # create some regex's for parsing each spec
291 splitExpr = \
291 splitExpr = \
292 re.compile('(?P<names>\w+[-A-Za-z0-9|]*)?(?P<spec>!|[=:][infs]@?)?')
292 re.compile('(?P<names>\w+[-A-Za-z0-9|]*)?(?P<spec>!|[=:][infs]@?)?')
293 for option in spec:
293 for option in spec:
294 # push to lower case (does not negatively affect
294 # push to lower case (does not negatively affect
295 # specification)
295 # specification)
296 if self.ignoreCase:
296 if self.ignoreCase:
297 option = string.lower(option)
297 option = string.lower(option)
298
298
299 # break into names, specification
299 # break into names, specification
300 match = splitExpr.match(option)
300 match = splitExpr.match(option)
301 if match is None:
301 if match is None:
302 raise spec_error, 'Invalid specification {' + option + '}'
302 raise spec_error, 'Invalid specification {' + option + '}'
303
303
304 names = match.group('names')
304 names = match.group('names')
305 specification = match.group('spec')
305 specification = match.group('spec')
306
306
307 # break name into name, aliases
307 # break name into name, aliases
308 nlist = string.split(names, '|')
308 nlist = string.split(names, '|')
309
309
310 # get name
310 # get name
311 name = nlist[0]
311 name = nlist[0]
312 aliases = nlist[1:]
312 aliases = nlist[1:]
313
313
314 # specificationExpr = regex.symcomp('\(<required>.\)\(<type>.\)\(<multi>@?\)')
314 # specificationExpr = regex.symcomp('\(<required>.\)\(<type>.\)\(<multi>@?\)')
315 if not specification:
315 if not specification:
316 #spec tuple is ('type', 'arg mode', 'default value', 'multiple')
316 #spec tuple is ('type', 'arg mode', 'default value', 'multiple')
317 argType = GenericArgType
317 argType = GenericArgType
318 argMode = None
318 argMode = None
319 argDefault = 1
319 argDefault = 1
320 argMultiple = 0
320 argMultiple = 0
321 elif specification == '!':
321 elif specification == '!':
322 argType = BooleanArgType
322 argType = BooleanArgType
323 argMode = None
323 argMode = None
324 argDefault = 1
324 argDefault = 1
325 argMultiple = 0
325 argMultiple = 0
326 else:
326 else:
327 # parse
327 # parse
328 match = specificationExpr.match(specification)
328 match = specificationExpr.match(specification)
329 if match is None:
329 if match is None:
330 # failed to parse, die
330 # failed to parse, die
331 raise spec_error, 'Invalid configuration for option \'' + option + '\''
331 raise spec_error, 'Invalid configuration for option \'' + option + '\''
332
332
333 # determine mode
333 # determine mode
334 required = match.group('required')
334 required = match.group('required')
335 if required == '=':
335 if required == '=':
336 argMode = ArgRequired
336 argMode = ArgRequired
337 elif required == ':':
337 elif required == ':':
338 argMode = ArgOptional
338 argMode = ArgOptional
339 else:
339 else:
340 raise spec_error, 'Unknown requirement configuration \'' + required + '\''
340 raise spec_error, 'Unknown requirement configuration \'' + required + '\''
341
341
342 # determine type
342 # determine type
343 type = match.group('type')
343 type = match.group('type')
344 if type == 's':
344 if type == 's':
345 argType = StringArgType
345 argType = StringArgType
346 argDefault = ''
346 argDefault = ''
347 elif type == 'i':
347 elif type == 'i':
348 argType = IntegerArgType
348 argType = IntegerArgType
349 argDefault = 1
349 argDefault = 1
350 elif type == 'f' or type == 'n':
350 elif type == 'f' or type == 'n':
351 argType = RealArgType
351 argType = RealArgType
352 argDefault = 1
352 argDefault = 1
353 else:
353 else:
354 raise spec_error, 'Unknown type specifier \'' + type + '\''
354 raise spec_error, 'Unknown type specifier \'' + type + '\''
355
355
356 # determine quantity
356 # determine quantity
357 if match.group('multi') == '@':
357 if match.group('multi') == '@':
358 argMultiple = 1
358 argMultiple = 1
359 else:
359 else:
360 argMultiple = 0
360 argMultiple = 0
361 ## end else (of not specification)
361 ## end else (of not specification)
362
362
363 # construct specification tuple
363 # construct specification tuple
364 specTuple = (argType, argMode, argDefault, argMultiple)
364 specTuple = (argType, argMode, argDefault, argMultiple)
365
365
366 # add the option-- option tuple is (name, specTuple, real name)
366 # add the option-- option tuple is (name, specTuple, real name)
367 oTuple = (name, specTuple, name)
367 oTuple = (name, specTuple, name)
368 self._addOption(oTuple)
368 self._addOption(oTuple)
369
369
370 for alias in aliases:
370 for alias in aliases:
371 # drop to all lower (if configured to do so)
371 # drop to all lower (if configured to do so)
372 if self.ignoreCase:
372 if self.ignoreCase:
373 alias = string.lower(alias)
373 alias = string.lower(alias)
374 # create configuration tuple
374 # create configuration tuple
375 oTuple = (alias, specTuple, name)
375 oTuple = (alias, specTuple, name)
376 # add
376 # add
377 self._addOption(oTuple)
377 self._addOption(oTuple)
378
378
379 # successfully parsed....
379 # successfully parsed....
380 self.needsParse = 0
380 self.needsParse = 0
381
381
382 def _getArgTuple(self, argName):
382 def _getArgTuple(self, argName):
383 """
383 """
384 Returns a list containing all the specification tuples that
384 Returns a list containing all the specification tuples that
385 match argName. If none match, None is returned. If one
385 match argName. If none match, None is returned. If one
386 matches, a list with one tuple is returned. If more than one
386 matches, a list with one tuple is returned. If more than one
387 match, a list containing all the tuples that matched is
387 match, a list containing all the tuples that matched is
388 returned.
388 returned.
389
389
390 In other words, this function does not pass judgement upon the
390 In other words, this function does not pass judgement upon the
391 validity of multiple matches.
391 validity of multiple matches.
392 """
392 """
393 # is it in the optionNames dict?
393 # is it in the optionNames dict?
394
394
395 try:
395 try:
396 # sys.stderr.write(argName + string.join(self.optionNames.keys()) + "\n")
396 # sys.stderr.write(argName + string.join(self.optionNames.keys()) + "\n")
397
397
398 # yes, get index
398 # yes, get index
399 tupleIndex = self.optionNames[argName]
399 tupleIndex = self.optionNames[argName]
400 # and return tuple as element of list
400 # and return tuple as element of list
401 return [self.optionTuples[tupleIndex]]
401 return [self.optionTuples[tupleIndex]]
402 except KeyError:
402 except KeyError:
403 # are abbreviations allowed?
403 # are abbreviations allowed?
404 if not self.allowAbbreviations:
404 if not self.allowAbbreviations:
405 # No! terefore, this cannot be valid argument-- nothing found
405 # No! terefore, this cannot be valid argument-- nothing found
406 return None
406 return None
407
407
408 # argName might be an abbreviation (and, abbreviations must
408 # argName might be an abbreviation (and, abbreviations must
409 # be allowed... or this would not have been reached!)
409 # be allowed... or this would not have been reached!)
410
410
411 # create regex for argName
411 # create regex for argName
412 argExpr = re.compile('^' + argName)
412 argExpr = re.compile('^' + argName)
413
413
414 tuples = filter(lambda x, argExpr=argExpr: argExpr.search(x[0]) is not None,
414 tuples = filter(lambda x, argExpr=argExpr: argExpr.search(x[0]) is not None,
415 self.optionTuples)
415 self.optionTuples)
416
416
417 if not len(tuples):
417 if not len(tuples):
418 return None
418 return None
419 else:
419 else:
420 return tuples
420 return tuples
421
421
422 def _isTerminator(self, optionName):
422 def _isTerminator(self, optionName):
423 """
423 """
424 Returns the full name of the terminator if optionName is a valid
424 Returns the full name of the terminator if optionName is a valid
425 terminator. If it is, sets self.terminator to the full name of
425 terminator. If it is, sets self.terminator to the full name of
426 the terminator.
426 the terminator.
427
427
428 If more than one terminator matched, raises a term_error with a
428 If more than one terminator matched, raises a term_error with a
429 string describing the ambiguity.
429 string describing the ambiguity.
430 """
430 """
431
431
432 # sys.stderr.write(optionName + "\n")
432 # sys.stderr.write(optionName + "\n")
433 # sys.stderr.write(repr(self.terminators))
433 # sys.stderr.write(repr(self.terminators))
434
434
435 if optionName in self.terminators:
435 if optionName in self.terminators:
436 self.terminator = optionName
436 self.terminator = optionName
437 elif not self.allowAbbreviations:
437 elif not self.allowAbbreviations:
438 return None
438 return None
439
439
440 # regex thing in bogus
440 # regex thing in bogus
441 # termExpr = regex.compile('^' + optionName)
441 # termExpr = regex.compile('^' + optionName)
442
442
443 terms = filter(lambda x, on=optionName: string.find(x,on) == 0, self.terminators)
443 terms = filter(lambda x, on=optionName: string.find(x,on) == 0, self.terminators)
444
444
445 if not len(terms):
445 if not len(terms):
446 return None
446 return None
447 elif len(terms) > 1:
447 elif len(terms) > 1:
448 raise term_error, 'Ambiguous terminator \'' + optionName + \
448 raise term_error, 'Ambiguous terminator \'' + optionName + \
449 '\' matches ' + repr(terms)
449 '\' matches ' + repr(terms)
450
450
451 self.terminator = terms[0]
451 self.terminator = terms[0]
452 return self.terminator
452 return self.terminator
453
453
454 def processArguments(self, args = None):
454 def processArguments(self, args = None):
455 """
455 """
456 Processes args, a list of arguments (including options).
456 Processes args, a list of arguments (including options).
457
457
458 If args is the same as sys.argv, automatically trims the first
458 If args is the same as sys.argv, automatically trims the first
459 argument (the executable name/path).
459 argument (the executable name/path).
460
460
461 If an exception is not raised, the argument list was parsed
461 If an exception is not raised, the argument list was parsed
462 correctly.
462 correctly.
463
463
464 Upon successful completion, the freeValues instance variable
464 Upon successful completion, the freeValues instance variable
465 will contain all the arguments that were not associated with an
465 will contain all the arguments that were not associated with an
466 option in the order they were encountered. optionValues is a
466 option in the order they were encountered. optionValues is a
467 dictionary containing the value of each option-- the method
467 dictionary containing the value of each option-- the method
468 valueForOption() can be used to query this dictionary.
468 valueForOption() can be used to query this dictionary.
469 terminator will contain the argument encountered that terminated
469 terminator will contain the argument encountered that terminated
470 option processing (or None, if a terminator was never
470 option processing (or None, if a terminator was never
471 encountered) and termValues will contain all of the options that
471 encountered) and termValues will contain all of the options that
472 appeared after the Terminator (or an empty list).
472 appeared after the Terminator (or an empty list).
473 """
473 """
474
474
475 if hasattr(sys, "argv") and args == sys.argv:
475 if hasattr(sys, "argv") and args == sys.argv:
476 args = sys.argv[1:]
476 args = sys.argv[1:]
477
477
478 max = len(args) # maximum index + 1
478 max = len(args) # maximum index + 1
479 self.freeValues = [] # array to hold return values
479 self.freeValues = [] # array to hold return values
480 self.optionValues= {}
480 self.optionValues= {}
481 index = 0 # initial index
481 index = 0 # initial index
482 self.terminator = None
482 self.terminator = None
483 self.termValues = []
483 self.termValues = []
484
484
485 while index < max:
485 while index < max:
486 # obtain argument
486 # obtain argument
487 arg = args[index]
487 arg = args[index]
488 # increment index -- REMEMBER; it is NOW incremented
488 # increment index -- REMEMBER; it is NOW incremented
489 index = index + 1
489 index = index + 1
490
490
491 # terminate immediately if option terminator encountered
491 # terminate immediately if option terminator encountered
492 if self._isTerminator(arg):
492 if self._isTerminator(arg):
493 self.freeValues = self.freeValues + args[index:]
493 self.freeValues = self.freeValues + args[index:]
494 self.termValues = args[index:]
494 self.termValues = args[index:]
495 return
495 return
496
496
497 # is this possibly an option?
497 # is this possibly an option?
498 match = self.optionStartExpr.match(arg)
498 match = self.optionStartExpr.match(arg)
499 if match is None:
499 if match is None:
500 # not an option-- add to freeValues
500 # not an option-- add to freeValues
501 self.freeValues = self.freeValues + [arg]
501 self.freeValues = self.freeValues + [arg]
502 if not self.orderMixed:
502 if not self.orderMixed:
503 # mixing not allowed; add rest of args as freeValues
503 # mixing not allowed; add rest of args as freeValues
504 self.freeValues = self.freeValues + args[index:]
504 self.freeValues = self.freeValues + args[index:]
505 # return to caller
505 # return to caller
506 return
506 return
507 else:
507 else:
508 continue
508 continue
509
509
510 # grab name
510 # grab name
511 optName = match.group('option')
511 optName = match.group('option')
512
512
513 # obtain next argument-- index has already been incremented
513 # obtain next argument-- index has already been incremented
514 nextArg = match.group('arg')
514 nextArg = match.group('arg')
515 if nextArg:
515 if nextArg:
516 nextArg = nextArg[1:]
516 nextArg = nextArg[1:]
517 index = index - 1 # put it back
517 index = index - 1 # put it back
518 else:
518 else:
519 try:
519 try:
520 nextArg = args[index]
520 nextArg = args[index]
521 except:
521 except:
522 nextArg = None
522 nextArg = None
523
523
524 # transpose to lower case, if necessary
524 # transpose to lower case, if necessary
525 if self.ignoreCase:
525 if self.ignoreCase:
526 optName = string.lower(optName)
526 optName = string.lower(optName)
527
527
528 # obtain defining tuple
528 # obtain defining tuple
529 tuples = self._getArgTuple(optName)
529 tuples = self._getArgTuple(optName)
530
530
531 if tuples == None:
531 if tuples == None:
532 raise arg_error, 'Illegal option \'' + arg + '\''
532 raise arg_error, 'Illegal option \'' + arg + '\''
533 elif len(tuples) > 1:
533 elif len(tuples) > 1:
534 raise arg_error, 'Ambiguous option \'' + arg + '\'; matches ' + \
534 raise arg_error, 'Ambiguous option \'' + arg + '\'; matches ' + \
535 repr(map(lambda x: x[0], tuples))
535 repr(map(lambda x: x[0], tuples))
536 else:
536 else:
537 config = tuples[0]
537 config = tuples[0]
538
538
539 # config is now set to the configuration tuple for the
539 # config is now set to the configuration tuple for the
540 # argument
540 # argument
541 (fullName, spec, realName) = config
541 (fullName, spec, realName) = config
542 (optType, optMode, optDefault, optMultiple) = spec
542 (optType, optMode, optDefault, optMultiple) = spec
543
543
544 # if opt mode required, but nextArg is none, raise an error
544 # if opt mode required, but nextArg is none, raise an error
545 if (optMode == ArgRequired):
545 if (optMode == ArgRequired):
546 if (not nextArg) or self._isTerminator(nextArg):
546 if (not nextArg) or self._isTerminator(nextArg):
547 # print nextArg
547 # print nextArg
548 raise arg_error, 'Option \'' + arg + \
548 raise arg_error, 'Option \'' + arg + \
549 '\' requires an argument of type ' + optType
549 '\' requires an argument of type ' + optType
550
550
551 if (not optMode == None) and nextArg and (not self._isTerminator(nextArg)):
551 if (not optMode == None) and nextArg and (not self._isTerminator(nextArg)):
552 # nextArg defined, option configured to possibly consume arg
552 # nextArg defined, option configured to possibly consume arg
553 try:
553 try:
554 # grab conversion function-- the try is more for internal diagnostics
554 # grab conversion function-- the try is more for internal diagnostics
555 func = ConversionFunctions[optType]
555 func = ConversionFunctions[optType]
556 try:
556 try:
557 optionValue = func(nextArg)
557 optionValue = func(nextArg)
558 index = index + 1
558 index = index + 1
559 except:
559 except:
560 # only raise conversion error if REQUIRED to consume argument
560 # only raise conversion error if REQUIRED to consume argument
561 if optMode == ArgRequired:
561 if optMode == ArgRequired:
562 raise arg_error, 'Invalid argument to option \'' + arg + \
562 raise arg_error, 'Invalid argument to option \'' + arg + \
563 '\'; should be \'' + optType + '\''
563 '\'; should be \'' + optType + '\''
564 else:
564 else:
565 optionValue = optDefault
565 optionValue = optDefault
566 except arg_error:
566 except arg_error:
567 raise arg_error, sys.exc_value
567 raise arg_error, sys.exc_value
568 except:
568 except:
569 raise arg_error, '(' + arg + \
569 raise arg_error, '(' + arg + \
570 ') Conversion function for \'' + optType + '\' not found.'
570 ') Conversion function for \'' + optType + '\' not found.'
571 else:
571 else:
572 optionValue = optDefault
572 optionValue = optDefault
573
573
574 # add value to options dictionary
574 # add value to options dictionary
575 if optMultiple:
575 if optMultiple:
576 # can be multiple values
576 # can be multiple values
577 try:
577 try:
578 # try to append element
578 # try to append element
579 self.optionValues[realName] = self.optionValues[realName] + [optionValue]
579 self.optionValues[realName] = self.optionValues[realName] + [optionValue]
580 except:
580 except:
581 # failed-- must not exist; add it
581 # failed-- must not exist; add it
582 self.optionValues[realName] = [optionValue]
582 self.optionValues[realName] = [optionValue]
583 else:
583 else:
584 # only one value per
584 # only one value per
585 if self.isPosixCompliant and self.optionValues.has_key(realName):
585 if self.isPosixCompliant and self.optionValues.has_key(realName):
586 raise arg_error, 'Argument \'' + arg + '\' occurs multiple times.'
586 raise arg_error, 'Argument \'' + arg + '\' occurs multiple times.'
587
587
588 self.optionValues[realName] = optionValue
588 self.optionValues[realName] = optionValue
589
589
590 def valueForOption(self, optionName, defaultValue = None):
590 def valueForOption(self, optionName, defaultValue = None):
591 """
591 """
592 Return the value associated with optionName. If optionName was
592 Return the value associated with optionName. If optionName was
593 not encountered during parsing of the arguments, returns the
593 not encountered during parsing of the arguments, returns the
594 defaultValue (which defaults to None).
594 defaultValue (which defaults to None).
595 """
595 """
596 try:
596 try:
597 optionValue = self.optionValues[optionName]
597 optionValue = self.optionValues[optionName]
598 except:
598 except:
599 optionValue = defaultValue
599 optionValue = defaultValue
600
600
601 return optionValue
601 return optionValue
602
602
603 ##
603 ##
604 ## test/example section
604 ## test/example section
605 ##
605 ##
606 test_error = 'Test Run Amok!'
606 test_error = 'Test Run Amok!'
607 def _test():
607 def _test():
608 """
608 """
609 A relatively complete test suite.
609 A relatively complete test suite.
610 """
610 """
611 try:
611 try:
612 DPyGetOpt(['foo', 'bar=s', 'foo'])
612 DPyGetOpt(['foo', 'bar=s', 'foo'])
613 except:
613 except:
614 print 'EXCEPTION (should be \'foo\' already used..): ' + sys.exc_value
614 print 'EXCEPTION (should be \'foo\' already used..): ' + sys.exc_value
615
615
616 try:
616 try:
617 DPyGetOpt(['foo|bar|apple=s@', 'baz|apple!'])
617 DPyGetOpt(['foo|bar|apple=s@', 'baz|apple!'])
618 except:
618 except:
619 print 'EXCEPTION (should be duplicate alias/name error): ' + sys.exc_value
619 print 'EXCEPTION (should be duplicate alias/name error): ' + sys.exc_value
620
620
621 x = DPyGetOpt(['apple|atlas=i@', 'application|executable=f@'])
621 x = DPyGetOpt(['apple|atlas=i@', 'application|executable=f@'])
622 try:
622 try:
623 x.processArguments(['-app', '29.3'])
623 x.processArguments(['-app', '29.3'])
624 except:
624 except:
625 print 'EXCEPTION (should be ambiguous argument): ' + sys.exc_value
625 print 'EXCEPTION (should be ambiguous argument): ' + sys.exc_value
626
626
627 x = DPyGetOpt(['foo'], ['antigravity', 'antithesis'])
627 x = DPyGetOpt(['foo'], ['antigravity', 'antithesis'])
628 try:
628 try:
629 x.processArguments(['-foo', 'anti'])
629 x.processArguments(['-foo', 'anti'])
630 except:
630 except:
631 print 'EXCEPTION (should be ambiguous terminator): ' + sys.exc_value
631 print 'EXCEPTION (should be ambiguous terminator): ' + sys.exc_value
632
632
633 profile = ['plain-option',
633 profile = ['plain-option',
634 'boolean-option!',
634 'boolean-option!',
635 'list-of-integers=i@',
635 'list-of-integers=i@',
636 'list-real-option|list-real-alias|list-real-pseudonym=f@',
636 'list-real-option|list-real-alias|list-real-pseudonym=f@',
637 'optional-string-option:s',
637 'optional-string-option:s',
638 'abbreviated-string-list=s@']
638 'abbreviated-string-list=s@']
639
639
640 terminators = ['terminator']
640 terminators = ['terminator']
641
641
642 args = ['-plain-option',
642 args = ['-plain-option',
643 '+noboolean-option',
643 '+noboolean-option',
644 '--list-of-integers', '1',
644 '--list-of-integers', '1',
645 '+list-of-integers', '2',
645 '+list-of-integers', '2',
646 '-list-of-integers', '3',
646 '-list-of-integers', '3',
647 'freeargone',
647 'freeargone',
648 '-list-real-option', '1.1',
648 '-list-real-option', '1.1',
649 '+list-real-alias', '1.2',
649 '+list-real-alias', '1.2',
650 '--list-real-pseudonym', '1.3',
650 '--list-real-pseudonym', '1.3',
651 'freeargtwo',
651 'freeargtwo',
652 '-abbreviated-string-list', 'String1',
652 '-abbreviated-string-list', 'String1',
653 '--abbreviated-s', 'String2',
653 '--abbreviated-s', 'String2',
654 '-abbrev', 'String3',
654 '-abbrev', 'String3',
655 '-a', 'String4',
655 '-a', 'String4',
656 '-optional-string-option',
656 '-optional-string-option',
657 'term',
657 'term',
658 'next option should look like an invalid arg',
658 'next option should look like an invalid arg',
659 '-a']
659 '-a']
660
660
661
661
662 print 'Using profile: ' + repr(profile)
662 print 'Using profile: ' + repr(profile)
663 print 'With terminator: ' + repr(terminators)
663 print 'With terminator: ' + repr(terminators)
664 print 'Processing arguments: ' + repr(args)
664 print 'Processing arguments: ' + repr(args)
665
665
666 go = DPyGetOpt(profile, terminators)
666 go = DPyGetOpt(profile, terminators)
667 go.processArguments(args)
667 go.processArguments(args)
668
668
669 print 'Options (and values): ' + repr(go.optionValues)
669 print 'Options (and values): ' + repr(go.optionValues)
670 print 'free args: ' + repr(go.freeValues)
670 print 'free args: ' + repr(go.freeValues)
671 print 'term args: ' + repr(go.termValues)
671 print 'term args: ' + repr(go.termValues)
@@ -10,10 +10,10 b' try:'
10 from IPython.Extensions.path import path
10 from IPython.Extensions.path import path
11 except ImportError:
11 except ImportError:
12 try:
12 try:
13 from Extensions.path import path
13 from Extensions.path import path
14 except ImportError:
14 except ImportError:
15 from path import path
15 from path import path
16
16
17 import md5,pickle
17 import md5,pickle
18
18
19 def showdiff(old,new):
19 def showdiff(old,new):
@@ -24,12 +24,12 b' def showdiff(old,new):'
24 for l in lines:
24 for l in lines:
25 print l,
25 print l,
26 if not realdiff and not l[0].isspace():
26 if not realdiff and not l[0].isspace():
27 realdiff = True
27 realdiff = True
28 return realdiff
28 return realdiff
29
29
30 def upgrade_dir(srcdir, tgtdir):
30 def upgrade_dir(srcdir, tgtdir):
31 """ Copy over all files in srcdir to tgtdir w/ native line endings
31 """ Copy over all files in srcdir to tgtdir w/ native line endings
32
32
33 Creates .upgrade_report in tgtdir that stores md5sums of all files
33 Creates .upgrade_report in tgtdir that stores md5sums of all files
34 to notice changed files b/w upgrades.
34 to notice changed files b/w upgrades.
35 """
35 """
@@ -41,8 +41,8 b' def upgrade_dir(srcdir, tgtdir):'
41 if p.lower().startswith('.svn') or p.startswith('ipythonrc'):
41 if p.lower().startswith('.svn') or p.startswith('ipythonrc'):
42 return True
42 return True
43 return False
43 return False
44
44
45
45
46 modded = []
46 modded = []
47 files = [path(srcdir).relpathto(p) for p in path(srcdir).walkfiles()]
47 files = [path(srcdir).relpathto(p) for p in path(srcdir).walkfiles()]
48 #print files
48 #print files
@@ -51,7 +51,7 b' def upgrade_dir(srcdir, tgtdir):'
51 rpt = pickle.load(rep.open())
51 rpt = pickle.load(rep.open())
52 except:
52 except:
53 rpt = {}
53 rpt = {}
54
54
55 for f in files:
55 for f in files:
56 if ignorable(f):
56 if ignorable(f):
57 continue
57 continue
@@ -59,7 +59,7 b' def upgrade_dir(srcdir, tgtdir):'
59 tgt = tgtdir / f
59 tgt = tgtdir / f
60 if not tgt.isfile():
60 if not tgt.isfile():
61 pr("Creating %s" % str(tgt))
61 pr("Creating %s" % str(tgt))
62
62
63 tgt.write_text(src.text())
63 tgt.write_text(src.text())
64 rpt[str(tgt)] = md5.new(tgt.text()).hexdigest()
64 rpt[str(tgt)] = md5.new(tgt.text()).hexdigest()
65 else:
65 else:
@@ -87,10 +87,8 b' def upgrade_dir(srcdir, tgtdir):'
87 print "\n\nDelete the following files manually (and rerun %upgrade)\nif you need a full upgrade:"
87 print "\n\nDelete the following files manually (and rerun %upgrade)\nif you need a full upgrade:"
88 for m in modded:
88 for m in modded:
89 print m
89 print m
90
90
91
91
92 import sys
92 import sys
93 if __name__ == "__main__":
93 if __name__ == "__main__":
94 upgrade_dir(path(sys.argv[1]), path(sys.argv[2]))
94 upgrade_dir(path(sys.argv[1]), path(sys.argv[2]))
95
96
General Comments 0
You need to be logged in to leave comments. Login now