templater: extract helper to just evaluate template expression
authorYuya Nishihara <yuya@tcha.org>
Sat, 02 Sep 2017 23:13:54 +0900
changeset 34326 e60c601953d7
parent 34325 86d050abd5c1
child 34327 4647e0a8d3d7
templater: extract helper to just evaluate template expression A named function can be easily grepped and is probably good for code readability.
mercurial/templater.py
--- a/mercurial/templater.py	Sat Sep 02 23:09:34 2017 +0900
+++ b/mercurial/templater.py	Sat Sep 02 23:13:54 2017 +0900
@@ -298,11 +298,17 @@
         else:
             return None
 
-def evalfuncarg(context, mapping, arg):
+def evalrawexp(context, mapping, arg):
+    """Evaluate given argument as a bare template object which may require
+    further processing (such as folding generator of strings)"""
     func, data = arg
-    # func() may return string, generator of strings or arbitrary object such
-    # as date tuple, but filter does not want generator.
-    thing = func(context, mapping, data)
+    return func(context, mapping, data)
+
+def evalfuncarg(context, mapping, arg):
+    """Evaluate given argument as value type"""
+    thing = evalrawexp(context, mapping, arg)
+    # evalrawexp() may return string, generator of strings or arbitrary object
+    # such as date tuple, but filter does not want generator.
     if isinstance(thing, types.GeneratorType):
         thing = stringify(thing)
     return thing
@@ -331,8 +337,7 @@
         raise error.ParseError(err)
 
 def evalstring(context, mapping, arg):
-    func, data = arg
-    return stringify(func(context, mapping, data))
+    return stringify(evalrawexp(context, mapping, arg))
 
 def evalstringliteral(context, mapping, arg):
     """Evaluate given argument as string template, but returns symbol name
@@ -380,8 +385,8 @@
     return (runtemplate, ctmpl)
 
 def runtemplate(context, mapping, template):
-    for func, data in template:
-        yield func(context, mapping, data)
+    for arg in template:
+        yield evalrawexp(context, mapping, arg)
 
 def buildfilter(exp, context):
     n = getsymbol(exp[2])
@@ -415,15 +420,15 @@
     return (runmap, (darg, targ))
 
 def runmap(context, mapping, data):
-    (func, data), (tfunc, tdata) = data
-    d = func(context, mapping, data)
+    darg, targ = data
+    d = evalrawexp(context, mapping, darg)
     if util.safehasattr(d, 'itermaps'):
         diter = d.itermaps()
     else:
         try:
             diter = iter(d)
         except TypeError:
-            sym = findsymbolicname((func, data))
+            sym = findsymbolicname(darg)
             if sym:
                 raise error.ParseError(_("keyword '%s' is not iterable") % sym)
             else:
@@ -435,7 +440,7 @@
         if isinstance(v, dict):
             lm.update(v)
             lm['originalnode'] = mapping.get('node')
-            yield tfunc(context, lm, tdata)
+            yield evalrawexp(context, lm, targ)
         else:
             # v is not an iterable of dicts, this happen when 'key'
             # has been fully expanded already and format is useless.
@@ -718,9 +723,9 @@
 
     test = evalboolean(context, mapping, args[0])
     if test:
-        yield args[1][0](context, mapping, args[1][1])
+        yield evalrawexp(context, mapping, args[1])
     elif len(args) == 3:
-        yield args[2][0](context, mapping, args[2][1])
+        yield evalrawexp(context, mapping, args[2])
 
 @templatefunc('ifcontains(needle, haystack, then[, else])')
 def ifcontains(context, mapping, args):
@@ -734,9 +739,9 @@
     haystack = evalfuncarg(context, mapping, args[1])
 
     if needle in haystack:
-        yield args[2][0](context, mapping, args[2][1])
+        yield evalrawexp(context, mapping, args[2])
     elif len(args) == 4:
-        yield args[3][0](context, mapping, args[3][1])
+        yield evalrawexp(context, mapping, args[3])
 
 @templatefunc('ifeq(expr1, expr2, then[, else])')
 def ifeq(context, mapping, args):
@@ -749,9 +754,9 @@
     test = evalstring(context, mapping, args[0])
     match = evalstring(context, mapping, args[1])
     if test == match:
-        yield args[2][0](context, mapping, args[2][1])
+        yield evalrawexp(context, mapping, args[2])
     elif len(args) == 4:
-        yield args[3][0](context, mapping, args[3][1])
+        yield evalrawexp(context, mapping, args[3])
 
 @templatefunc('join(list, sep)')
 def join(context, mapping, args):
@@ -760,7 +765,9 @@
         # i18n: "join" is a keyword
         raise error.ParseError(_("join expects one or two arguments"))
 
-    joinset = args[0][0](context, mapping, args[0][1])
+    # TODO: perhaps this should be evalfuncarg(), but it can't because hgweb
+    # abuses generator as a keyword that returns a list of dicts.
+    joinset = evalrawexp(context, mapping, args[0])
     if util.safehasattr(joinset, 'itermaps'):
         jf = joinset.joinfmt
         joinset = [jf(x) for x in joinset.itermaps()]