Mercurial > public > mercurial-scm > hg
comparison mercurial/templateutil.py @ 37404:7c902a8345ef
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 '<generator *>', which will
be fixed later.
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Sun, 18 Mar 2018 21:01:23 +0900 |
parents | 0b64416224d9 |
children | da8e9ecac4a4 |
comparison
equal
deleted
inserted
replaced
37403:448f7ec247e2 | 37404:7c902a8345ef |
---|---|
565 if not sym: | 565 if not sym: |
566 return _("incompatible use of template filter '%s'") % fn | 566 return _("incompatible use of template filter '%s'") % fn |
567 return (_("template filter '%s' is not compatible with keyword '%s'") | 567 return (_("template filter '%s' is not compatible with keyword '%s'") |
568 % (fn, sym)) | 568 % (fn, sym)) |
569 | 569 |
570 def _checkeditermaps(darg, d): | |
571 try: | |
572 for v in d: | |
573 if not isinstance(v, dict): | |
574 raise TypeError | |
575 yield v | |
576 except TypeError: | |
577 sym = findsymbolicname(darg) | |
578 if sym: | |
579 raise error.ParseError(_("keyword '%s' is not iterable of mappings") | |
580 % sym) | |
581 else: | |
582 raise error.ParseError(_("%r is not iterable of mappings") % d) | |
583 | |
570 def _iteroverlaymaps(context, origmapping, newmappings): | 584 def _iteroverlaymaps(context, origmapping, newmappings): |
571 """Generate combined mappings from the original mapping and an iterable | 585 """Generate combined mappings from the original mapping and an iterable |
572 of partial mappings to override the original""" | 586 of partial mappings to override the original""" |
573 for i, nm in enumerate(newmappings): | 587 for i, nm in enumerate(newmappings): |
574 lm = context.overlaymap(origmapping, nm) | 588 lm = context.overlaymap(origmapping, nm) |
576 yield lm | 590 yield lm |
577 | 591 |
578 def runmap(context, mapping, data): | 592 def runmap(context, mapping, data): |
579 darg, targ = data | 593 darg, targ = data |
580 d = evalrawexp(context, mapping, darg) | 594 d = evalrawexp(context, mapping, darg) |
595 # TODO: a generator should be rejected because it is a thunk of lazy | |
596 # string, but we can't because hgweb abuses generator as a keyword | |
597 # that returns a list of dicts. | |
581 if isinstance(d, wrapped): | 598 if isinstance(d, wrapped): |
582 diter = d.itermaps(context) | 599 diter = d.itermaps(context) |
583 else: | 600 else: |
584 try: | 601 diter = _checkeditermaps(darg, d) |
585 diter = iter(d) | |
586 except TypeError: | |
587 sym = findsymbolicname(darg) | |
588 if sym: | |
589 raise error.ParseError(_("keyword '%s' is not iterable") % sym) | |
590 else: | |
591 raise error.ParseError(_("%r is not iterable") % d) | |
592 | |
593 for i, v in enumerate(diter): | 602 for i, v in enumerate(diter): |
594 if isinstance(v, dict): | 603 lm = context.overlaymap(mapping, v) |
595 lm = context.overlaymap(mapping, v) | 604 lm['index'] = i |
596 lm['index'] = i | 605 yield evalrawexp(context, lm, targ) |
597 yield evalrawexp(context, lm, targ) | |
598 else: | |
599 # v is not an iterable of dicts, this happen when 'key' | |
600 # has been fully expanded already and format is useless. | |
601 # If so, return the expanded value. | |
602 yield v | |
603 | 606 |
604 def runmember(context, mapping, data): | 607 def runmember(context, mapping, data): |
605 darg, memb = data | 608 darg, memb = data |
606 d = evalrawexp(context, mapping, darg) | 609 d = evalrawexp(context, mapping, darg) |
607 if util.safehasattr(d, 'tomap'): | 610 if util.safehasattr(d, 'tomap'): |