Mercurial > public > mercurial-scm > hg-stable
diff mercurial/templateutil.py @ 38255:06d11cd90516
templater: promote getmember() to an interface of wrapped types
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Wed, 21 Mar 2018 11:30:21 +0900 |
parents | 12b6ee9e88f3 |
children | 688fbb758ba9 |
line wrap: on
line diff
--- a/mercurial/templateutil.py Wed Mar 21 01:39:44 2018 +0900 +++ b/mercurial/templateutil.py Wed Mar 21 11:30:21 2018 +0900 @@ -38,6 +38,14 @@ __metaclass__ = abc.ABCMeta @abc.abstractmethod + def getmember(self, context, mapping, key): + """Return a member item for the specified key + + A returned object may be either a wrapped object or a pure value + depending on the self type. + """ + + @abc.abstractmethod def itermaps(self, context): """Yield each template mapping""" @@ -72,6 +80,10 @@ def __init__(self, value): self._value = value + def getmember(self, context, mapping, key): + raise error.ParseError(_('%r is not a dictionary') + % pycompat.bytestr(self._value)) + def itermaps(self, context): raise error.ParseError(_('%r is not iterable of mappings') % pycompat.bytestr(self._value)) @@ -91,6 +103,9 @@ def __init__(self, value): self._value = value + def getmember(self, context, mapping, key): + raise error.ParseError(_('%r is not a dictionary') % self._value) + def itermaps(self, context): raise error.ParseError(_('%r is not iterable of mappings') % self._value) @@ -196,6 +211,10 @@ def tomap(self): return self._makemap(self._key) + def getmember(self, context, mapping, key): + w = makewrapped(context, mapping, self._value) + return w.getmember(context, mapping, key) + def itermaps(self, context): yield self.tomap() @@ -231,6 +250,9 @@ self._tmpl = tmpl self._defaultsep = sep + def getmember(self, context, mapping, key): + raise error.ParseError(_('not a dictionary')) + def join(self, context, mapping, sep): mapsiter = _iteroverlaymaps(context, mapping, self.itermaps(context)) if self._name: @@ -294,6 +316,9 @@ def _gen(self, context): return self._make(context, *self._args) + def getmember(self, context, mapping, key): + raise error.ParseError(_('not a dictionary')) + def itermaps(self, context): raise error.ParseError(_('list of strings is not mappable')) @@ -678,15 +703,13 @@ lm = context.overlaymap(mapping, d.tomap()) return runsymbol(context, lm, memb) try: - if util.safehasattr(d, 'getmember'): - return d.getmember(context, mapping, memb) - raise error.ParseError - except error.ParseError: + return d.getmember(context, mapping, memb) + except error.ParseError as err: sym = findsymbolicname(darg) - if sym: - raise error.ParseError(_("keyword '%s' has no member") % sym) - else: - raise error.ParseError(_("%r has no member") % pycompat.bytestr(d)) + if not sym: + raise + hint = _("keyword '%s' does not support member operation") % sym + raise error.ParseError(bytes(err), hint=hint) def runnegate(context, mapping, data): data = evalinteger(context, mapping, data,