D2090: fancyopts: add support for custom multi-arg opts in fancyopts.py
dploch (Daniel Ploch)
phabricator at mercurial-scm.org
Wed Feb 21 22:26:02 EST 2018
dploch updated this revision to Diff 5981.
dploch marked 4 inline comments as done.
REPOSITORY
rHG Mercurial
CHANGES SINCE LAST UPDATE
https://phab.mercurial-scm.org/D2090?vs=5330&id=5981
REVISION DETAIL
https://phab.mercurial-scm.org/D2090
AFFECTED FILES
mercurial/fancyopts.py
CHANGE DETAILS
diff --git a/mercurial/fancyopts.py b/mercurial/fancyopts.py
--- a/mercurial/fancyopts.py
+++ b/mercurial/fancyopts.py
@@ -7,7 +7,9 @@
from __future__ import absolute_import
+import abc
import functools
+import types
from .i18n import _
from . import (
@@ -201,6 +203,65 @@
parsedargs.extend(args[pos:])
return parsedopts, parsedargs
+class customopt(object):
+ """Manage defaults and mutations for any type of opt."""
+
+ __metaclass__ = abc.ABCMeta
+
+ def __init__(self, defaultvalue):
+ self.defaultvalue = defaultvalue
+
+ def _isboolopt(self):
+ return False
+
+ @abc.abstractmethod
+ def newstate(self, oldstate, newparam, abort):
+ """Adds newparam to oldstate and returns the new state.
+
+ On failure, abort can be called with a string error message."""
+
+class _simpleopt(customopt):
+ def _isboolopt(self):
+ return isinstance(self.defaultvalue, (bool, types.NoneType))
+
+ def newstate(self, oldstate, newparam, abort):
+ return newparam
+
+class _callableopt(customopt):
+ def __init__(self, callablefn):
+ self.callablefn = callablefn
+ super(_callableopt, self).__init__(None)
+
+ def newstate(self, oldstate, newparam, abort):
+ return self.callablefn(newparam)
+
+class _listopt(customopt):
+ def newstate(self, oldstate, newparam, abort):
+ oldstate.append(newparam)
+ return oldstate
+
+class _intopt(customopt):
+ def newstate(self, oldstate, newparam, abort):
+ try:
+ return int(newparam)
+ except ValueError:
+ abort(_('expected int'))
+
+def _defaultopt(default):
+ """Returns a default opt implementation, given a default value."""
+
+ if isinstance(default, customopt):
+ return default
+ elif callable(default):
+ return _callableopt(default)
+ elif isinstance(default, list):
+ return _listopt(default[:])
+ # isinstance(True, int) returns True for some reason.
+ elif isinstance(default, (int, long)) and not isinstance(default, bool):
+ return _intopt(default)
+ else:
+ return _simpleopt(default)
+
def fancyopts(args, options, state, gnu=False, early=False, optaliases=None):
"""
read args, parse options, and store options in state
@@ -220,6 +281,7 @@
list - parameter string is added to a list
integer - parameter strings is stored as int
function - call function with parameter
+ customopt - subclass of 'customopt'
optaliases is a mapping from a canonical option name to a list of
additional long options. This exists for preserving backward compatibility
@@ -250,18 +312,13 @@
argmap['-' + short] = name
for n in onames:
argmap['--' + n] = name
- defmap[name] = default
+ defmap[name] = _defaultopt(default)
# copy defaults to state
- if isinstance(default, list):
- state[name] = default[:]
- elif callable(default):
- state[name] = None
- else:
- state[name] = default
+ state[name] = defmap[name].defaultvalue
# does it take a parameter?
- if not (default is None or default is True or default is False):
+ if not defmap[name]._isboolopt():
if short:
short += ':'
onames = [n + '=' for n in onames]
@@ -301,21 +358,13 @@
boolval = False
name = argmap[opt]
obj = defmap[name]
- t = type(obj)
- if callable(obj):
- state[name] = defmap[name](val)
- elif t is type(1):
- try:
- state[name] = int(val)
- except ValueError:
- raise error.Abort(_('invalid value %r for option %s, '
- 'expected int') % (val, opt))
- elif t is type(''):
- state[name] = val
- elif t is type([]):
- state[name].append(val)
- elif t is type(None) or t is type(False):
+ if obj._isboolopt():
state[name] = boolval
+ else:
+ def abort(s):
+ raise error.Abort(
+ _('invalid value %r for option %s, %s') % (val, opt, s))
+ state[name] = defmap[name].newstate(state[name], val, abort)
# return unparsed args
return args
To: dploch, #hg-reviewers, durin42, indygreg
Cc: durin42, indygreg, mercurial-devel
More information about the Mercurial-devel
mailing list