changeset 37281:26f6fc179e62

templater: define interface for objects requiring unwrapvalue() unwrapvalue() is changed to not return a lazy bytes generator for "wrapped" types because I want to define the tovalue() interface as such. It's a baby step to unify unwrapvalue() and _unwrapvalue().
author Yuya Nishihara <yuya@tcha.org>
date Sat, 17 Mar 2018 21:03:16 +0900
parents 671a01cd50b5
children 435481393198
files mercurial/templateutil.py
diffstat 1 files changed, 22 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/templateutil.py	Fri Mar 23 21:40:16 2018 +0900
+++ b/mercurial/templateutil.py	Sat Mar 17 21:03:16 2018 +0900
@@ -29,7 +29,11 @@
 
 class wrapped(object):
     """Object requiring extra conversion prior to displaying or processing
-    as value"""
+    as value
+
+    Use unwrapvalue(), unwrapastype(), or unwraphybrid() to obtain the inner
+    object.
+    """
 
     __metaclass__ = abc.ABCMeta
 
@@ -42,6 +46,13 @@
         not printable.
         """
 
+    @abc.abstractmethod
+    def tovalue(self, context, mapping):
+        """Move the inner value object out or create a value representation
+
+        A returned value must be serializable by templaterfilters.json().
+        """
+
 # stub for representing a date type; may be a real date type that can
 # provide a readable string value
 class date(object):
@@ -85,6 +96,10 @@
             return gen()
         return gen
 
+    def tovalue(self, context, mapping):
+        # TODO: return self._values and get rid of proxy methods
+        return self
+
     def __contains__(self, x):
         return x in self._values
     def __getitem__(self, key):
@@ -108,8 +123,7 @@
     - "{manifest.rev}"
 
     Unlike a hybrid, this does not simulate the behavior of the underling
-    value. Use unwrapvalue(), unwrapastype(), or unwraphybrid() to obtain
-    the inner object.
+    value.
     """
 
     def __init__(self, gen, key, value, makemap):
@@ -133,6 +147,9 @@
             return gen()
         return gen
 
+    def tovalue(self, context, mapping):
+        return _unthunk(context, mapping, self._value)
+
 def hybriddict(data, key='key', value='value', fmt=None, gen=None):
     """Wrap data to support both dict-like and string-like operations"""
     prefmt = pycompat.identity
@@ -159,9 +176,9 @@
 
 def unwrapvalue(context, mapping, thing):
     """Move the inner value object out of the wrapper"""
-    if not util.safehasattr(thing, '_value'):
+    if not isinstance(thing, wrapped):
         return thing
-    return thing._value
+    return thing.tovalue(context, mapping)
 
 def wraphybridvalue(container, key, value):
     """Wrap an element of hybrid container to be mappable