# HG changeset patch # User Yuya Nishihara # Date 1521114219 -32400 # Node ID 44757e6dad9313784234182edc327c56526ef395 # Parent d64ae4fef4717f5b43e61504fd0970ae747c1b8a templater: introduce resourcemapper class A couple more functions will be added later to work around nested mapping bugs such as the issue 5612. diff -r d64ae4fef471 -r 44757e6dad93 mercurial/formatter.py --- a/mercurial/formatter.py Thu Mar 15 20:27:38 2018 +0900 +++ b/mercurial/formatter.py Thu Mar 15 20:43:39 2018 +0900 @@ -494,22 +494,32 @@ t.cache[''] = tmpl return t -def templateresources(ui, repo=None): - """Create a dict of template resources designed for the default templatekw - and function""" - resmap = { - 'cache': {}, # for templatekw/funcs to store reusable data - 'repo': repo, - 'ui': ui, - } +class templateresources(templater.resourcemapper): + """Resource mapper designed for the default templatekw and function""" + + def __init__(self, ui, repo=None): + self._resmap = { + 'cache': {}, # for templatekw/funcs to store reusable data + 'repo': repo, + 'ui': ui, + } - def getsome(context, mapping, key): + def knownkeys(self): + return self._knownkeys + + def lookup(self, context, mapping, key): + get = self._gettermap.get(key) + if not get: + return None + return get(self, context, mapping, key) + + def _getsome(self, context, mapping, key): v = mapping.get(key) if v is not None: return v - return resmap.get(key) + return self._resmap.get(key) - def getctx(context, mapping, key): + def _getctx(self, context, mapping, key): ctx = mapping.get('ctx') if ctx is not None: return ctx @@ -517,20 +527,21 @@ if fctx is not None: return fctx.changectx() - def getrepo(context, mapping, key): - ctx = getctx(context, mapping, 'ctx') + def _getrepo(self, context, mapping, key): + ctx = self._getctx(context, mapping, 'ctx') if ctx is not None: return ctx.repo() - return getsome(context, mapping, key) + return self._getsome(context, mapping, key) - return { - 'cache': getsome, - 'ctx': getctx, - 'fctx': getsome, - 'repo': getrepo, - 'revcache': getsome, # per-ctx cache; set later - 'ui': getsome, + _gettermap = { + 'cache': _getsome, + 'ctx': _getctx, + 'fctx': _getsome, + 'repo': _getrepo, + 'revcache': _getsome, # per-ctx cache; set later + 'ui': _getsome, } + _knownkeys = set(_gettermap.keys()) def formatter(ui, out, topic, opts): template = opts.get("template", "") diff -r d64ae4fef471 -r 44757e6dad93 mercurial/templater.py --- a/mercurial/templater.py Thu Mar 15 20:27:38 2018 +0900 +++ b/mercurial/templater.py Thu Mar 15 20:43:39 2018 +0900 @@ -48,6 +48,7 @@ from __future__ import absolute_import, print_function +import abc import os from .i18n import _ @@ -556,6 +557,26 @@ return s return s[1:-1] +class resourcemapper(object): + """Mapper of internal template resources""" + + __metaclass__ = abc.ABCMeta + + @abc.abstractmethod + def knownkeys(self): + """Return a set of supported resource keys""" + + @abc.abstractmethod + def lookup(self, context, mapping, key): + """Return a resource for the key if available; otherwise None""" + +class nullresourcemapper(resourcemapper): + def knownkeys(self): + return set() + + def lookup(self, context, mapping, key): + return None + class engine(object): '''template expansion engine. @@ -586,7 +607,7 @@ if defaults is None: defaults = {} if resources is None: - resources = {} + resources = nullresourcemapper() self._defaults = defaults self._resources = resources self._aliasmap = _aliasrules.buildmap(aliases) @@ -595,7 +616,7 @@ def symbol(self, mapping, key): """Resolve symbol to value or function; None if nothing found""" v = None - if key not in self._resources: + if key not in self._resources.knownkeys(): v = mapping.get(key) if v is None: v = self._defaults.get(key) @@ -604,9 +625,7 @@ def resource(self, mapping, key): """Return internal data (e.g. cache) used for keyword/function evaluation""" - v = None - if key in self._resources: - v = self._resources[key](self, mapping, key) + v = self._resources.lookup(self, mapping, key) if v is None: raise templateutil.ResourceUnavailable( _('template resource not available: %s') % key) @@ -717,7 +736,7 @@ - ``filters``: a dict of functions to transform a value into another. - ``defaults``: a dict of symbol values/functions; may be overridden by a ``mapping`` dict. - - ``resources``: a dict of functions returning internal data + - ``resources``: a resourcemapper object to look up internal data (e.g. cache), inaccessible from user template. - ``cache``: a dict of preloaded template fragments. - ``aliases``: a list of alias (name, replacement) pairs. @@ -729,8 +748,6 @@ filters = {} if defaults is None: defaults = {} - if resources is None: - resources = {} if cache is None: cache = {} self.cache = cache.copy() diff -r d64ae4fef471 -r 44757e6dad93 mercurial/templateutil.py --- a/mercurial/templateutil.py Thu Mar 15 20:27:38 2018 +0900 +++ b/mercurial/templateutil.py Thu Mar 15 20:43:39 2018 +0900 @@ -349,8 +349,8 @@ if callable(v) and getattr(v, '_requires', None) is None: # old templatekw: expand all keywords and resources # (TODO: deprecate this after porting web template keywords to new API) - props = {k: f(context, mapping, k) - for k, f in context._resources.items()} + props = {k: context._resources.lookup(context, mapping, k) + for k in context._resources.knownkeys()} # pass context to _showcompatlist() through templatekw._showlist() props['templ'] = context props.update(mapping)