Patchwork [5,of,5] templater: hide resources by naming rule (API)

login
register
mail settings
Submitter Yuya Nishihara
Date March 14, 2018, 2:27 p.m.
Message ID <2a9f0d2579cdabe0c947.1521037658@mimosa>
Download mbox | patch
Permalink /patch/29496/
State Superseded
Headers show

Comments

Yuya Nishihara - March 14, 2018, 2:27 p.m.
# HG changeset patch
# User Yuya Nishihara <yuya@tcha.org>
# Date 1521029431 -32400
#      Wed Mar 14 21:10:31 2018 +0900
# Node ID 2a9f0d2579cdabe0c94725c52c567e26701479ad
# Parent  94780b04daec618e289ac7bffac170d89330f94d
templater: hide resources by naming rule (API)

Instead of overloading resource names with symbols, this patch makes all
internal data prefixed with '_'. I think this is less bad.

props['_revcache'] is unconditionally set by the formatter, as the
resources/symbols namespace is semi-isolated now.

.. api::

   Template keyword that switches a ctx object must generate _-prefixed names
   (e.g. ``{'_ctx': ctx, '_revcache': {}}``) instead of ``{'ctx': ctx, ...}``.
Yuya Nishihara - March 15, 2018, 1:41 p.m.
On Wed, 14 Mar 2018 23:27:38 +0900, Yuya Nishihara wrote:
> # HG changeset patch
> # User Yuya Nishihara <yuya@tcha.org>
> # Date 1521029431 -32400
> #      Wed Mar 14 21:10:31 2018 +0900
> # Node ID 2a9f0d2579cdabe0c94725c52c567e26701479ad
> # Parent  94780b04daec618e289ac7bffac170d89330f94d
> templater: hide resources by naming rule (API)

Please disregard the last patch. I'll include it in the next series fixing
more templater issues.

Patch

diff --git a/hgext/show.py b/hgext/show.py
--- a/hgext/show.py
+++ b/hgext/show.py
@@ -260,7 +260,7 @@  def showstack(ui, repo, displayer):
     shortesttmpl = formatter.maketemplater(ui, '{shortest(node, %d)}' % nodelen,
                                            resources=tres)
     def shortest(ctx):
-        return shortesttmpl.render({'ctx': ctx, 'node': ctx.hex()})
+        return shortesttmpl.render({'_ctx': ctx, 'node': ctx.hex()})
 
     # We write out new heads to aid in DAG awareness and to help with decision
     # making on how the stack should be reconciled with commits made since the
diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -903,7 +903,7 @@  def rendertemplate(ctx, tmpl, props=None
     tres = formatter.templateresources(repo.ui, repo)
     t = formatter.maketemplater(repo.ui, tmpl, defaults=templatekw.keywords,
                                 resources=tres)
-    mapping = {'ctx': ctx, 'revcache': {}}
+    mapping = {'_ctx': ctx, '_revcache': {}}
     if props:
         mapping.update(props)
     return t.render(mapping)
diff --git a/mercurial/filemerge.py b/mercurial/filemerge.py
--- a/mercurial/filemerge.py
+++ b/mercurial/filemerge.py
@@ -562,7 +562,7 @@  def _formatconflictmarker(ctx, template,
     if ctx.node() is None:
         ctx = ctx.p1()
 
-    props = {'ctx': ctx}
+    props = {'_ctx': ctx}
     templateresult = template.render(props)
 
     label = ('%s:' % label).ljust(pad + 1)
diff --git a/mercurial/formatter.py b/mercurial/formatter.py
--- a/mercurial/formatter.py
+++ b/mercurial/formatter.py
@@ -190,7 +190,7 @@  class baseformatter(object):
         ctxs = pycompat.byteskwargs(ctxs)
         assert all(k in {'ctx', 'fctx'} for k in ctxs)
         if self._converter.storecontext:
-            self._item.update(ctxs)
+            self._item.update(('_' + k, v) for k, v in ctxs.items())
     def data(self, **data):
         '''insert data into item that's not shown in default output'''
         data = pycompat.byteskwargs(data)
@@ -395,12 +395,8 @@  class templateformatter(baseformatter):
             return
         ref = self._parts[part]
 
-        props = {}
-        # explicitly-defined fields precede templatekw
-        props.update(item)
-        if 'ctx' in item or 'fctx' in item:
-            # but template resources must be always available
-            props['revcache'] = {}
+        props = item.copy()
+        props['_revcache'] = {}
         props = pycompat.strkwargs(props)
         g = self._t(ref, **props)
         self._out.write(templateutil.stringify(g))
@@ -506,16 +502,16 @@  def templateresources(ui, repo=None):
     }
 
     def getsome(context, mapping, key):
-        v = mapping.get(key)
+        v = mapping.get('_' + key)
         if v is not None:
             return v
         return resmap.get(key)
 
     def getctx(context, mapping, key):
-        ctx = mapping.get('ctx')
+        ctx = mapping.get('_ctx')
         if ctx is not None:
             return ctx
-        fctx = mapping.get('fctx')
+        fctx = mapping.get('_fctx')
         if fctx is not None:
             return fctx.changectx()
 
diff --git a/mercurial/hgweb/webutil.py b/mercurial/hgweb/webutil.py
--- a/mercurial/hgweb/webutil.py
+++ b/mercurial/hgweb/webutil.py
@@ -368,8 +368,8 @@  def commonentry(repo, ctx):
         # TODO: perhaps ctx.changectx() should be assigned if ctx is a
         # filectx, but I'm not pretty sure if that would always work because
         # fctx.parents() != fctx.changectx.parents() for example.
-        'ctx': ctx,
-        'revcache': {},
+        '_ctx': ctx,
+        '_revcache': {},
         'rev': ctx.rev(),
         'node': hex(node),
         'author': ctx.user(),
diff --git a/mercurial/logcmdutil.py b/mercurial/logcmdutil.py
--- a/mercurial/logcmdutil.py
+++ b/mercurial/logcmdutil.py
@@ -285,7 +285,7 @@  class changesetprinter(object):
         t = formatter.maketemplater(self.repo.ui, '{join(obsfate, "\n")}',
                                     defaults=templatekw.keywords,
                                     resources=tres)
-        obsfate = t.render({'ctx': ctx, 'revcache': {}}).splitlines()
+        obsfate = t.render({'_ctx': ctx, '_revcache': {}}).splitlines()
 
         if obsfate:
             for obsfateline in obsfate:
@@ -464,9 +464,9 @@  class changesettemplater(changesetprinte
     def _show(self, ctx, copies, props):
         '''show a single changeset or file revision'''
         props = props.copy()
-        props['ctx'] = ctx
+        props['_ctx'] = ctx
+        props['_revcache'] = {'copies': copies}
         props['index'] = index = next(self._counter)
-        props['revcache'] = {'copies': copies}
         props = pycompat.strkwargs(props)
 
         # write separator, which wouldn't work well with the header part below
@@ -857,7 +857,7 @@  def _graphnodeformatter(ui, displayer):
     templ = formatter.maketemplater(ui, spec, defaults=templatekw.keywords,
                                     resources=tres)
     def formatnode(repo, ctx):
-        props = {'ctx': ctx, 'repo': repo, 'revcache': {}}
+        props = {'_ctx': ctx, '_repo': repo, '_revcache': {}}
         return templ.render(props)
     return formatnode
 
diff --git a/mercurial/templatekw.py b/mercurial/templatekw.py
--- a/mercurial/templatekw.py
+++ b/mercurial/templatekw.py
@@ -479,7 +479,7 @@  def showmanifest(context, mapping):
     mapping = mapping.copy()
     mapping.update({'rev': mrev, 'node': mhex})
     f = templ('manifest', **pycompat.strkwargs(mapping))
-    # TODO: perhaps 'ctx' should be dropped from mapping because manifest
+    # TODO: perhaps '_ctx' should be dropped from mapping because manifest
     # rev and node are completely different from changeset's.
     return _mappable(f, None, f, lambda x: {'rev': mrev, 'node': mhex})
 
@@ -578,7 +578,7 @@  def showpredecessors(context, mapping):
     predecessors = map(hex, predecessors)
 
     return _hybrid(None, predecessors,
-                   lambda x: {'ctx': repo[x], 'revcache': {}},
+                   lambda x: {'_ctx': repo[x], '_revcache': {}},
                    lambda x: scmutil.formatchangeid(repo[x]))
 
 @templatekeyword('reporoot', requires={'repo'})
@@ -602,7 +602,7 @@  def showsuccessorssets(context, mapping)
 
     data = []
     for ss in ssets:
-        h = _hybrid(None, ss, lambda x: {'ctx': repo[x], 'revcache': {}},
+        h = _hybrid(None, ss, lambda x: {'_ctx': repo[x], '_revcache': {}},
                     lambda x: scmutil.formatchangeid(repo[x]))
         data.append(h)
 
@@ -643,7 +643,7 @@  def showsuccsandmarkers(context, mapping
 
         successors = [hex(n) for n in successors]
         successors = _hybrid(None, successors,
-                             lambda x: {'ctx': repo[x], 'revcache': {}},
+                             lambda x: {'_ctx': repo[x], '_revcache': {}},
                              lambda x: scmutil.formatchangeid(repo[x]))
 
         # Format markers
@@ -707,7 +707,7 @@  def showparents(context, mapping):
                 ('phase', p.phasestr())]
                for p in pctxs]
     f = _showlist('parent', parents, templ, mapping)
-    return _hybrid(f, prevs, lambda x: {'ctx': repo[x], 'revcache': {}},
+    return _hybrid(f, prevs, lambda x: {'_ctx': repo[x], '_revcache': {}},
                    lambda x: scmutil.formatchangeid(repo[x]), keytype=int)
 
 @templatekeyword('phase', requires={'ctx'})
@@ -735,7 +735,7 @@  def showrevslist(context, mapping, name,
     templ = context.resource(mapping, 'templ')
     f = _showlist(name, ['%d' % r for r in revs], templ, mapping)
     return _hybrid(f, revs,
-                   lambda x: {name: x, 'ctx': repo[x], 'revcache': {}},
+                   lambda x: {name: x, '_ctx': repo[x], '_revcache': {}},
                    pycompat.identity, keytype=int)
 
 @templatekeyword('subrepos', requires={'ctx', 'templ'})
diff --git a/mercurial/templater.py b/mercurial/templater.py
--- a/mercurial/templater.py
+++ b/mercurial/templater.py
@@ -554,7 +554,7 @@  class engine(object):
     def symbol(self, mapping, key):
         """Resolve symbol to value or function; None if nothing found"""
         v = None
-        if key not in self._resources:
+        if not key.startswith('_'):
             v = mapping.get(key)
         if v is None:
             v = self._defaults.get(key)
diff --git a/tests/test-command-template.t b/tests/test-command-template.t
--- a/tests/test-command-template.t
+++ b/tests/test-command-template.t
@@ -207,6 +207,7 @@  never cause crash:
 Internal resources shouldn't be exposed (issue5699):
 
   $ hg log -r. -T '{cache}{ctx}{repo}{revcache}{templ}{ui}'
+  $ hg log -r. -T '{_cache}{_ctx}{_repo}{_revcache}{_templ}{_ui}'
 
 Never crash on internal resource not available:
 
diff --git a/tests/test-template-engine.t b/tests/test-template-engine.t
--- a/tests/test-template-engine.t
+++ b/tests/test-template-engine.t
@@ -26,7 +26,7 @@ 
   >         props = self._defaults.copy()
   >         props.update(map)
   >         for k, v in props.items():
-  >             if k in ('templ', 'ctx', 'repo', 'revcache', 'cache', 'troubles'):
+  >             if k.startswith('_'):
   >                 continue
   >             if callable(v) and getattr(v, '_requires', None) is None:
   >                 props = self._resources.copy()