##// END OF EJS Templates
templater: promote getmember() to an interface of wrapped types
Yuya Nishihara -
r38261:06d11cd9 default
parent child Browse files
Show More
@@ -713,6 +713,9 b' class sessionvars(templateutil.wrapped):'
713 713 def __copy__(self):
714 714 return sessionvars(copy.copy(self._vars), self._start)
715 715
716 def getmember(self, context, mapping, key):
717 return self._vars.get(key)
718
716 719 def itermaps(self, context):
717 720 separator = self._start
718 721 for key, value in sorted(self._vars.iteritems()):
@@ -262,12 +262,13 b' def get(context, mapping, args):'
262 262 raise error.ParseError(_("get() expects two arguments"))
263 263
264 264 dictarg = evalwrapped(context, mapping, args[0])
265 if not util.safehasattr(dictarg, 'getmember'):
265 key = evalfuncarg(context, mapping, args[1])
266 try:
267 return dictarg.getmember(context, mapping, key)
268 except error.ParseError as err:
266 269 # i18n: "get" is a keyword
267 raise error.ParseError(_("get() expects a dict as first argument"))
268
269 key = evalfuncarg(context, mapping, args[1])
270 return dictarg.getmember(context, mapping, key)
270 hint = _("get() expects a dict as first argument")
271 raise error.ParseError(bytes(err), hint=hint)
271 272
272 273 @templatefunc('if(expr, then[, else])')
273 274 def if_(context, mapping, args):
@@ -38,6 +38,14 b' class wrapped(object):'
38 38 __metaclass__ = abc.ABCMeta
39 39
40 40 @abc.abstractmethod
41 def getmember(self, context, mapping, key):
42 """Return a member item for the specified key
43
44 A returned object may be either a wrapped object or a pure value
45 depending on the self type.
46 """
47
48 @abc.abstractmethod
41 49 def itermaps(self, context):
42 50 """Yield each template mapping"""
43 51
@@ -72,6 +80,10 b' class wrappedbytes(wrapped):'
72 80 def __init__(self, value):
73 81 self._value = value
74 82
83 def getmember(self, context, mapping, key):
84 raise error.ParseError(_('%r is not a dictionary')
85 % pycompat.bytestr(self._value))
86
75 87 def itermaps(self, context):
76 88 raise error.ParseError(_('%r is not iterable of mappings')
77 89 % pycompat.bytestr(self._value))
@@ -91,6 +103,9 b' class wrappedvalue(wrapped):'
91 103 def __init__(self, value):
92 104 self._value = value
93 105
106 def getmember(self, context, mapping, key):
107 raise error.ParseError(_('%r is not a dictionary') % self._value)
108
94 109 def itermaps(self, context):
95 110 raise error.ParseError(_('%r is not iterable of mappings')
96 111 % self._value)
@@ -196,6 +211,10 b' class mappable(wrapped):'
196 211 def tomap(self):
197 212 return self._makemap(self._key)
198 213
214 def getmember(self, context, mapping, key):
215 w = makewrapped(context, mapping, self._value)
216 return w.getmember(context, mapping, key)
217
199 218 def itermaps(self, context):
200 219 yield self.tomap()
201 220
@@ -231,6 +250,9 b' class _mappingsequence(wrapped):'
231 250 self._tmpl = tmpl
232 251 self._defaultsep = sep
233 252
253 def getmember(self, context, mapping, key):
254 raise error.ParseError(_('not a dictionary'))
255
234 256 def join(self, context, mapping, sep):
235 257 mapsiter = _iteroverlaymaps(context, mapping, self.itermaps(context))
236 258 if self._name:
@@ -294,6 +316,9 b' class mappedgenerator(wrapped):'
294 316 def _gen(self, context):
295 317 return self._make(context, *self._args)
296 318
319 def getmember(self, context, mapping, key):
320 raise error.ParseError(_('not a dictionary'))
321
297 322 def itermaps(self, context):
298 323 raise error.ParseError(_('list of strings is not mappable'))
299 324
@@ -678,15 +703,13 b' def runmember(context, mapping, data):'
678 703 lm = context.overlaymap(mapping, d.tomap())
679 704 return runsymbol(context, lm, memb)
680 705 try:
681 if util.safehasattr(d, 'getmember'):
682 706 return d.getmember(context, mapping, memb)
683 raise error.ParseError
684 except error.ParseError:
707 except error.ParseError as err:
685 708 sym = findsymbolicname(darg)
686 if sym:
687 raise error.ParseError(_("keyword '%s' has no member") % sym)
688 else:
689 raise error.ParseError(_("%r has no member") % pycompat.bytestr(d))
709 if not sym:
710 raise
711 hint = _("keyword '%s' does not support member operation") % sym
712 raise error.ParseError(bytes(err), hint=hint)
690 713
691 714 def runnegate(context, mapping, data):
692 715 data = evalinteger(context, mapping, data,
@@ -3345,10 +3345,11 b' Test evaluation of dot operator:'
3345 3345 default
3346 3346
3347 3347 $ hg log -R latesttag -l1 -T '{author.invalid}\n'
3348 hg: parse error: keyword 'author' has no member
3348 hg: parse error: 'test' is not a dictionary
3349 (keyword 'author' does not support member operation)
3349 3350 [255]
3350 3351 $ hg log -R latesttag -l1 -T '{min("abc").invalid}\n'
3351 hg: parse error: 'a' has no member
3352 hg: parse error: 'a' is not a dictionary
3352 3353 [255]
3353 3354
3354 3355 Test the sub function of templating for expansion:
@@ -3851,7 +3852,8 b' Test get function:'
3851 3852 $ hg log -r 0 --template '{get(extras, "br{"anch"}")}\n'
3852 3853 default
3853 3854 $ hg log -r 0 --template '{get(files, "should_fail")}\n'
3854 hg: parse error: get() expects a dict as first argument
3855 hg: parse error: not a dictionary
3856 (get() expects a dict as first argument)
3855 3857 [255]
3856 3858
3857 3859 Test json filter applied to hybrid object:
General Comments 0
You need to be logged in to leave comments. Login now