Patchwork [02,of,11] templatefilters: allow declaration of input data type

login
register
mail settings
Submitter Yuya Nishihara
Date March 31, 2018, 1:49 a.m.
Message ID <a31ddf984c1b851d78fa.1522460970@mimosa>
Download mbox | patch
Permalink /patch/30038/
State Accepted
Headers show

Comments

Yuya Nishihara - March 31, 2018, 1:49 a.m.
# HG changeset patch
# User Yuya Nishihara <yuya@tcha.org>
# Date 1521353698 -32400
#      Sun Mar 18 15:14:58 2018 +0900
# Node ID a31ddf984c1b851d78faa753b12aa694f6884ee5
# Parent  eb32cf0cbbf309242f75d5b94f27744b1a1abd5d
templatefilters: allow declaration of input data type

Currently filters take an unwrapped value, which should have no hybrid magic
but actually it does because stringify() relies on it. The 'intype' allows
us to pre-process the magic by .e.g. evalstring() keeping filter functions
as simple as they are now.

stringify() is ported as an example. More follow.

Patch

diff --git a/mercurial/registrar.py b/mercurial/registrar.py
--- a/mercurial/registrar.py
+++ b/mercurial/registrar.py
@@ -324,7 +324,7 @@  class templatefilter(_templateregistrarb
 
         templatefilter = registrar.templatefilter()
 
-        @templatefilter('myfilter')
+        @templatefilter('myfilter', intype=bytes)
         def myfilterfunc(text):
             '''Explanation of this template filter ....
             '''
@@ -332,6 +332,9 @@  class templatefilter(_templateregistrarb
 
     The first string argument is used also in online help.
 
+    Optional argument 'intype' defines the type of the input argument,
+    which should be (bytes, int, or None for any.)
+
     'templatefilter' instance in example above can be used to
     decorate multiple functions.
 
@@ -342,6 +345,9 @@  class templatefilter(_templateregistrarb
     Otherwise, explicit 'templatefilters.loadkeyword()' is needed.
     """
 
+    def _extrasetup(self, name, func, intype=None):
+        func._intype = intype
+
 class templatefunc(_templateregistrarbase):
     """Decorator to register template function
 
diff --git a/mercurial/templatefilters.py b/mercurial/templatefilters.py
--- a/mercurial/templatefilters.py
+++ b/mercurial/templatefilters.py
@@ -354,12 +354,12 @@  def splitlines(text):
 def stringescape(text):
     return stringutil.escapestr(text)
 
-@templatefilter('stringify')
+@templatefilter('stringify', intype=bytes)
 def stringify(thing):
     """Any type. Turns the value into text by converting values into
     text and concatenating them.
     """
-    return templateutil.stringify(thing)
+    return thing  # coerced by the intype
 
 @templatefilter('stripdir')
 def stripdir(text):
diff --git a/mercurial/templateutil.py b/mercurial/templateutil.py
--- a/mercurial/templateutil.py
+++ b/mercurial/templateutil.py
@@ -342,6 +342,7 @@  def evalstringliteral(context, mapping, 
     return stringify(thing)
 
 _unwrapfuncbytype = {
+    None: _unwrapvalue,
     bytes: stringify,
     int: unwrapinteger,
 }
@@ -400,8 +401,9 @@  def runtemplate(context, mapping, templa
 
 def runfilter(context, mapping, data):
     arg, filt = data
-    thing = evalfuncarg(context, mapping, arg)
+    thing = evalrawexp(context, mapping, arg)
     try:
+        thing = unwrapastype(thing, getattr(filt, '_intype', None))
         return filt(thing)
     except (ValueError, AttributeError, TypeError):
         sym = findsymbolicname(arg)