Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/templateutil.py @ 38296:e72697893c93
templater: promote tomap() to an interface type
I originally considered merging tomap() with itermaps()/getmember(), but
decided to not. We might want to add support for chained map operations
(e.g. {foo % func() % ...}), where func() will return a mappable object,
and 'foo % func()' will be a mappedgenerator of mappable objects.
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Sat, 21 Apr 2018 19:01:35 +0900 |
parents | 0e0d03d09ecd |
children | 8d6109b49b31 |
comparison
equal
deleted
inserted
replaced
38295:0e0d03d09ecd | 38296:e72697893c93 |
---|---|
89 """Move the inner value object out or create a value representation | 89 """Move the inner value object out or create a value representation |
90 | 90 |
91 A returned value must be serializable by templaterfilters.json(). | 91 A returned value must be serializable by templaterfilters.json(). |
92 """ | 92 """ |
93 | 93 |
94 class mappable(object): | |
95 """Object which can be converted to a single template mapping""" | |
96 | |
97 def itermaps(self, context): | |
98 yield self.tomap(context) | |
99 | |
100 @abc.abstractmethod | |
101 def tomap(self, context): | |
102 """Create a single template mapping representing this""" | |
103 | |
94 class wrappedbytes(wrapped): | 104 class wrappedbytes(wrapped): |
95 """Wrapper for byte string""" | 105 """Wrapper for byte string""" |
96 | 106 |
97 def __init__(self, value): | 107 def __init__(self, value): |
98 self._value = value | 108 self._value = value |
241 if util.safehasattr(xs, 'get'): | 251 if util.safehasattr(xs, 'get'): |
242 return {k: unwrapvalue(context, mapping, v) | 252 return {k: unwrapvalue(context, mapping, v) |
243 for k, v in xs.iteritems()} | 253 for k, v in xs.iteritems()} |
244 return [unwrapvalue(context, mapping, x) for x in xs] | 254 return [unwrapvalue(context, mapping, x) for x in xs] |
245 | 255 |
246 class hybriditem(wrapped): | 256 class hybriditem(mappable, wrapped): |
247 """Wrapper for non-list/dict object to support map operation | 257 """Wrapper for non-list/dict object to support map operation |
248 | 258 |
249 This class allows us to handle both: | 259 This class allows us to handle both: |
250 - "{manifest}" | 260 - "{manifest}" |
251 - "{manifest % '{rev}:{node}'}" | 261 - "{manifest % '{rev}:{node}'}" |
256 self._gen = gen # generator or function returning generator | 266 self._gen = gen # generator or function returning generator |
257 self._key = key | 267 self._key = key |
258 self._value = value # may be generator of strings | 268 self._value = value # may be generator of strings |
259 self._makemap = makemap | 269 self._makemap = makemap |
260 | 270 |
261 def tomap(self): | 271 def tomap(self, context): |
262 return self._makemap(self._key) | 272 return self._makemap(self._key) |
263 | 273 |
264 def contains(self, context, mapping, item): | 274 def contains(self, context, mapping, item): |
265 w = makewrapped(context, mapping, self._value) | 275 w = makewrapped(context, mapping, self._value) |
266 return w.contains(context, mapping, item) | 276 return w.contains(context, mapping, item) |
274 return w.getmin(context, mapping) | 284 return w.getmin(context, mapping) |
275 | 285 |
276 def getmax(self, context, mapping): | 286 def getmax(self, context, mapping): |
277 w = makewrapped(context, mapping, self._value) | 287 w = makewrapped(context, mapping, self._value) |
278 return w.getmax(context, mapping) | 288 return w.getmax(context, mapping) |
279 | |
280 def itermaps(self, context): | |
281 yield self.tomap() | |
282 | 289 |
283 def join(self, context, mapping, sep): | 290 def join(self, context, mapping, sep): |
284 w = makewrapped(context, mapping, self._value) | 291 w = makewrapped(context, mapping, self._value) |
285 return w.join(context, mapping, sep) | 292 return w.join(context, mapping, sep) |
286 | 293 |
773 return mappedgenerator(_applymap, args=(mapping, d, darg, targ)) | 780 return mappedgenerator(_applymap, args=(mapping, d, darg, targ)) |
774 | 781 |
775 def runmember(context, mapping, data): | 782 def runmember(context, mapping, data): |
776 darg, memb = data | 783 darg, memb = data |
777 d = evalwrapped(context, mapping, darg) | 784 d = evalwrapped(context, mapping, darg) |
778 if util.safehasattr(d, 'tomap'): | 785 if isinstance(d, mappable): |
779 lm = context.overlaymap(mapping, d.tomap()) | 786 lm = context.overlaymap(mapping, d.tomap(context)) |
780 return runsymbol(context, lm, memb) | 787 return runsymbol(context, lm, memb) |
781 try: | 788 try: |
782 return d.getmember(context, mapping, memb) | 789 return d.getmember(context, mapping, memb) |
783 except error.ParseError as err: | 790 except error.ParseError as err: |
784 sym = findsymbolicname(darg) | 791 sym = findsymbolicname(darg) |