templater: convert resources to a table of callables for future extension
I'm going to add a full templating support to the annotate command. As the
annotate is a filectx-oriented command, we'll need a way to look up a ctx
from a bounded fctx only when necessary.
This is the minimal change to support that. I'm thinking of defining a proper
interface to look up template resources to fix other issues, but that isn't
ready yet.
(Changes from V1: just updated tests and patch descriptions.)
--- a/mercurial/formatter.py Sat Mar 17 21:46:17 2018 -0400
+++ b/mercurial/formatter.py Sun Mar 11 21:05:29 2018 +0900
@@ -501,14 +501,23 @@
def templateresources(ui, repo=None):
"""Create a dict of template resources designed for the default templatekw
and function"""
- return {
+ resmap = {
'cache': {}, # for templatekw/funcs to store reusable data
- 'ctx': None,
'repo': repo,
- 'revcache': None, # per-ctx cache; set later
'ui': ui,
}
+ def getsome(context, mapping, key):
+ return resmap.get(key)
+
+ return {
+ 'cache': getsome,
+ 'ctx': getsome,
+ 'repo': getsome,
+ 'revcache': getsome, # per-ctx cache; set later
+ 'ui': getsome,
+ }
+
def formatter(ui, out, topic, opts):
template = opts.get("template", "")
if template == "json":
--- a/mercurial/logcmdutil.py Sat Mar 17 21:46:17 2018 -0400
+++ b/mercurial/logcmdutil.py Sun Mar 11 21:05:29 2018 +0900
@@ -423,7 +423,7 @@
resources=tres,
cache=templatekw.defaulttempl)
self._counter = itertools.count()
- self.cache = tres['cache'] # shared with _graphnodeformatter()
+ self._getcache = tres['cache'] # shared with _graphnodeformatter()
self._tref = tmplspec.ref
self._parts = {'header': '', 'footer': '',
@@ -852,7 +852,8 @@
spec = templater.unquotestring(spec)
tres = formatter.templateresources(ui)
if isinstance(displayer, changesettemplater):
- tres['cache'] = displayer.cache # reuse cache of slow templates
+ # reuse cache of slow templates
+ tres['cache'] = displayer._getcache
templ = formatter.maketemplater(ui, spec, defaults=templatekw.keywords,
resources=tres)
def formatnode(repo, ctx):
--- a/mercurial/templater.py Sat Mar 17 21:46:17 2018 -0400
+++ b/mercurial/templater.py Sun Mar 11 21:05:29 2018 +0900
@@ -566,8 +566,8 @@
v = None
if key in self._resources:
v = mapping.get(key)
- if v is None:
- v = self._resources.get(key)
+ if v is None and key in self._resources:
+ v = self._resources[key](self, mapping, key)
if v is None:
raise templateutil.ResourceUnavailable(
_('template resource not available: %s') % key)
@@ -670,8 +670,9 @@
- ``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 internal data (e.g. cache), inaccessible
- from user template; may be overridden by a ``mapping`` dict.
+ - ``resources``: a dict of functions returning internal data
+ (e.g. cache), inaccessible from user template; may be overridden by
+ a ``mapping`` dict.
- ``cache``: a dict of preloaded template fragments.
- ``aliases``: a list of alias (name, replacement) pairs.
@@ -691,7 +692,7 @@
self.filters = templatefilters.filters.copy()
self.filters.update(filters)
self.defaults = defaults
- self._resources = {'templ': self}
+ self._resources = {'templ': lambda context, mapping, key: self}
self._resources.update(resources)
self._aliases = aliases
self.minchunk, self.maxchunk = minchunk, maxchunk
--- a/mercurial/templateutil.py Sat Mar 17 21:46:17 2018 -0400
+++ b/mercurial/templateutil.py Sun Mar 11 21:05:29 2018 +0900
@@ -350,7 +350,8 @@
v = default
if callable(v) and getattr(v, '_requires', None) is None:
# old templatekw: expand all keywords and resources
- props = context._resources.copy()
+ props = {k: f(context, mapping, k)
+ for k, f in context._resources.items()}
props.update(mapping)
return v(**pycompat.strkwargs(props))
if callable(v):