Patchwork [8,of,8] templater: define interface for objects requiring unwrapvalue()

login
register
mail settings
Submitter Yuya Nishihara
Date April 1, 2018, 2:46 a.m.
Message ID <7e5b902521dc5d58b3da.1522550765@mimosa>
Download mbox | patch
Permalink /patch/30095/
State Deferred
Headers show

Comments

Yuya Nishihara - April 1, 2018, 2:46 a.m.
# HG changeset patch
# User Yuya Nishihara <yuya@tcha.org>
# Date 1521288196 -32400
#      Sat Mar 17 21:03:16 2018 +0900
# Node ID 7e5b902521dc5d58b3da8f6bd8b4b8e8cb33dad7
# Parent  5d5ecd0c1e91676bc1ac6a481679cad21fb0e108
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().

Patch

diff --git a/mercurial/templateutil.py b/mercurial/templateutil.py
--- a/mercurial/templateutil.py
+++ b/mercurial/templateutil.py
@@ -29,7 +29,11 @@  class TemplateNotFound(error.Abort):
 
 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
 
@@ -37,6 +41,13 @@  class wrapped(object):
     def show(self, context):
         """Return a bytes or (possibly nested) generator of bytes"""
 
+    @abc.abstractmethod
+    def tovalue(self, context):
+        """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):
@@ -80,6 +91,10 @@  class hybrid(wrapped):
             return gen()
         return gen
 
+    def tovalue(self, context):
+        # 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):
@@ -103,8 +118,7 @@  class mappable(wrapped):
     - "{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):
@@ -128,6 +142,9 @@  class mappable(wrapped):
             return gen()
         return gen
 
+    def tovalue(self, context):
+        return _unthunk(context, 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
@@ -154,9 +171,9 @@  def unwraphybrid(context, thing):
 
 def unwrapvalue(context, 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)
 
 def wraphybridvalue(container, key, value):
     """Wrap an element of hybrid container to be mappable