From patchwork Sat Mar 24 03:07:50 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: D2937: fancyopts: prevent mutation of the default value in customopts From: phabricator X-Patchwork-Id: 29805 Message-Id: To: mercurial-devel@mercurial-scm.org Date: Sat, 24 Mar 2018 03:07:50 +0000 This revision was automatically updated to reflect the committed changes. Closed by commit rHGef6215df2402: fancyopts: prevent mutation of the default value in customopts (authored by dploch, committed by ). CHANGED PRIOR TO COMMIT https://phab.mercurial-scm.org/D2937?vs=7258&id=7264#toc REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2937?vs=7258&id=7264 REVISION DETAIL https://phab.mercurial-scm.org/D2937 AFFECTED FILES mercurial/fancyopts.py mercurial/help.py CHANGE DETAILS To: dploch, #hg-reviewers, yuja Cc: mercurial-devel diff --git a/mercurial/help.py b/mercurial/help.py --- a/mercurial/help.py +++ b/mercurial/help.py @@ -87,7 +87,7 @@ lo = '--' + longopt if isinstance(default, fancyopts.customopt): - default = default.defaultvalue + default = default.getdefaultvalue() if default and not callable(default): # default is of unknown type, and in Python 2 we abused # the %s-shows-repr property to handle integers etc. To diff --git a/mercurial/fancyopts.py b/mercurial/fancyopts.py --- a/mercurial/fancyopts.py +++ b/mercurial/fancyopts.py @@ -208,20 +208,27 @@ __metaclass__ = abc.ABCMeta def __init__(self, defaultvalue): - self.defaultvalue = defaultvalue + self._defaultvalue = defaultvalue def _isboolopt(self): return False + def getdefaultvalue(self): + """Returns the default value for this opt. + + Subclasses should override this to return a new value if the value type + is mutable.""" + return self._defaultvalue + @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, type(None))) + return isinstance(self._defaultvalue, (bool, type(None))) def newstate(self, oldstate, newparam, abort): return newparam @@ -235,6 +242,9 @@ return self.callablefn(newparam) class _listopt(customopt): + def getdefaultvalue(self): + return self._defaultvalue[:] + def newstate(self, oldstate, newparam, abort): oldstate.append(newparam) return oldstate @@ -313,7 +323,7 @@ defmap[name] = _defaultopt(default) # copy defaults to state - state[name] = defmap[name].defaultvalue + state[name] = defmap[name].getdefaultvalue() # does it take a parameter? if not defmap[name]._isboolopt():