##// END OF EJS Templates
fancyopts: add support for custom multi-arg opts in fancyopts.py...
Daniel Ploch -
r36373:cc9d0763 default
parent child Browse files
Show More
@@ -7,7 +7,9 b''
7 7
8 8 from __future__ import absolute_import
9 9
10 import abc
10 11 import functools
12 import types
11 13
12 14 from .i18n import _
13 15 from . import (
@@ -201,6 +203,64 b' def earlygetopt(args, shortlist, namelis'
201 203 parsedargs.extend(args[pos:])
202 204 return parsedopts, parsedargs
203 205
206 class customopt(object):
207 """Manage defaults and mutations for any type of opt."""
208
209 __metaclass__ = abc.ABCMeta
210
211 def __init__(self, defaultvalue):
212 self.defaultvalue = defaultvalue
213
214 def _isboolopt(self):
215 return False
216
217 @abc.abstractmethod
218 def newstate(self, oldstate, newparam, abort):
219 """Adds newparam to oldstate and returns the new state.
220
221 On failure, abort can be called with a string error message."""
222
223 class _simpleopt(customopt):
224 def _isboolopt(self):
225 return isinstance(self.defaultvalue, (bool, types.NoneType))
226
227 def newstate(self, oldstate, newparam, abort):
228 return newparam
229
230 class _callableopt(customopt):
231 def __init__(self, callablefn):
232 self.callablefn = callablefn
233 super(_callableopt, self).__init__(None)
234
235 def newstate(self, oldstate, newparam, abort):
236 return self.callablefn(newparam)
237
238 class _listopt(customopt):
239 def newstate(self, oldstate, newparam, abort):
240 oldstate.append(newparam)
241 return oldstate
242
243 class _intopt(customopt):
244 def newstate(self, oldstate, newparam, abort):
245 try:
246 return int(newparam)
247 except ValueError:
248 abort(_('expected int'))
249
250 def _defaultopt(default):
251 """Returns a default opt implementation, given a default value."""
252
253 if isinstance(default, customopt):
254 return default
255 elif callable(default):
256 return _callableopt(default)
257 elif isinstance(default, list):
258 return _listopt(default[:])
259 elif type(default) is type(1):
260 return _intopt(default)
261 else:
262 return _simpleopt(default)
263
204 264 def fancyopts(args, options, state, gnu=False, early=False, optaliases=None):
205 265 """
206 266 read args, parse options, and store options in state
@@ -220,6 +280,7 b' def fancyopts(args, options, state, gnu='
220 280 list - parameter string is added to a list
221 281 integer - parameter strings is stored as int
222 282 function - call function with parameter
283 customopt - subclass of 'customopt'
223 284
224 285 optaliases is a mapping from a canonical option name to a list of
225 286 additional long options. This exists for preserving backward compatibility
@@ -250,18 +311,13 b' def fancyopts(args, options, state, gnu='
250 311 argmap['-' + short] = name
251 312 for n in onames:
252 313 argmap['--' + n] = name
253 defmap[name] = default
314 defmap[name] = _defaultopt(default)
254 315
255 316 # copy defaults to state
256 if isinstance(default, list):
257 state[name] = default[:]
258 elif callable(default):
259 state[name] = None
260 else:
261 state[name] = default
317 state[name] = defmap[name].defaultvalue
262 318
263 319 # does it take a parameter?
264 if not (default is None or default is True or default is False):
320 if not defmap[name]._isboolopt():
265 321 if short:
266 322 short += ':'
267 323 onames = [n + '=' for n in onames]
@@ -301,21 +357,13 b' def fancyopts(args, options, state, gnu='
301 357 boolval = False
302 358 name = argmap[opt]
303 359 obj = defmap[name]
304 t = type(obj)
305 if callable(obj):
306 state[name] = defmap[name](val)
307 elif t is type(1):
308 try:
309 state[name] = int(val)
310 except ValueError:
311 raise error.Abort(_('invalid value %r for option %s, '
312 'expected int') % (val, opt))
313 elif t is type(''):
314 state[name] = val
315 elif t is type([]):
316 state[name].append(val)
317 elif t is type(None) or t is type(False):
360 if obj._isboolopt():
318 361 state[name] = boolval
362 else:
363 def abort(s):
364 raise error.Abort(
365 _('invalid value %r for option %s, %s') % (val, opt, s))
366 state[name] = defmap[name].newstate(state[name], val, abort)
319 367
320 368 # return unparsed args
321 369 return args
General Comments 0
You need to be logged in to leave comments. Login now