Mercurial > public > mercurial-scm > hg-stable
annotate mercurial/templateutil.py @ 36926:6ff6e1d6b5b8
templater: move stringify() to templateutil module
As we have a util module, it doesn't make sense to import stringify() from
templatefilters.py.
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Thu, 08 Mar 2018 23:10:46 +0900 |
parents | da2977e674a3 |
children | 32f9b7e3f056 |
rev | line source |
---|---|
36919
da2977e674a3
templater: extract template evaluation utility to new module
Yuya Nishihara <yuya@tcha.org>
parents:
36918
diff
changeset
|
1 # templateutil.py - utility for template evaluation |
1909
37b9f80a5fbb
add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
1906
diff
changeset
|
2 # |
37b9f80a5fbb
add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
1906
diff
changeset
|
3 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com> |
37b9f80a5fbb
add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
1906
diff
changeset
|
4 # |
8225
46293a0c7e9f
updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents:
8223
diff
changeset
|
5 # This software may be used and distributed according to the terms of the |
10263 | 6 # GNU General Public License version 2 or any later version. |
1909
37b9f80a5fbb
add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
1906
diff
changeset
|
7 |
36919
da2977e674a3
templater: extract template evaluation utility to new module
Yuya Nishihara <yuya@tcha.org>
parents:
36918
diff
changeset
|
8 from __future__ import absolute_import |
25985
7eb357b5f774
templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25815
diff
changeset
|
9 |
17982
e06e9fd2d99f
template engine: convert generator-based iterator to list-based iterator
Weiwen <weiwen@fb.com>
parents:
17890
diff
changeset
|
10 import types |
25985
7eb357b5f774
templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25815
diff
changeset
|
11 |
7eb357b5f774
templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25815
diff
changeset
|
12 from .i18n import _ |
7eb357b5f774
templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25815
diff
changeset
|
13 from . import ( |
7eb357b5f774
templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25815
diff
changeset
|
14 error, |
30620
bb77654dc7ae
py3: replace os.sep with pycompat.ossep (part 3 of 4)
Pulkit Goyal <7895pulkit@gmail.com>
parents:
30342
diff
changeset
|
15 pycompat, |
25985
7eb357b5f774
templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25815
diff
changeset
|
16 templatekw, |
7eb357b5f774
templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25815
diff
changeset
|
17 util, |
7eb357b5f774
templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25815
diff
changeset
|
18 ) |
13176
895f54a79c6e
templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents:
13175
diff
changeset
|
19 |
36474
717a279c0c21
templater: specialize ResourceUnavailable error so that it can be caught
Yuya Nishihara <yuya@tcha.org>
parents:
36473
diff
changeset
|
20 class ResourceUnavailable(error.Abort): |
717a279c0c21
templater: specialize ResourceUnavailable error so that it can be caught
Yuya Nishihara <yuya@tcha.org>
parents:
36473
diff
changeset
|
21 pass |
717a279c0c21
templater: specialize ResourceUnavailable error so that it can be caught
Yuya Nishihara <yuya@tcha.org>
parents:
36473
diff
changeset
|
22 |
36473
8dbd97aef915
templater: move specialized exception types to top
Yuya Nishihara <yuya@tcha.org>
parents:
36278
diff
changeset
|
23 class TemplateNotFound(error.Abort): |
8dbd97aef915
templater: move specialized exception types to top
Yuya Nishihara <yuya@tcha.org>
parents:
36278
diff
changeset
|
24 pass |
8dbd97aef915
templater: move specialized exception types to top
Yuya Nishihara <yuya@tcha.org>
parents:
36278
diff
changeset
|
25 |
36926
6ff6e1d6b5b8
templater: move stringify() to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents:
36919
diff
changeset
|
26 def stringify(thing): |
6ff6e1d6b5b8
templater: move stringify() to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents:
36919
diff
changeset
|
27 """Turn values into bytes by converting into text and concatenating them""" |
6ff6e1d6b5b8
templater: move stringify() to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents:
36919
diff
changeset
|
28 thing = templatekw.unwraphybrid(thing) |
6ff6e1d6b5b8
templater: move stringify() to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents:
36919
diff
changeset
|
29 if util.safehasattr(thing, '__iter__') and not isinstance(thing, bytes): |
6ff6e1d6b5b8
templater: move stringify() to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents:
36919
diff
changeset
|
30 if isinstance(thing, str): |
6ff6e1d6b5b8
templater: move stringify() to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents:
36919
diff
changeset
|
31 # This is only reachable on Python 3 (otherwise |
6ff6e1d6b5b8
templater: move stringify() to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents:
36919
diff
changeset
|
32 # isinstance(thing, bytes) would have been true), and is |
6ff6e1d6b5b8
templater: move stringify() to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents:
36919
diff
changeset
|
33 # here to prevent infinite recursion bugs on Python 3. |
6ff6e1d6b5b8
templater: move stringify() to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents:
36919
diff
changeset
|
34 raise error.ProgrammingError( |
6ff6e1d6b5b8
templater: move stringify() to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents:
36919
diff
changeset
|
35 'stringify got unexpected unicode string: %r' % thing) |
6ff6e1d6b5b8
templater: move stringify() to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents:
36919
diff
changeset
|
36 return "".join([stringify(t) for t in thing if t is not None]) |
6ff6e1d6b5b8
templater: move stringify() to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents:
36919
diff
changeset
|
37 if thing is None: |
6ff6e1d6b5b8
templater: move stringify() to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents:
36919
diff
changeset
|
38 return "" |
6ff6e1d6b5b8
templater: move stringify() to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents:
36919
diff
changeset
|
39 return pycompat.bytestr(thing) |
6ff6e1d6b5b8
templater: move stringify() to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents:
36919
diff
changeset
|
40 |
31927
2abc556dbe92
templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents:
31926
diff
changeset
|
41 def findsymbolicname(arg): |
2abc556dbe92
templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents:
31926
diff
changeset
|
42 """Find symbolic name for the given compiled expression; returns None |
2abc556dbe92
templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents:
31926
diff
changeset
|
43 if nothing found reliably""" |
2abc556dbe92
templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents:
31926
diff
changeset
|
44 while True: |
2abc556dbe92
templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents:
31926
diff
changeset
|
45 func, data = arg |
2abc556dbe92
templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents:
31926
diff
changeset
|
46 if func is runsymbol: |
2abc556dbe92
templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents:
31926
diff
changeset
|
47 return data |
2abc556dbe92
templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents:
31926
diff
changeset
|
48 elif func is runfilter: |
2abc556dbe92
templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents:
31926
diff
changeset
|
49 arg = data[0] |
2abc556dbe92
templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents:
31926
diff
changeset
|
50 else: |
2abc556dbe92
templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents:
31926
diff
changeset
|
51 return None |
2abc556dbe92
templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents:
31926
diff
changeset
|
52 |
34333
e60c601953d7
templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents:
34332
diff
changeset
|
53 def evalrawexp(context, mapping, arg): |
e60c601953d7
templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents:
34332
diff
changeset
|
54 """Evaluate given argument as a bare template object which may require |
e60c601953d7
templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents:
34332
diff
changeset
|
55 further processing (such as folding generator of strings)""" |
26124
604a7c941103
templater: extract helper that evaluates filter or function argument
Yuya Nishihara <yuya@tcha.org>
parents:
26106
diff
changeset
|
56 func, data = arg |
34333
e60c601953d7
templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents:
34332
diff
changeset
|
57 return func(context, mapping, data) |
e60c601953d7
templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents:
34332
diff
changeset
|
58 |
e60c601953d7
templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents:
34332
diff
changeset
|
59 def evalfuncarg(context, mapping, arg): |
e60c601953d7
templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents:
34332
diff
changeset
|
60 """Evaluate given argument as value type""" |
e60c601953d7
templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents:
34332
diff
changeset
|
61 thing = evalrawexp(context, mapping, arg) |
34337
89aec1834a86
templatekw: add new-style template expansion to {manifest}
Yuya Nishihara <yuya@tcha.org>
parents:
34336
diff
changeset
|
62 thing = templatekw.unwrapvalue(thing) |
34333
e60c601953d7
templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents:
34332
diff
changeset
|
63 # evalrawexp() may return string, generator of strings or arbitrary object |
e60c601953d7
templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents:
34332
diff
changeset
|
64 # such as date tuple, but filter does not want generator. |
26124
604a7c941103
templater: extract helper that evaluates filter or function argument
Yuya Nishihara <yuya@tcha.org>
parents:
26106
diff
changeset
|
65 if isinstance(thing, types.GeneratorType): |
604a7c941103
templater: extract helper that evaluates filter or function argument
Yuya Nishihara <yuya@tcha.org>
parents:
26106
diff
changeset
|
66 thing = stringify(thing) |
604a7c941103
templater: extract helper that evaluates filter or function argument
Yuya Nishihara <yuya@tcha.org>
parents:
26106
diff
changeset
|
67 return thing |
604a7c941103
templater: extract helper that evaluates filter or function argument
Yuya Nishihara <yuya@tcha.org>
parents:
26106
diff
changeset
|
68 |
29827
034412ca28c3
templater: fix if() to not evaluate False as bool('False')
Yuya Nishihara <yuya@tcha.org>
parents:
29826
diff
changeset
|
69 def evalboolean(context, mapping, arg): |
29828
cc11079644fc
templater: make pad() evaluate boolean argument (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
29827
diff
changeset
|
70 """Evaluate given argument as boolean, but also takes boolean literals""" |
29827
034412ca28c3
templater: fix if() to not evaluate False as bool('False')
Yuya Nishihara <yuya@tcha.org>
parents:
29826
diff
changeset
|
71 func, data = arg |
29828
cc11079644fc
templater: make pad() evaluate boolean argument (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
29827
diff
changeset
|
72 if func is runsymbol: |
cc11079644fc
templater: make pad() evaluate boolean argument (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
29827
diff
changeset
|
73 thing = func(context, mapping, data, default=None) |
cc11079644fc
templater: make pad() evaluate boolean argument (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
29827
diff
changeset
|
74 if thing is None: |
cc11079644fc
templater: make pad() evaluate boolean argument (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
29827
diff
changeset
|
75 # not a template keyword, takes as a boolean literal |
cc11079644fc
templater: make pad() evaluate boolean argument (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
29827
diff
changeset
|
76 thing = util.parsebool(data) |
cc11079644fc
templater: make pad() evaluate boolean argument (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
29827
diff
changeset
|
77 else: |
cc11079644fc
templater: make pad() evaluate boolean argument (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
29827
diff
changeset
|
78 thing = func(context, mapping, data) |
34337
89aec1834a86
templatekw: add new-style template expansion to {manifest}
Yuya Nishihara <yuya@tcha.org>
parents:
34336
diff
changeset
|
79 thing = templatekw.unwrapvalue(thing) |
29827
034412ca28c3
templater: fix if() to not evaluate False as bool('False')
Yuya Nishihara <yuya@tcha.org>
parents:
29826
diff
changeset
|
80 if isinstance(thing, bool): |
034412ca28c3
templater: fix if() to not evaluate False as bool('False')
Yuya Nishihara <yuya@tcha.org>
parents:
29826
diff
changeset
|
81 return thing |
034412ca28c3
templater: fix if() to not evaluate False as bool('False')
Yuya Nishihara <yuya@tcha.org>
parents:
29826
diff
changeset
|
82 # other objects are evaluated as strings, which means 0 is True, but |
034412ca28c3
templater: fix if() to not evaluate False as bool('False')
Yuya Nishihara <yuya@tcha.org>
parents:
29826
diff
changeset
|
83 # empty dict/list should be False as they are expected to be '' |
034412ca28c3
templater: fix if() to not evaluate False as bool('False')
Yuya Nishihara <yuya@tcha.org>
parents:
29826
diff
changeset
|
84 return bool(stringify(thing)) |
034412ca28c3
templater: fix if() to not evaluate False as bool('False')
Yuya Nishihara <yuya@tcha.org>
parents:
29826
diff
changeset
|
85 |
34581
ee0d74083a22
templater: store revisions as ints so min/max won't compare them as strings
Yuya Nishihara <yuya@tcha.org>
parents:
34536
diff
changeset
|
86 def evalinteger(context, mapping, arg, err=None): |
28344
ac371d4c007f
templater: drop redundant type conversion when evaluating integer argument
Yuya Nishihara <yuya@tcha.org>
parents:
28343
diff
changeset
|
87 v = evalfuncarg(context, mapping, arg) |
28343
a6c2310b3827
templater: factor out function that evaluates argument as integer
Yuya Nishihara <yuya@tcha.org>
parents:
28334
diff
changeset
|
88 try: |
28344
ac371d4c007f
templater: drop redundant type conversion when evaluating integer argument
Yuya Nishihara <yuya@tcha.org>
parents:
28343
diff
changeset
|
89 return int(v) |
ac371d4c007f
templater: drop redundant type conversion when evaluating integer argument
Yuya Nishihara <yuya@tcha.org>
parents:
28343
diff
changeset
|
90 except (TypeError, ValueError): |
34581
ee0d74083a22
templater: store revisions as ints so min/max won't compare them as strings
Yuya Nishihara <yuya@tcha.org>
parents:
34536
diff
changeset
|
91 raise error.ParseError(err or _('not an integer')) |
28343
a6c2310b3827
templater: factor out function that evaluates argument as integer
Yuya Nishihara <yuya@tcha.org>
parents:
28334
diff
changeset
|
92 |
28348
ccedb17a5657
templater: factor out thin helper that evaluates argument as string
Yuya Nishihara <yuya@tcha.org>
parents:
28346
diff
changeset
|
93 def evalstring(context, mapping, arg): |
34333
e60c601953d7
templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents:
34332
diff
changeset
|
94 return stringify(evalrawexp(context, mapping, arg)) |
28348
ccedb17a5657
templater: factor out thin helper that evaluates argument as string
Yuya Nishihara <yuya@tcha.org>
parents:
28346
diff
changeset
|
95 |
28373
9a9dd71e882c
templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents:
28349
diff
changeset
|
96 def evalstringliteral(context, mapping, arg): |
9a9dd71e882c
templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents:
28349
diff
changeset
|
97 """Evaluate given argument as string template, but returns symbol name |
9a9dd71e882c
templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents:
28349
diff
changeset
|
98 if it is unknown""" |
9a9dd71e882c
templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents:
28349
diff
changeset
|
99 func, data = arg |
9a9dd71e882c
templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents:
28349
diff
changeset
|
100 if func is runsymbol: |
9a9dd71e882c
templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents:
28349
diff
changeset
|
101 thing = func(context, mapping, data, default=data) |
9a9dd71e882c
templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents:
28349
diff
changeset
|
102 else: |
9a9dd71e882c
templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents:
28349
diff
changeset
|
103 thing = func(context, mapping, data) |
9a9dd71e882c
templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents:
28349
diff
changeset
|
104 return stringify(thing) |
9a9dd71e882c
templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents:
28349
diff
changeset
|
105 |
34581
ee0d74083a22
templater: store revisions as ints so min/max won't compare them as strings
Yuya Nishihara <yuya@tcha.org>
parents:
34536
diff
changeset
|
106 _evalfuncbytype = { |
ee0d74083a22
templater: store revisions as ints so min/max won't compare them as strings
Yuya Nishihara <yuya@tcha.org>
parents:
34536
diff
changeset
|
107 bool: evalboolean, |
ee0d74083a22
templater: store revisions as ints so min/max won't compare them as strings
Yuya Nishihara <yuya@tcha.org>
parents:
34536
diff
changeset
|
108 bytes: evalstring, |
ee0d74083a22
templater: store revisions as ints so min/max won't compare them as strings
Yuya Nishihara <yuya@tcha.org>
parents:
34536
diff
changeset
|
109 int: evalinteger, |
ee0d74083a22
templater: store revisions as ints so min/max won't compare them as strings
Yuya Nishihara <yuya@tcha.org>
parents:
34536
diff
changeset
|
110 } |
ee0d74083a22
templater: store revisions as ints so min/max won't compare them as strings
Yuya Nishihara <yuya@tcha.org>
parents:
34536
diff
changeset
|
111 |
ee0d74083a22
templater: store revisions as ints so min/max won't compare them as strings
Yuya Nishihara <yuya@tcha.org>
parents:
34536
diff
changeset
|
112 def evalastype(context, mapping, arg, typ): |
ee0d74083a22
templater: store revisions as ints so min/max won't compare them as strings
Yuya Nishihara <yuya@tcha.org>
parents:
34536
diff
changeset
|
113 """Evaluate given argument and coerce its type""" |
ee0d74083a22
templater: store revisions as ints so min/max won't compare them as strings
Yuya Nishihara <yuya@tcha.org>
parents:
34536
diff
changeset
|
114 try: |
ee0d74083a22
templater: store revisions as ints so min/max won't compare them as strings
Yuya Nishihara <yuya@tcha.org>
parents:
34536
diff
changeset
|
115 f = _evalfuncbytype[typ] |
ee0d74083a22
templater: store revisions as ints so min/max won't compare them as strings
Yuya Nishihara <yuya@tcha.org>
parents:
34536
diff
changeset
|
116 except KeyError: |
ee0d74083a22
templater: store revisions as ints so min/max won't compare them as strings
Yuya Nishihara <yuya@tcha.org>
parents:
34536
diff
changeset
|
117 raise error.ProgrammingError('invalid type specified: %r' % typ) |
ee0d74083a22
templater: store revisions as ints so min/max won't compare them as strings
Yuya Nishihara <yuya@tcha.org>
parents:
34536
diff
changeset
|
118 return f(context, mapping, arg) |
ee0d74083a22
templater: store revisions as ints so min/max won't compare them as strings
Yuya Nishihara <yuya@tcha.org>
parents:
34536
diff
changeset
|
119 |
25002
829faf8ab605
templater: tokenize decimal integer literal (issue4638) (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
25001
diff
changeset
|
120 def runinteger(context, mapping, data): |
829faf8ab605
templater: tokenize decimal integer literal (issue4638) (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
25001
diff
changeset
|
121 return int(data) |
829faf8ab605
templater: tokenize decimal integer literal (issue4638) (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
25001
diff
changeset
|
122 |
13176
895f54a79c6e
templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents:
13175
diff
changeset
|
123 def runstring(context, mapping, data): |
895f54a79c6e
templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents:
13175
diff
changeset
|
124 return data |
895f54a79c6e
templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents:
13175
diff
changeset
|
125 |
27939
7ed3a3c0cef1
templater: abort if infinite recursion detected while evaluation (issue4758)
Yuya Nishihara <yuya@tcha.org>
parents:
27892
diff
changeset
|
126 def _recursivesymbolblocker(key): |
7ed3a3c0cef1
templater: abort if infinite recursion detected while evaluation (issue4758)
Yuya Nishihara <yuya@tcha.org>
parents:
27892
diff
changeset
|
127 def showrecursion(**args): |
7ed3a3c0cef1
templater: abort if infinite recursion detected while evaluation (issue4758)
Yuya Nishihara <yuya@tcha.org>
parents:
27892
diff
changeset
|
128 raise error.Abort(_("recursive reference '%s' in template") % key) |
7ed3a3c0cef1
templater: abort if infinite recursion detected while evaluation (issue4758)
Yuya Nishihara <yuya@tcha.org>
parents:
27892
diff
changeset
|
129 return showrecursion |
7ed3a3c0cef1
templater: abort if infinite recursion detected while evaluation (issue4758)
Yuya Nishihara <yuya@tcha.org>
parents:
27892
diff
changeset
|
130 |
28373
9a9dd71e882c
templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents:
28349
diff
changeset
|
131 def runsymbol(context, mapping, key, default=''): |
35471
d6cfa722b044
templater: look up mapping table through template engine
Yuya Nishihara <yuya@tcha.org>
parents:
35421
diff
changeset
|
132 v = context.symbol(mapping, key) |
19770
0361163efbaf
templater: support using templates with non-standard names from map file
Alexander Plavin <alexander@plav.in>
parents:
19390
diff
changeset
|
133 if v is None: |
27939
7ed3a3c0cef1
templater: abort if infinite recursion detected while evaluation (issue4758)
Yuya Nishihara <yuya@tcha.org>
parents:
27892
diff
changeset
|
134 # put poison to cut recursion. we can't move this to parsing phase |
7ed3a3c0cef1
templater: abort if infinite recursion detected while evaluation (issue4758)
Yuya Nishihara <yuya@tcha.org>
parents:
27892
diff
changeset
|
135 # because "x = {x}" is allowed if "x" is a keyword. (issue4758) |
7ed3a3c0cef1
templater: abort if infinite recursion detected while evaluation (issue4758)
Yuya Nishihara <yuya@tcha.org>
parents:
27892
diff
changeset
|
136 safemapping = mapping.copy() |
7ed3a3c0cef1
templater: abort if infinite recursion detected while evaluation (issue4758)
Yuya Nishihara <yuya@tcha.org>
parents:
27892
diff
changeset
|
137 safemapping[key] = _recursivesymbolblocker(key) |
19770
0361163efbaf
templater: support using templates with non-standard names from map file
Alexander Plavin <alexander@plav.in>
parents:
19390
diff
changeset
|
138 try: |
27939
7ed3a3c0cef1
templater: abort if infinite recursion detected while evaluation (issue4758)
Yuya Nishihara <yuya@tcha.org>
parents:
27892
diff
changeset
|
139 v = context.process(key, safemapping) |
19770
0361163efbaf
templater: support using templates with non-standard names from map file
Alexander Plavin <alexander@plav.in>
parents:
19390
diff
changeset
|
140 except TemplateNotFound: |
28373
9a9dd71e882c
templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents:
28349
diff
changeset
|
141 v = default |
36475
e8d37838f5df
templatekw: add 'requires' flag to switch to exception-safe interface
Yuya Nishihara <yuya@tcha.org>
parents:
36474
diff
changeset
|
142 if callable(v) and getattr(v, '_requires', None) is None: |
e8d37838f5df
templatekw: add 'requires' flag to switch to exception-safe interface
Yuya Nishihara <yuya@tcha.org>
parents:
36474
diff
changeset
|
143 # old templatekw: expand all keywords and resources |
35472
32c278eb876f
templater: keep default resources per template engine (API)
Yuya Nishihara <yuya@tcha.org>
parents:
35471
diff
changeset
|
144 props = context._resources.copy() |
32c278eb876f
templater: keep default resources per template engine (API)
Yuya Nishihara <yuya@tcha.org>
parents:
35471
diff
changeset
|
145 props.update(mapping) |
35588
dadbf213a765
py3: convert dict keys' to str before passing as kwargs
Pulkit Goyal <7895pulkit@gmail.com>
parents:
35485
diff
changeset
|
146 return v(**pycompat.strkwargs(props)) |
36475
e8d37838f5df
templatekw: add 'requires' flag to switch to exception-safe interface
Yuya Nishihara <yuya@tcha.org>
parents:
36474
diff
changeset
|
147 if callable(v): |
e8d37838f5df
templatekw: add 'requires' flag to switch to exception-safe interface
Yuya Nishihara <yuya@tcha.org>
parents:
36474
diff
changeset
|
148 # new templatekw |
e8d37838f5df
templatekw: add 'requires' flag to switch to exception-safe interface
Yuya Nishihara <yuya@tcha.org>
parents:
36474
diff
changeset
|
149 try: |
e8d37838f5df
templatekw: add 'requires' flag to switch to exception-safe interface
Yuya Nishihara <yuya@tcha.org>
parents:
36474
diff
changeset
|
150 return v(context, mapping) |
e8d37838f5df
templatekw: add 'requires' flag to switch to exception-safe interface
Yuya Nishihara <yuya@tcha.org>
parents:
36474
diff
changeset
|
151 except ResourceUnavailable: |
e8d37838f5df
templatekw: add 'requires' flag to switch to exception-safe interface
Yuya Nishihara <yuya@tcha.org>
parents:
36474
diff
changeset
|
152 # unsupported keyword is mapped to empty just like unknown keyword |
e8d37838f5df
templatekw: add 'requires' flag to switch to exception-safe interface
Yuya Nishihara <yuya@tcha.org>
parents:
36474
diff
changeset
|
153 return None |
13176
895f54a79c6e
templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents:
13175
diff
changeset
|
154 return v |
895f54a79c6e
templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents:
13175
diff
changeset
|
155 |
25595
a7dd6692e5cb
templater: move runtemplate function out of buildmap/runmap pair
Yuya Nishihara <yuya@tcha.org>
parents:
25580
diff
changeset
|
156 def runtemplate(context, mapping, template): |
34333
e60c601953d7
templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents:
34332
diff
changeset
|
157 for arg in template: |
e60c601953d7
templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents:
34332
diff
changeset
|
158 yield evalrawexp(context, mapping, arg) |
25595
a7dd6692e5cb
templater: move runtemplate function out of buildmap/runmap pair
Yuya Nishihara <yuya@tcha.org>
parents:
25580
diff
changeset
|
159 |
13176
895f54a79c6e
templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents:
13175
diff
changeset
|
160 def runfilter(context, mapping, data): |
26125
c990afab2243
templater: drop unneeded destructuring of argument tuple at buildfilter
Yuya Nishihara <yuya@tcha.org>
parents:
26124
diff
changeset
|
161 arg, filt = data |
c990afab2243
templater: drop unneeded destructuring of argument tuple at buildfilter
Yuya Nishihara <yuya@tcha.org>
parents:
26124
diff
changeset
|
162 thing = evalfuncarg(context, mapping, arg) |
17383
099c778ceb33
templater: abort when a template filter raises an exception (issue2987)
Neil Kodner <neilk@fb.com>
parents:
17334
diff
changeset
|
163 try: |
24280
6c55e37ba5f2
templater: allow piping generator-type function output to filters
Yuya Nishihara <yuya@tcha.org>
parents:
24240
diff
changeset
|
164 return filt(thing) |
17383
099c778ceb33
templater: abort when a template filter raises an exception (issue2987)
Neil Kodner <neilk@fb.com>
parents:
17334
diff
changeset
|
165 except (ValueError, AttributeError, TypeError): |
31927
2abc556dbe92
templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents:
31926
diff
changeset
|
166 sym = findsymbolicname(arg) |
2abc556dbe92
templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents:
31926
diff
changeset
|
167 if sym: |
2abc556dbe92
templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents:
31926
diff
changeset
|
168 msg = (_("template filter '%s' is not compatible with keyword '%s'") |
34838
d3ea6a1c798f
templater: use pycompat.sysbytes to bytes-ify some __name__ attrs
Augie Fackler <augie@google.com>
parents:
34808
diff
changeset
|
169 % (pycompat.sysbytes(filt.__name__), sym)) |
17383
099c778ceb33
templater: abort when a template filter raises an exception (issue2987)
Neil Kodner <neilk@fb.com>
parents:
17334
diff
changeset
|
170 else: |
34838
d3ea6a1c798f
templater: use pycompat.sysbytes to bytes-ify some __name__ attrs
Augie Fackler <augie@google.com>
parents:
34808
diff
changeset
|
171 msg = (_("incompatible use of template filter '%s'") |
d3ea6a1c798f
templater: use pycompat.sysbytes to bytes-ify some __name__ attrs
Augie Fackler <augie@google.com>
parents:
34808
diff
changeset
|
172 % pycompat.sysbytes(filt.__name__)) |
31927
2abc556dbe92
templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents:
31926
diff
changeset
|
173 raise error.Abort(msg) |
13176
895f54a79c6e
templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents:
13175
diff
changeset
|
174 |
895f54a79c6e
templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents:
13175
diff
changeset
|
175 def runmap(context, mapping, data): |
34333
e60c601953d7
templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents:
34332
diff
changeset
|
176 darg, targ = data |
e60c601953d7
templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents:
34332
diff
changeset
|
177 d = evalrawexp(context, mapping, darg) |
27891
ac8c0ee5c3b8
templater: make _hybrid not callable to avoid conflicting semantics
Yuya Nishihara <yuya@tcha.org>
parents:
27637
diff
changeset
|
178 if util.safehasattr(d, 'itermaps'): |
28349
7cb2f2438f85
templater: handle exception when applying map operator to non-iterable object
Yuya Nishihara <yuya@tcha.org>
parents:
28348
diff
changeset
|
179 diter = d.itermaps() |
7cb2f2438f85
templater: handle exception when applying map operator to non-iterable object
Yuya Nishihara <yuya@tcha.org>
parents:
28348
diff
changeset
|
180 else: |
7cb2f2438f85
templater: handle exception when applying map operator to non-iterable object
Yuya Nishihara <yuya@tcha.org>
parents:
28348
diff
changeset
|
181 try: |
7cb2f2438f85
templater: handle exception when applying map operator to non-iterable object
Yuya Nishihara <yuya@tcha.org>
parents:
28348
diff
changeset
|
182 diter = iter(d) |
7cb2f2438f85
templater: handle exception when applying map operator to non-iterable object
Yuya Nishihara <yuya@tcha.org>
parents:
28348
diff
changeset
|
183 except TypeError: |
34333
e60c601953d7
templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents:
34332
diff
changeset
|
184 sym = findsymbolicname(darg) |
34331
e473f482b9b3
templater: use helper function to get name of non-iterable keyword
Yuya Nishihara <yuya@tcha.org>
parents:
34294
diff
changeset
|
185 if sym: |
e473f482b9b3
templater: use helper function to get name of non-iterable keyword
Yuya Nishihara <yuya@tcha.org>
parents:
34294
diff
changeset
|
186 raise error.ParseError(_("keyword '%s' is not iterable") % sym) |
28349
7cb2f2438f85
templater: handle exception when applying map operator to non-iterable object
Yuya Nishihara <yuya@tcha.org>
parents:
28348
diff
changeset
|
187 else: |
7cb2f2438f85
templater: handle exception when applying map operator to non-iterable object
Yuya Nishihara <yuya@tcha.org>
parents:
28348
diff
changeset
|
188 raise error.ParseError(_("%r is not iterable") % d) |
17631
0b241d7a8c62
templating: make new-style templating features work with command line lists
Matt Mackall <mpm@selenic.com>
parents:
17383
diff
changeset
|
189 |
31807
e6eb86b154c5
templater: provide loop counter as "index" keyword
Yuya Nishihara <yuya@tcha.org>
parents:
31806
diff
changeset
|
190 for i, v in enumerate(diter): |
28225
5c11702fe2a3
templater: fix list templating bug
Kostia Balytskyi <ikostia@fb.com>
parents:
28178
diff
changeset
|
191 lm = mapping.copy() |
31807
e6eb86b154c5
templater: provide loop counter as "index" keyword
Yuya Nishihara <yuya@tcha.org>
parents:
31806
diff
changeset
|
192 lm['index'] = i |
31806
8f203b491bb5
templater: rename variable "i" to "v" in runmap()
Yuya Nishihara <yuya@tcha.org>
parents:
31527
diff
changeset
|
193 if isinstance(v, dict): |
8f203b491bb5
templater: rename variable "i" to "v" in runmap()
Yuya Nishihara <yuya@tcha.org>
parents:
31527
diff
changeset
|
194 lm.update(v) |
17991
d605a82cf189
hgweb: display diff for a changeset against any parents (issue2810)
Weiwen <weiwen@fb.com>
parents:
17982
diff
changeset
|
195 lm['originalnode'] = mapping.get('node') |
34333
e60c601953d7
templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents:
34332
diff
changeset
|
196 yield evalrawexp(context, lm, targ) |
13176
895f54a79c6e
templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents:
13175
diff
changeset
|
197 else: |
895f54a79c6e
templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents:
13175
diff
changeset
|
198 # v is not an iterable of dicts, this happen when 'key' |
895f54a79c6e
templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents:
13175
diff
changeset
|
199 # has been fully expanded already and format is useless. |
895f54a79c6e
templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents:
13175
diff
changeset
|
200 # If so, return the expanded value. |
31806
8f203b491bb5
templater: rename variable "i" to "v" in runmap()
Yuya Nishihara <yuya@tcha.org>
parents:
31527
diff
changeset
|
201 yield v |
13176
895f54a79c6e
templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents:
13175
diff
changeset
|
202 |
34535
78590585c0db
templater: add dot operator to easily access a sub item
Yuya Nishihara <yuya@tcha.org>
parents:
34534
diff
changeset
|
203 def runmember(context, mapping, data): |
78590585c0db
templater: add dot operator to easily access a sub item
Yuya Nishihara <yuya@tcha.org>
parents:
34534
diff
changeset
|
204 darg, memb = data |
78590585c0db
templater: add dot operator to easily access a sub item
Yuya Nishihara <yuya@tcha.org>
parents:
34534
diff
changeset
|
205 d = evalrawexp(context, mapping, darg) |
78590585c0db
templater: add dot operator to easily access a sub item
Yuya Nishihara <yuya@tcha.org>
parents:
34534
diff
changeset
|
206 if util.safehasattr(d, 'tomap'): |
78590585c0db
templater: add dot operator to easily access a sub item
Yuya Nishihara <yuya@tcha.org>
parents:
34534
diff
changeset
|
207 lm = mapping.copy() |
78590585c0db
templater: add dot operator to easily access a sub item
Yuya Nishihara <yuya@tcha.org>
parents:
34534
diff
changeset
|
208 lm.update(d.tomap()) |
78590585c0db
templater: add dot operator to easily access a sub item
Yuya Nishihara <yuya@tcha.org>
parents:
34534
diff
changeset
|
209 return runsymbol(context, lm, memb) |
34536
4c1cfe54c08d
templater: extend dot operator as a short for get(dict, key)
Yuya Nishihara <yuya@tcha.org>
parents:
34535
diff
changeset
|
210 if util.safehasattr(d, 'get'): |
36919
da2977e674a3
templater: extract template evaluation utility to new module
Yuya Nishihara <yuya@tcha.org>
parents:
36918
diff
changeset
|
211 return getdictitem(d, memb) |
34535
78590585c0db
templater: add dot operator to easily access a sub item
Yuya Nishihara <yuya@tcha.org>
parents:
34534
diff
changeset
|
212 |
78590585c0db
templater: add dot operator to easily access a sub item
Yuya Nishihara <yuya@tcha.org>
parents:
34534
diff
changeset
|
213 sym = findsymbolicname(darg) |
78590585c0db
templater: add dot operator to easily access a sub item
Yuya Nishihara <yuya@tcha.org>
parents:
34534
diff
changeset
|
214 if sym: |
78590585c0db
templater: add dot operator to easily access a sub item
Yuya Nishihara <yuya@tcha.org>
parents:
34534
diff
changeset
|
215 raise error.ParseError(_("keyword '%s' has no member") % sym) |
78590585c0db
templater: add dot operator to easily access a sub item
Yuya Nishihara <yuya@tcha.org>
parents:
34534
diff
changeset
|
216 else: |
36574
ab7f86a748e6
py3: drop b'' from error message generated by templater.runmember()
Yuya Nishihara <yuya@tcha.org>
parents:
36573
diff
changeset
|
217 raise error.ParseError(_("%r has no member") % pycompat.bytestr(d)) |
34535
78590585c0db
templater: add dot operator to easily access a sub item
Yuya Nishihara <yuya@tcha.org>
parents:
34534
diff
changeset
|
218 |
30115
8e42dfde93d1
templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents:
30083
diff
changeset
|
219 def runnegate(context, mapping, data): |
8e42dfde93d1
templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents:
30083
diff
changeset
|
220 data = evalinteger(context, mapping, data, |
8e42dfde93d1
templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents:
30083
diff
changeset
|
221 _('negation needs an integer argument')) |
8e42dfde93d1
templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents:
30083
diff
changeset
|
222 return -data |
8e42dfde93d1
templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents:
30083
diff
changeset
|
223 |
8e42dfde93d1
templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents:
30083
diff
changeset
|
224 def runarithmetic(context, mapping, data): |
8e42dfde93d1
templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents:
30083
diff
changeset
|
225 func, left, right = data |
8e42dfde93d1
templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents:
30083
diff
changeset
|
226 left = evalinteger(context, mapping, left, |
8e42dfde93d1
templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents:
30083
diff
changeset
|
227 _('arithmetic only defined on integers')) |
8e42dfde93d1
templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents:
30083
diff
changeset
|
228 right = evalinteger(context, mapping, right, |
8e42dfde93d1
templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents:
30083
diff
changeset
|
229 _('arithmetic only defined on integers')) |
30116
1c01fa29630f
templater: handle division by zero in arithmetic
Simon Farnsworth <simonfar@fb.com>
parents:
30115
diff
changeset
|
230 try: |
1c01fa29630f
templater: handle division by zero in arithmetic
Simon Farnsworth <simonfar@fb.com>
parents:
30115
diff
changeset
|
231 return func(left, right) |
1c01fa29630f
templater: handle division by zero in arithmetic
Simon Farnsworth <simonfar@fb.com>
parents:
30115
diff
changeset
|
232 except ZeroDivisionError: |
1c01fa29630f
templater: handle division by zero in arithmetic
Simon Farnsworth <simonfar@fb.com>
parents:
30115
diff
changeset
|
233 raise error.Abort(_('division by zero is not defined')) |
30115
8e42dfde93d1
templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents:
30083
diff
changeset
|
234 |
36919
da2977e674a3
templater: extract template evaluation utility to new module
Yuya Nishihara <yuya@tcha.org>
parents:
36918
diff
changeset
|
235 def getdictitem(dictarg, key): |
34534
b3073e175c17
templater: wrap get/min/max result so map operation can apply to element
Yuya Nishihara <yuya@tcha.org>
parents:
34459
diff
changeset
|
236 val = dictarg.get(key) |
b3073e175c17
templater: wrap get/min/max result so map operation can apply to element
Yuya Nishihara <yuya@tcha.org>
parents:
34459
diff
changeset
|
237 if val is None: |
b3073e175c17
templater: wrap get/min/max result so map operation can apply to element
Yuya Nishihara <yuya@tcha.org>
parents:
34459
diff
changeset
|
238 return |
b3073e175c17
templater: wrap get/min/max result so map operation can apply to element
Yuya Nishihara <yuya@tcha.org>
parents:
34459
diff
changeset
|
239 return templatekw.wraphybridvalue(dictarg, key, val) |