# HG changeset patch # User Yuya Nishihara # Date 1521374483 -32400 # Node ID 7c902a8345efd3bc079cd9579434ebba1df065e8 # Parent 448f7ec247e2032a4f3c0cd9efed1170b37d4752 templater: complain about invalid application of '%' operator (BC) Before, '{x % y % z ...}' was silently evaluated as '{x % y}'. We no longer need this hack since the web template bugs was fixed by earlier patches. At this point, the error message may contain '', which will be fixed later. diff -r 448f7ec247e2 -r 7c902a8345ef mercurial/templateutil.py --- a/mercurial/templateutil.py Sun Mar 18 21:18:57 2018 +0900 +++ b/mercurial/templateutil.py Sun Mar 18 21:01:23 2018 +0900 @@ -567,6 +567,20 @@ return (_("template filter '%s' is not compatible with keyword '%s'") % (fn, sym)) +def _checkeditermaps(darg, d): + try: + for v in d: + if not isinstance(v, dict): + raise TypeError + yield v + except TypeError: + sym = findsymbolicname(darg) + if sym: + raise error.ParseError(_("keyword '%s' is not iterable of mappings") + % sym) + else: + raise error.ParseError(_("%r is not iterable of mappings") % d) + def _iteroverlaymaps(context, origmapping, newmappings): """Generate combined mappings from the original mapping and an iterable of partial mappings to override the original""" @@ -578,28 +592,17 @@ def runmap(context, mapping, data): darg, targ = data d = evalrawexp(context, mapping, darg) + # TODO: a generator should be rejected because it is a thunk of lazy + # string, but we can't because hgweb abuses generator as a keyword + # that returns a list of dicts. if isinstance(d, wrapped): diter = d.itermaps(context) else: - try: - diter = iter(d) - except TypeError: - sym = findsymbolicname(darg) - if sym: - raise error.ParseError(_("keyword '%s' is not iterable") % sym) - else: - raise error.ParseError(_("%r is not iterable") % d) - + diter = _checkeditermaps(darg, d) for i, v in enumerate(diter): - if isinstance(v, dict): - lm = context.overlaymap(mapping, v) - lm['index'] = i - yield evalrawexp(context, lm, targ) - else: - # v is not an iterable of dicts, this happen when 'key' - # has been fully expanded already and format is useless. - # If so, return the expanded value. - yield v + lm = context.overlaymap(mapping, v) + lm['index'] = i + yield evalrawexp(context, lm, targ) def runmember(context, mapping, data): darg, memb = data diff -r 448f7ec247e2 -r 7c902a8345ef tests/test-command-template.t --- a/tests/test-command-template.t Sun Mar 18 21:18:57 2018 +0900 +++ b/tests/test-command-template.t Sun Mar 18 21:01:23 2018 +0900 @@ -3210,10 +3210,13 @@ $ hg log -R latesttag -r tip -T '{rev % "a"}\n' - hg: parse error: keyword 'rev' is not iterable + hg: parse error: keyword 'rev' is not iterable of mappings [255] $ hg log -R latesttag -r tip -T '{get(extras, "unknown") % "a"}\n' - hg: parse error: None is not iterable + hg: parse error: None is not iterable of mappings + [255] + $ hg log -R latesttag -r tip -T '{extras % "{key}\n" % "{key}\n"}' + hg: parse error: is not iterable of mappings (glob) [255] Test new-style inline templating of non-list/dict type: @@ -3228,7 +3231,7 @@ $ hg log -R latesttag -r tip -T '{get(extras, "branch") % "{key}: {value}\n"}' branch: default $ hg log -R latesttag -r tip -T '{get(extras, "unknown") % "{key}\n"}' - hg: parse error: None is not iterable + hg: parse error: None is not iterable of mappings [255] $ hg log -R latesttag -r tip -T '{min(extras) % "{key}: {value}\n"}' branch: default