Mercurial > hg
comparison mercurial/templater.py @ 31927:2abc556dbe92
templater: find keyword name more thoroughly on filtering error
Before, it could spill an internal representation of compiled template such
as [(<function runsymbol at 0x....>, 'extras'), ...]. Show less cryptic
message if no symbol found.
New findsymbolicname() function will be also used by dict() constructor.
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Sat, 08 Apr 2017 23:33:32 +0900 |
parents | 932241b8c644 |
children | 277b3e2d711b |
comparison
equal
deleted
inserted
replaced
31926:932241b8c644 | 31927:2abc556dbe92 |
---|---|
282 # even if it exists in mapping. this allows us to override mapping | 282 # even if it exists in mapping. this allows us to override mapping |
283 # by web templates, e.g. 'changelogtag' is redefined in map file. | 283 # by web templates, e.g. 'changelogtag' is redefined in map file. |
284 return context._load(exp[1]) | 284 return context._load(exp[1]) |
285 raise error.ParseError(_("expected template specifier")) | 285 raise error.ParseError(_("expected template specifier")) |
286 | 286 |
287 def findsymbolicname(arg): | |
288 """Find symbolic name for the given compiled expression; returns None | |
289 if nothing found reliably""" | |
290 while True: | |
291 func, data = arg | |
292 if func is runsymbol: | |
293 return data | |
294 elif func is runfilter: | |
295 arg = data[0] | |
296 else: | |
297 return None | |
298 | |
287 def evalfuncarg(context, mapping, arg): | 299 def evalfuncarg(context, mapping, arg): |
288 func, data = arg | 300 func, data = arg |
289 # func() may return string, generator of strings or arbitrary object such | 301 # func() may return string, generator of strings or arbitrary object such |
290 # as date tuple, but filter does not want generator. | 302 # as date tuple, but filter does not want generator. |
291 thing = func(context, mapping, data) | 303 thing = func(context, mapping, data) |
385 arg, filt = data | 397 arg, filt = data |
386 thing = evalfuncarg(context, mapping, arg) | 398 thing = evalfuncarg(context, mapping, arg) |
387 try: | 399 try: |
388 return filt(thing) | 400 return filt(thing) |
389 except (ValueError, AttributeError, TypeError): | 401 except (ValueError, AttributeError, TypeError): |
390 if isinstance(arg[1], tuple): | 402 sym = findsymbolicname(arg) |
391 dt = arg[1][1] | 403 if sym: |
404 msg = (_("template filter '%s' is not compatible with keyword '%s'") | |
405 % (filt.func_name, sym)) | |
392 else: | 406 else: |
393 dt = arg[1] | 407 msg = _("incompatible use of template filter '%s'") % filt.func_name |
394 raise error.Abort(_("template filter '%s' is not compatible with " | 408 raise error.Abort(msg) |
395 "keyword '%s'") % (filt.func_name, dt)) | |
396 | 409 |
397 def buildmap(exp, context): | 410 def buildmap(exp, context): |
398 func, data = compileexp(exp[1], context, methods) | 411 func, data = compileexp(exp[1], context, methods) |
399 tfunc, tdata = gettemplate(exp[2], context) | 412 tfunc, tdata = gettemplate(exp[2], context) |
400 return (runmap, (func, data, tfunc, tdata)) | 413 return (runmap, (func, data, tfunc, tdata)) |