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 |
|
|
|
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 | return d.getmember(context, mapping, memb) | |
|
683 | raise error.ParseError | |
|
684 | except error.ParseError: | |
|
706 | return d.getmember(context, mapping, memb) | |
|
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: |
|
|
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' |
|
|
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: |
|
|
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