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 @@ -770,11 +770,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"""