templater: remove __iter__() from _hybrid, resolve it explicitly
The goal is to fix "{hybrid_obj|json}" output.
A _hybrid object must act as a list or a dict as well as a generator of
legacy template strings. Before, _hybrid.__iter__() was assigned for legacy
template, which conflicted with list.__iter__() API.
This patch drops _hybrid.__iter__() and makes stringify/flatten functions
unwrap a generator instead.
--- a/mercurial/templatefilters.py Sun Apr 24 19:15:34 2016 +0900
+++ b/mercurial/templatefilters.py Tue Apr 04 22:19:02 2017 +0900
@@ -350,6 +350,7 @@
"""Any type. Turns the value into text by converting values into
text and concatenating them.
"""
+ thing = templatekw.unwraphybrid(thing)
if util.safehasattr(thing, '__iter__') and not isinstance(thing, str):
return "".join([stringify(t) for t in thing if t is not None])
if thing is None:
--- a/mercurial/templatekw.py Sun Apr 24 19:15:34 2016 +0900
+++ b/mercurial/templatekw.py Tue Apr 04 22:19:02 2017 +0900
@@ -35,8 +35,6 @@
self.values = values
self._makemap = makemap
self.joinfmt = joinfmt
- def __iter__(self):
- return self.gen
def itermaps(self):
makemap = self._makemap
for x in self.values:
@@ -50,6 +48,13 @@
raise AttributeError(name)
return getattr(self.values, name)
+def unwraphybrid(thing):
+ """Return an object which can be stringified possibly by using a legacy
+ template"""
+ if not util.safehasattr(thing, 'gen'):
+ return thing
+ return thing.gen
+
def showlist(name, values, plural=None, element=None, separator=' ', **args):
if not element:
element = name
--- a/mercurial/templater.py Sun Apr 24 19:15:34 2016 +0900
+++ b/mercurial/templater.py Tue Apr 04 22:19:02 2017 +0900
@@ -1020,6 +1020,7 @@
def _flatten(thing):
'''yield a single stream from a possibly nested set of iterators'''
+ thing = templatekw.unwraphybrid(thing)
if isinstance(thing, str):
yield thing
elif thing is None:
@@ -1028,6 +1029,7 @@
yield str(thing)
else:
for i in thing:
+ i = templatekw.unwraphybrid(i)
if isinstance(i, str):
yield i
elif i is None: