Patchwork [2,of,3,V2] templater: use named function to expand template against mapping dict (API)

login
register
mail settings
Submitter Yuya Nishihara
Date March 19, 2018, 1:45 p.m.
Message ID <faaed935789fd2b36121.1521467104@mimosa>
Download mbox | patch
Permalink /patch/29620/
State Accepted
Headers show

Comments

Yuya Nishihara - March 19, 2018, 1:45 p.m.
# HG changeset patch
# User Yuya Nishihara <yuya@tcha.org>
# Date 1521203972 -32400
#      Fri Mar 16 21:39:32 2018 +0900
# Node ID faaed935789fd2b36121a5a5ec407d1cb694d48b
# Parent  75c311c2a72be114b791e0a6d4dd0d1cef20fa7b
templater: use named function to expand template against mapping dict (API)

And replace __call__(t, **mapping) in favor of generate(t, mapping). I prefer
a named function here since the templater isn't a simple function-like object.

.. api::

   The templater is no longer callable. Use ``templater.generate(t, mapping)``
   instead of ``templater(t, **pycompat.strkwargs(mapping))``.
via Mercurial-devel - March 19, 2018, 6:17 p.m.
On Mon, Mar 19, 2018 at 6:45 AM Yuya Nishihara <yuya@tcha.org> wrote:

> # HG changeset patch
> # User Yuya Nishihara <yuya@tcha.org>
> # Date 1521203972 -32400
> #      Fri Mar 16 21:39:32 2018 +0900
> # Node ID faaed935789fd2b36121a5a5ec407d1cb694d48b
> # Parent  75c311c2a72be114b791e0a6d4dd0d1cef20fa7b
> templater: use named function to expand template against mapping dict (API)
>

Queued, thanks.

Patch

diff --git a/mercurial/hgweb/hgweb_mod.py b/mercurial/hgweb/hgweb_mod.py
--- a/mercurial/hgweb/hgweb_mod.py
+++ b/mercurial/hgweb/hgweb_mod.py
@@ -198,7 +198,8 @@  class requestcontext(object):
 
     def sendtemplate(self, name, **kwargs):
         """Helper function to send a response generated from a template."""
-        self.res.setbodygen(self.tmpl(name, **kwargs))
+        kwargs = pycompat.byteskwargs(kwargs)
+        self.res.setbodygen(self.tmpl.generate(name, kwargs))
         return self.res.sendresponse()
 
 class hgweb(object):
diff --git a/mercurial/hgweb/hgwebdir_mod.py b/mercurial/hgweb/hgwebdir_mod.py
--- a/mercurial/hgweb/hgwebdir_mod.py
+++ b/mercurial/hgweb/hgwebdir_mod.py
@@ -452,12 +452,12 @@  class hgwebdir(object):
 
             # prefixes not found
             res.status = '404 Not Found'
-            res.setbodygen(tmpl('notfound', repo=virtual))
+            res.setbodygen(tmpl.generate('notfound', {'repo': virtual}))
             return res.sendresponse()
 
         except ErrorResponse as e:
             res.status = statusmessage(e.code, pycompat.bytestr(e))
-            res.setbodygen(tmpl('error', error=e.message or ''))
+            res.setbodygen(tmpl.generate('error', {'error': e.message or ''}))
             return res.sendresponse()
         finally:
             tmpl = None
@@ -485,15 +485,15 @@  class hgwebdir(object):
                                self.stripecount, sortcolumn=sortcolumn,
                                descending=descending, subdir=subdir)
 
-        res.setbodygen(tmpl(
-            'index',
-            entries=entries,
-            subdir=subdir,
-            pathdef=hgweb_mod.makebreadcrumb('/' + subdir, self.prefix),
-            sortcolumn=sortcolumn,
-            descending=descending,
-            **dict(sort)))
-
+        mapping = {
+            'entries': entries,
+            'subdir': subdir,
+            'pathdef': hgweb_mod.makebreadcrumb('/' + subdir, self.prefix),
+            'sortcolumn': sortcolumn,
+            'descending': descending,
+        }
+        mapping.update(sort)
+        res.setbodygen(tmpl.generate('index', mapping))
         return res.sendresponse()
 
     def templater(self, req, nonce):
diff --git a/mercurial/hgweb/webcommands.py b/mercurial/hgweb/webcommands.py
--- a/mercurial/hgweb/webcommands.py
+++ b/mercurial/hgweb/webcommands.py
@@ -294,12 +294,13 @@  def _search(web):
             files = webutil.listfilediffs(web.tmpl, ctx.files(), n,
                                           web.maxfiles)
 
-            yield web.tmpl(
-                'searchentry',
-                parity=next(parity),
-                changelogtag=showtags,
-                files=files,
-                **pycompat.strkwargs(webutil.commonentry(web.repo, ctx)))
+            lm = webutil.commonentry(web.repo, ctx)
+            lm.update({
+                'parity': next(parity),
+                'changelogtag': showtags,
+                'files': files,
+            })
+            yield web.tmpl.generate('searchentry', lm)
 
             if count >= revcount:
                 break
@@ -719,12 +720,12 @@  def summary(web):
             if count > 10: # limit to 10 tags
                 break
 
-            yield web.tmpl(
-                'tagentry',
-                parity=next(parity),
-                tag=k,
-                node=hex(n),
-                date=web.repo[n].date())
+            yield web.tmpl.generate('tagentry', {
+                'parity': next(parity),
+                'tag': k,
+                'node': hex(n),
+                'date': web.repo[n].date(),
+            })
 
     def bookmarks(**map):
         parity = paritygen(web.stripecount)
@@ -745,11 +746,9 @@  def summary(web):
             revs = web.repo.changelog.revs(start, end - 1)
         for i in revs:
             ctx = web.repo[i]
-
-            l.append(web.tmpl(
-                'shortlogentry',
-                parity=next(parity),
-                **pycompat.strkwargs(webutil.commonentry(web.repo, ctx))))
+            lm = webutil.commonentry(web.repo, ctx)
+            lm['parity'] = next(parity)
+            l.append(web.tmpl.generate('shortlogentry', lm))
 
         for entry in reversed(l):
             yield entry
diff --git a/mercurial/hgweb/webutil.py b/mercurial/hgweb/webutil.py
--- a/mercurial/hgweb/webutil.py
+++ b/mercurial/hgweb/webutil.py
@@ -243,12 +243,18 @@  def nodebranchnodefault(ctx):
     return branches
 
 def showtag(repo, tmpl, t1, node=nullid, **args):
+    args = pycompat.byteskwargs(args)
     for t in repo.nodetags(node):
-        yield tmpl(t1, tag=t, **args)
+        lm = args.copy()
+        lm['tag'] = t
+        yield tmpl.generate(t1, lm)
 
 def showbookmark(repo, tmpl, t1, node=nullid, **args):
+    args = pycompat.byteskwargs(args)
     for t in repo.nodebookmarks(node):
-        yield tmpl(t1, bookmark=t, **args)
+        lm = args.copy()
+        lm['bookmark'] = t
+        yield tmpl.generate(t1, lm)
 
 def branchentries(repo, stripecount, limit=0):
     tips = []
@@ -443,9 +449,12 @@  def changesetentry(web, ctx):
     parity = paritygen(web.stripecount)
     for blockno, f in enumerate(ctx.files()):
         template = 'filenodelink' if f in ctx else 'filenolink'
-        files.append(web.tmpl(template,
-                              node=ctx.hex(), file=f, blockno=blockno + 1,
-                              parity=next(parity)))
+        files.append(web.tmpl.generate(template, {
+            'node': ctx.hex(),
+            'file': f,
+            'blockno': blockno + 1,
+            'parity': next(parity),
+        }))
 
     basectx = basechangectx(web.repo, web.req)
     if basectx is None:
@@ -476,9 +485,9 @@  def changesetentry(web, ctx):
 
 def listfilediffs(tmpl, files, node, max):
     for f in files[:max]:
-        yield tmpl('filedifflink', node=hex(node), file=f)
+        yield tmpl.generate('filedifflink', {'node': hex(node), 'file': f})
     if len(files) > max:
-        yield tmpl('fileellipses')
+        yield tmpl.generate('fileellipses', {})
 
 def diffs(web, ctx, basectx, files, style, linerange=None,
           lineidprefix=''):
@@ -494,12 +503,12 @@  def diffs(web, ctx, basectx, files, styl
                 ltype = "difflineat"
             else:
                 ltype = "diffline"
-            yield web.tmpl(
-                ltype,
-                line=l,
-                lineno=lineno,
-                lineid=lineidprefix + "l%s" % difflineno,
-                linenumber="% 8s" % difflineno)
+            yield web.tmpl.generate(ltype, {
+                'line': l,
+                'lineno': lineno,
+                'lineid': lineidprefix + "l%s" % difflineno,
+                'linenumber': "% 8s" % difflineno,
+            })
 
     repo = web.repo
     if files:
@@ -524,8 +533,11 @@  def diffs(web, ctx, basectx, files, styl
                     continue
             lines.extend(hunklines)
         if lines:
-            yield web.tmpl('diffblock', parity=next(parity), blockno=blockno,
-                           lines=prettyprintlines(lines, blockno))
+            yield web.tmpl.generate('diffblock', {
+                'parity': next(parity),
+                'blockno': blockno,
+                'lines': prettyprintlines(lines, blockno),
+            })
 
 def compare(tmpl, context, leftlines, rightlines):
     '''Generator function that provides side-by-side comparison data.'''
@@ -535,15 +547,16 @@  def compare(tmpl, context, leftlines, ri
         lineid += rightlineno and ("r%d" % rightlineno) or ''
         llno = '%d' % leftlineno if leftlineno else ''
         rlno = '%d' % rightlineno if rightlineno else ''
-        return tmpl('comparisonline',
-                    type=type,
-                    lineid=lineid,
-                    leftlineno=leftlineno,
-                    leftlinenumber="% 6s" % llno,
-                    leftline=leftline or '',
-                    rightlineno=rightlineno,
-                    rightlinenumber="% 6s" % rlno,
-                    rightline=rightline or '')
+        return tmpl.generate('comparisonline', {
+            'type': type,
+            'lineid': lineid,
+            'leftlineno': leftlineno,
+            'leftlinenumber': "% 6s" % llno,
+            'leftline': leftline or '',
+            'rightlineno': rightlineno,
+            'rightlinenumber': "% 6s" % rlno,
+            'rightline': rightline or '',
+        })
 
     def getblock(opcodes):
         for type, llo, lhi, rlo, rhi in opcodes:
@@ -573,10 +586,11 @@  def compare(tmpl, context, leftlines, ri
 
     s = difflib.SequenceMatcher(None, leftlines, rightlines)
     if context < 0:
-        yield tmpl('comparisonblock', lines=getblock(s.get_opcodes()))
+        yield tmpl.generate('comparisonblock',
+                            {'lines': getblock(s.get_opcodes())})
     else:
         for oc in s.get_grouped_opcodes(n=context):
-            yield tmpl('comparisonblock', lines=getblock(oc))
+            yield tmpl.generate('comparisonblock', {'lines': getblock(oc)})
 
 def diffstatgen(ctx, basectx):
     '''Generator function that provides the diffstat data.'''
@@ -610,9 +624,15 @@  def diffstat(tmpl, ctx, statgen, parity)
         template = 'diffstatlink' if filename in files else 'diffstatnolink'
         total = adds + removes
         fileno += 1
-        yield tmpl(template, node=ctx.hex(), file=filename, fileno=fileno,
-                   total=total, addpct=pct(adds), removepct=pct(removes),
-                   parity=next(parity))
+        yield tmpl.generate(template, {
+            'node': ctx.hex(),
+            'file': filename,
+            'fileno': fileno,
+            'total': total,
+            'addpct': pct(adds),
+            'removepct': pct(removes),
+            'parity': next(parity),
+        })
 
 class sessionvars(object):
     def __init__(self, vars, start='?'):
diff --git a/mercurial/templatekw.py b/mercurial/templatekw.py
--- a/mercurial/templatekw.py
+++ b/mercurial/templatekw.py
@@ -478,7 +478,7 @@  def showmanifest(context, mapping):
     mhex = hex(mnode)
     mapping = mapping.copy()
     mapping.update({'rev': mrev, 'node': mhex})
-    f = templ('manifest', **pycompat.strkwargs(mapping))
+    f = templ.generate('manifest', mapping)
     # 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})
diff --git a/mercurial/templater.py b/mercurial/templater.py
--- a/mercurial/templater.py
+++ b/mercurial/templater.py
@@ -729,11 +729,11 @@  class templater(object):
 
     def render(self, t, mapping):
         """Render the specified named template and return result as string"""
-        mapping = pycompat.strkwargs(mapping)
-        return templateutil.stringify(self(t, **mapping))
+        return templateutil.stringify(self.generate(t, mapping))
 
-    def __call__(self, t, **mapping):
-        mapping = pycompat.byteskwargs(mapping)
+    def generate(self, t, mapping):
+        """Return a generator that renders the specified named template and
+        yields chunks"""
         ttype = t in self.map and self.map[t][0] or 'default'
         if ttype not in self.ecache:
             try:
diff --git a/mercurial/templateutil.py b/mercurial/templateutil.py
--- a/mercurial/templateutil.py
+++ b/mercurial/templateutil.py
@@ -184,13 +184,12 @@  def _showlist(name, values, templ, mappi
 
     expand 'end_foos'.
     '''
-    strmapping = pycompat.strkwargs(mapping)
     if not plural:
         plural = name + 's'
     if not values:
         noname = 'no_' + plural
         if noname in templ:
-            yield templ(noname, **strmapping)
+            yield templ.generate(noname, mapping)
         return
     if name not in templ:
         if isinstance(values[0], bytes):
@@ -203,7 +202,7 @@  def _showlist(name, values, templ, mappi
         return
     startname = 'start_' + plural
     if startname in templ:
-        yield templ(startname, **strmapping)
+        yield templ.generate(startname, mapping)
     vmapping = mapping.copy()
     def one(v, tag=name):
         try:
@@ -218,7 +217,7 @@  def _showlist(name, values, templ, mappi
                     vmapping[a] = b
             except (TypeError, ValueError):
                 vmapping[name] = v
-        return templ(tag, **pycompat.strkwargs(vmapping))
+        return templ.generate(tag, vmapping)
     lastname = 'last_' + name
     if lastname in templ:
         last = values.pop()
@@ -230,7 +229,7 @@  def _showlist(name, values, templ, mappi
         yield one(last, tag=lastname)
     endname = 'end_' + plural
     if endname in templ:
-        yield templ(endname, **strmapping)
+        yield templ.generate(endname, mapping)
 
 def stringify(thing):
     """Turn values into bytes by converting into text and concatenating them"""