annotate mercurial/templateutil.py @ 38301:f9c426385853

templater: abstract truth testing to fix {if(list_of_empty_strings)} Non-empty list should always be True even if it's stringified to ''. Spotted by Martin von Zweigbergk.
author Yuya Nishihara <yuya@tcha.org>
date Sat, 09 Jun 2018 13:34:47 +0900
parents 851fc9d42d6d
children 88e7105b5cd9
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 9842
diff changeset
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
37275
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
10 import abc
17982
e06e9fd2d99f template engine: convert generator-based iterator to list-based iterator
Weiwen <weiwen@fb.com>
parents: 17890
diff changeset
11 import types
25985
7eb357b5f774 templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
12
7eb357b5f774 templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
13 from .i18n import _
7eb357b5f774 templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
14 from . import (
7eb357b5f774 templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
15 error,
30620
bb77654dc7ae py3: replace os.sep with pycompat.ossep (part 3 of 4)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30342
diff changeset
16 pycompat,
25985
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 )
37087
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 37077
diff changeset
19 from .utils import (
37226
67efce231633 templater: factor out function that parses argument as date tuple
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
20 dateutil,
37087
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 37077
diff changeset
21 stringutil,
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 37077
diff changeset
22 )
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
23
36474
717a279c0c21 templater: specialize ResourceUnavailable error so that it can be caught
Yuya Nishihara <yuya@tcha.org>
parents: 36473
diff changeset
24 class ResourceUnavailable(error.Abort):
717a279c0c21 templater: specialize ResourceUnavailable error so that it can be caught
Yuya Nishihara <yuya@tcha.org>
parents: 36473
diff changeset
25 pass
717a279c0c21 templater: specialize ResourceUnavailable error so that it can be caught
Yuya Nishihara <yuya@tcha.org>
parents: 36473
diff changeset
26
36473
8dbd97aef915 templater: move specialized exception types to top
Yuya Nishihara <yuya@tcha.org>
parents: 36278
diff changeset
27 class TemplateNotFound(error.Abort):
8dbd97aef915 templater: move specialized exception types to top
Yuya Nishihara <yuya@tcha.org>
parents: 36278
diff changeset
28 pass
8dbd97aef915 templater: move specialized exception types to top
Yuya Nishihara <yuya@tcha.org>
parents: 36278
diff changeset
29
37275
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
30 class wrapped(object):
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
31 """Object requiring extra conversion prior to displaying or processing
37281
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37280
diff changeset
32 as value
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37280
diff changeset
33
38282
630c62804383 templater: inline unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 38281
diff changeset
34 Use unwrapvalue() or unwrapastype() to obtain the inner object.
37281
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37280
diff changeset
35 """
37275
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
36
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
37 __metaclass__ = abc.ABCMeta
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
38
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
39 @abc.abstractmethod
38279
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38278
diff changeset
40 def contains(self, context, mapping, item):
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38278
diff changeset
41 """Test if the specified item is in self
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38278
diff changeset
42
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38278
diff changeset
43 The item argument may be a wrapped object.
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38278
diff changeset
44 """
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38278
diff changeset
45
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38278
diff changeset
46 @abc.abstractmethod
38255
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38254
diff changeset
47 def getmember(self, context, mapping, key):
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38254
diff changeset
48 """Return a member item for the specified key
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38254
diff changeset
49
38256
688fbb758ba9 templater: resolve type of dict key in getmember()
Yuya Nishihara <yuya@tcha.org>
parents: 38255
diff changeset
50 The key argument may be a wrapped object.
38255
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38254
diff changeset
51 A returned object may be either a wrapped object or a pure value
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38254
diff changeset
52 depending on the self type.
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38254
diff changeset
53 """
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38254
diff changeset
54
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38254
diff changeset
55 @abc.abstractmethod
38277
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
56 def getmin(self, context, mapping):
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
57 """Return the smallest item, which may be either a wrapped or a pure
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
58 value depending on the self type"""
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
59
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
60 @abc.abstractmethod
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
61 def getmax(self, context, mapping):
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
62 """Return the largest item, which may be either a wrapped or a pure
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
63 value depending on the self type"""
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
64
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
65 @abc.abstractmethod
37324
c2f74b8f6b7f templater: pass context to itermaps() for future extension
Yuya Nishihara <yuya@tcha.org>
parents: 37323
diff changeset
66 def itermaps(self, context):
37323
8c31b434697f templater: define interface for objects which act as iterator of mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37281
diff changeset
67 """Yield each template mapping"""
8c31b434697f templater: define interface for objects which act as iterator of mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37281
diff changeset
68
8c31b434697f templater: define interface for objects which act as iterator of mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37281
diff changeset
69 @abc.abstractmethod
37327
ebf139cbd4a1 templater: abstract away from joinfmt
Yuya Nishihara <yuya@tcha.org>
parents: 37326
diff changeset
70 def join(self, context, mapping, sep):
ebf139cbd4a1 templater: abstract away from joinfmt
Yuya Nishihara <yuya@tcha.org>
parents: 37326
diff changeset
71 """Join items with the separator; Returns a bytes or (possibly nested)
ebf139cbd4a1 templater: abstract away from joinfmt
Yuya Nishihara <yuya@tcha.org>
parents: 37326
diff changeset
72 generator of bytes
ebf139cbd4a1 templater: abstract away from joinfmt
Yuya Nishihara <yuya@tcha.org>
parents: 37326
diff changeset
73
ebf139cbd4a1 templater: abstract away from joinfmt
Yuya Nishihara <yuya@tcha.org>
parents: 37326
diff changeset
74 A pre-configured template may be rendered per item if this container
ebf139cbd4a1 templater: abstract away from joinfmt
Yuya Nishihara <yuya@tcha.org>
parents: 37326
diff changeset
75 holds unprintable items.
ebf139cbd4a1 templater: abstract away from joinfmt
Yuya Nishihara <yuya@tcha.org>
parents: 37326
diff changeset
76 """
ebf139cbd4a1 templater: abstract away from joinfmt
Yuya Nishihara <yuya@tcha.org>
parents: 37326
diff changeset
77
ebf139cbd4a1 templater: abstract away from joinfmt
Yuya Nishihara <yuya@tcha.org>
parents: 37326
diff changeset
78 @abc.abstractmethod
37275
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
79 def show(self, context, mapping):
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
80 """Return a bytes or (possibly nested) generator of bytes representing
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
81 the underlying object
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
82
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
83 A pre-configured template may be rendered if the underlying object is
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
84 not printable.
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
85 """
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
86
37281
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37280
diff changeset
87 @abc.abstractmethod
38301
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38298
diff changeset
88 def tobool(self, context, mapping):
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38298
diff changeset
89 """Return a boolean representation of the inner value"""
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38298
diff changeset
90
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38298
diff changeset
91 @abc.abstractmethod
37281
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37280
diff changeset
92 def tovalue(self, context, mapping):
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37280
diff changeset
93 """Move the inner value object out or create a value representation
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37280
diff changeset
94
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37280
diff changeset
95 A returned value must be serializable by templaterfilters.json().
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37280
diff changeset
96 """
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37280
diff changeset
97
38296
e72697893c93 templater: promote tomap() to an interface type
Yuya Nishihara <yuya@tcha.org>
parents: 38295
diff changeset
98 class mappable(object):
e72697893c93 templater: promote tomap() to an interface type
Yuya Nishihara <yuya@tcha.org>
parents: 38295
diff changeset
99 """Object which can be converted to a single template mapping"""
e72697893c93 templater: promote tomap() to an interface type
Yuya Nishihara <yuya@tcha.org>
parents: 38295
diff changeset
100
e72697893c93 templater: promote tomap() to an interface type
Yuya Nishihara <yuya@tcha.org>
parents: 38295
diff changeset
101 def itermaps(self, context):
e72697893c93 templater: promote tomap() to an interface type
Yuya Nishihara <yuya@tcha.org>
parents: 38295
diff changeset
102 yield self.tomap(context)
e72697893c93 templater: promote tomap() to an interface type
Yuya Nishihara <yuya@tcha.org>
parents: 38295
diff changeset
103
e72697893c93 templater: promote tomap() to an interface type
Yuya Nishihara <yuya@tcha.org>
parents: 38295
diff changeset
104 @abc.abstractmethod
e72697893c93 templater: promote tomap() to an interface type
Yuya Nishihara <yuya@tcha.org>
parents: 38295
diff changeset
105 def tomap(self, context):
e72697893c93 templater: promote tomap() to an interface type
Yuya Nishihara <yuya@tcha.org>
parents: 38295
diff changeset
106 """Create a single template mapping representing this"""
e72697893c93 templater: promote tomap() to an interface type
Yuya Nishihara <yuya@tcha.org>
parents: 38295
diff changeset
107
38238
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
108 class wrappedbytes(wrapped):
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
109 """Wrapper for byte string"""
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
110
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
111 def __init__(self, value):
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
112 self._value = value
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
113
38279
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38278
diff changeset
114 def contains(self, context, mapping, item):
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38278
diff changeset
115 item = stringify(context, mapping, item)
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38278
diff changeset
116 return item in self._value
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38278
diff changeset
117
38255
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38254
diff changeset
118 def getmember(self, context, mapping, key):
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38254
diff changeset
119 raise error.ParseError(_('%r is not a dictionary')
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38254
diff changeset
120 % pycompat.bytestr(self._value))
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38254
diff changeset
121
38277
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
122 def getmin(self, context, mapping):
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
123 return self._getby(context, mapping, min)
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
124
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
125 def getmax(self, context, mapping):
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
126 return self._getby(context, mapping, max)
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
127
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
128 def _getby(self, context, mapping, func):
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
129 if not self._value:
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
130 raise error.ParseError(_('empty string'))
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
131 return func(pycompat.iterbytestr(self._value))
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
132
38238
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
133 def itermaps(self, context):
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
134 raise error.ParseError(_('%r is not iterable of mappings')
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
135 % pycompat.bytestr(self._value))
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
136
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
137 def join(self, context, mapping, sep):
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
138 return joinitems(pycompat.iterbytestr(self._value), sep)
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
139
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
140 def show(self, context, mapping):
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
141 return self._value
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
142
38301
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38298
diff changeset
143 def tobool(self, context, mapping):
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38298
diff changeset
144 return bool(self._value)
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38298
diff changeset
145
38238
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
146 def tovalue(self, context, mapping):
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
147 return self._value
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
148
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
149 class wrappedvalue(wrapped):
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
150 """Generic wrapper for pure non-list/dict/bytes value"""
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
151
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
152 def __init__(self, value):
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
153 self._value = value
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
154
38279
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38278
diff changeset
155 def contains(self, context, mapping, item):
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38278
diff changeset
156 raise error.ParseError(_("%r is not iterable") % self._value)
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38278
diff changeset
157
38255
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38254
diff changeset
158 def getmember(self, context, mapping, key):
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38254
diff changeset
159 raise error.ParseError(_('%r is not a dictionary') % self._value)
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38254
diff changeset
160
38277
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
161 def getmin(self, context, mapping):
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
162 raise error.ParseError(_("%r is not iterable") % self._value)
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
163
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
164 def getmax(self, context, mapping):
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
165 raise error.ParseError(_("%r is not iterable") % self._value)
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
166
38238
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
167 def itermaps(self, context):
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
168 raise error.ParseError(_('%r is not iterable of mappings')
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
169 % self._value)
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
170
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
171 def join(self, context, mapping, sep):
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
172 raise error.ParseError(_('%r is not iterable') % self._value)
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
173
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
174 def show(self, context, mapping):
38284
354fad8697fd templater: fix string representation of wrapped None
Yuya Nishihara <yuya@tcha.org>
parents: 38283
diff changeset
175 if self._value is None:
354fad8697fd templater: fix string representation of wrapped None
Yuya Nishihara <yuya@tcha.org>
parents: 38283
diff changeset
176 return b''
38238
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
177 return pycompat.bytestr(self._value)
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
178
38301
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38298
diff changeset
179 def tobool(self, context, mapping):
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38298
diff changeset
180 if self._value is None:
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38298
diff changeset
181 return False
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38298
diff changeset
182 if isinstance(self._value, bool):
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38298
diff changeset
183 return self._value
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38298
diff changeset
184 # otherwise evaluate as string, which means 0 is True
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38298
diff changeset
185 return bool(pycompat.bytestr(self._value))
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38298
diff changeset
186
38238
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
187 def tovalue(self, context, mapping):
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
188 return self._value
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
189
38298
851fc9d42d6d templater: make date wrapper support dot/map operations
Yuya Nishihara <yuya@tcha.org>
parents: 38297
diff changeset
190 class date(mappable, wrapped):
38297
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38296
diff changeset
191 """Wrapper for date tuple"""
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38296
diff changeset
192
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38296
diff changeset
193 def __init__(self, value):
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38296
diff changeset
194 # value may be (float, int), but public interface shouldn't support
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38296
diff changeset
195 # floating-point timestamp
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38296
diff changeset
196 self._unixtime, self._tzoffset = map(int, value)
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38296
diff changeset
197
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38296
diff changeset
198 def contains(self, context, mapping, item):
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38296
diff changeset
199 raise error.ParseError(_('date is not iterable'))
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38296
diff changeset
200
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38296
diff changeset
201 def getmember(self, context, mapping, key):
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38296
diff changeset
202 raise error.ParseError(_('date is not a dictionary'))
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38296
diff changeset
203
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38296
diff changeset
204 def getmin(self, context, mapping):
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38296
diff changeset
205 raise error.ParseError(_('date is not iterable'))
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38296
diff changeset
206
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38296
diff changeset
207 def getmax(self, context, mapping):
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38296
diff changeset
208 raise error.ParseError(_('date is not iterable'))
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38296
diff changeset
209
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38296
diff changeset
210 def join(self, context, mapping, sep):
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38296
diff changeset
211 raise error.ParseError(_("date is not iterable"))
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38296
diff changeset
212
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38296
diff changeset
213 def show(self, context, mapping):
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38296
diff changeset
214 return '%d %d' % (self._unixtime, self._tzoffset)
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38296
diff changeset
215
38298
851fc9d42d6d templater: make date wrapper support dot/map operations
Yuya Nishihara <yuya@tcha.org>
parents: 38297
diff changeset
216 def tomap(self, context):
851fc9d42d6d templater: make date wrapper support dot/map operations
Yuya Nishihara <yuya@tcha.org>
parents: 38297
diff changeset
217 return {'unixtime': self._unixtime, 'tzoffset': self._tzoffset}
851fc9d42d6d templater: make date wrapper support dot/map operations
Yuya Nishihara <yuya@tcha.org>
parents: 38297
diff changeset
218
38301
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38298
diff changeset
219 def tobool(self, context, mapping):
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38298
diff changeset
220 return True
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38298
diff changeset
221
38297
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38296
diff changeset
222 def tovalue(self, context, mapping):
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38296
diff changeset
223 return (self._unixtime, self._tzoffset)
37229
9bcf096a2da2 templatefilters: declare input type as date where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37228
diff changeset
224
37275
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
225 class hybrid(wrapped):
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
226 """Wrapper for list or dict to support legacy template
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
227
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
228 This class allows us to handle both:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
229 - "{files}" (legacy command-line-specific list hack) and
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
230 - "{files % '{file}\n'}" (hgweb-style with inlining and function support)
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
231 and to access raw values:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
232 - "{ifcontains(file, files, ...)}", "{ifcontains(key, extras, ...)}"
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
233 - "{get(extras, key)}"
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
234 - "{files|json}"
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
235 """
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
236
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
237 def __init__(self, gen, values, makemap, joinfmt, keytype=None):
37325
41a5d815d2c1 templater: factor out generator of join()-ed items
Yuya Nishihara <yuya@tcha.org>
parents: 37324
diff changeset
238 self._gen = gen # generator or function returning generator
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
239 self._values = values
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
240 self._makemap = makemap
37329
676664592313 templater: mark .joinfmt as a private attribute
Yuya Nishihara <yuya@tcha.org>
parents: 37327
diff changeset
241 self._joinfmt = joinfmt
38280
49ef1539b84e templater: mark .keytype as a private attribute
Yuya Nishihara <yuya@tcha.org>
parents: 38279
diff changeset
242 self._keytype = keytype # hint for 'x in y' where type(x) is unresolved
37277
8c84dc8264dc templater: mark .gen as a private attribute
Yuya Nishihara <yuya@tcha.org>
parents: 37275
diff changeset
243
38279
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38278
diff changeset
244 def contains(self, context, mapping, item):
38280
49ef1539b84e templater: mark .keytype as a private attribute
Yuya Nishihara <yuya@tcha.org>
parents: 38279
diff changeset
245 item = unwrapastype(context, mapping, item, self._keytype)
38279
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38278
diff changeset
246 return item in self._values
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38278
diff changeset
247
38254
12b6ee9e88f3 templater: move getdictitem() to hybrid class
Yuya Nishihara <yuya@tcha.org>
parents: 38253
diff changeset
248 def getmember(self, context, mapping, key):
12b6ee9e88f3 templater: move getdictitem() to hybrid class
Yuya Nishihara <yuya@tcha.org>
parents: 38253
diff changeset
249 # TODO: maybe split hybrid list/dict types?
12b6ee9e88f3 templater: move getdictitem() to hybrid class
Yuya Nishihara <yuya@tcha.org>
parents: 38253
diff changeset
250 if not util.safehasattr(self._values, 'get'):
12b6ee9e88f3 templater: move getdictitem() to hybrid class
Yuya Nishihara <yuya@tcha.org>
parents: 38253
diff changeset
251 raise error.ParseError(_('not a dictionary'))
38280
49ef1539b84e templater: mark .keytype as a private attribute
Yuya Nishihara <yuya@tcha.org>
parents: 38279
diff changeset
252 key = unwrapastype(context, mapping, key, self._keytype)
38254
12b6ee9e88f3 templater: move getdictitem() to hybrid class
Yuya Nishihara <yuya@tcha.org>
parents: 38253
diff changeset
253 return self._wrapvalue(key, self._values.get(key))
12b6ee9e88f3 templater: move getdictitem() to hybrid class
Yuya Nishihara <yuya@tcha.org>
parents: 38253
diff changeset
254
38277
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
255 def getmin(self, context, mapping):
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
256 return self._getby(context, mapping, min)
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
257
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
258 def getmax(self, context, mapping):
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
259 return self._getby(context, mapping, max)
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
260
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
261 def _getby(self, context, mapping, func):
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
262 if not self._values:
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
263 raise error.ParseError(_('empty sequence'))
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
264 val = func(self._values)
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
265 return self._wrapvalue(val, val)
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
266
38254
12b6ee9e88f3 templater: move getdictitem() to hybrid class
Yuya Nishihara <yuya@tcha.org>
parents: 38253
diff changeset
267 def _wrapvalue(self, key, val):
12b6ee9e88f3 templater: move getdictitem() to hybrid class
Yuya Nishihara <yuya@tcha.org>
parents: 38253
diff changeset
268 if val is None:
12b6ee9e88f3 templater: move getdictitem() to hybrid class
Yuya Nishihara <yuya@tcha.org>
parents: 38253
diff changeset
269 return
38278
80f423a14c90 templater: inline wraphybridvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 38277
diff changeset
270 if util.safehasattr(val, '_makemap'):
80f423a14c90 templater: inline wraphybridvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 38277
diff changeset
271 # a nested hybrid list/dict, which has its own way of map operation
80f423a14c90 templater: inline wraphybridvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 38277
diff changeset
272 return val
38295
0e0d03d09ecd templater: rename mappable to hybriditem as it is the primary use case
Yuya Nishihara <yuya@tcha.org>
parents: 38284
diff changeset
273 return hybriditem(None, key, val, self._makemap)
38254
12b6ee9e88f3 templater: move getdictitem() to hybrid class
Yuya Nishihara <yuya@tcha.org>
parents: 38253
diff changeset
274
37324
c2f74b8f6b7f templater: pass context to itermaps() for future extension
Yuya Nishihara <yuya@tcha.org>
parents: 37323
diff changeset
275 def itermaps(self, context):
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
276 makemap = self._makemap
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
277 for x in self._values:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
278 yield makemap(x)
37275
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
279
37327
ebf139cbd4a1 templater: abstract away from joinfmt
Yuya Nishihara <yuya@tcha.org>
parents: 37326
diff changeset
280 def join(self, context, mapping, sep):
ebf139cbd4a1 templater: abstract away from joinfmt
Yuya Nishihara <yuya@tcha.org>
parents: 37326
diff changeset
281 # TODO: switch gen to (context, mapping) API?
37329
676664592313 templater: mark .joinfmt as a private attribute
Yuya Nishihara <yuya@tcha.org>
parents: 37327
diff changeset
282 return joinitems((self._joinfmt(x) for x in self._values), sep)
37327
ebf139cbd4a1 templater: abstract away from joinfmt
Yuya Nishihara <yuya@tcha.org>
parents: 37326
diff changeset
283
37275
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
284 def show(self, context, mapping):
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
285 # TODO: switch gen to (context, mapping) API?
37277
8c84dc8264dc templater: mark .gen as a private attribute
Yuya Nishihara <yuya@tcha.org>
parents: 37275
diff changeset
286 gen = self._gen
37325
41a5d815d2c1 templater: factor out generator of join()-ed items
Yuya Nishihara <yuya@tcha.org>
parents: 37324
diff changeset
287 if gen is None:
37327
ebf139cbd4a1 templater: abstract away from joinfmt
Yuya Nishihara <yuya@tcha.org>
parents: 37326
diff changeset
288 return self.join(context, mapping, ' ')
37275
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
289 if callable(gen):
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
290 return gen()
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
291 return gen
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
292
38301
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38298
diff changeset
293 def tobool(self, context, mapping):
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38298
diff changeset
294 return bool(self._values)
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38298
diff changeset
295
37281
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37280
diff changeset
296 def tovalue(self, context, mapping):
38281
cf8d210dfac4 templater: drop hybrid-ness on unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 38280
diff changeset
297 # TODO: make it non-recursive for trivial lists/dicts
cf8d210dfac4 templater: drop hybrid-ness on unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 38280
diff changeset
298 xs = self._values
cf8d210dfac4 templater: drop hybrid-ness on unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 38280
diff changeset
299 if util.safehasattr(xs, 'get'):
cf8d210dfac4 templater: drop hybrid-ness on unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 38280
diff changeset
300 return {k: unwrapvalue(context, mapping, v)
cf8d210dfac4 templater: drop hybrid-ness on unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 38280
diff changeset
301 for k, v in xs.iteritems()}
cf8d210dfac4 templater: drop hybrid-ness on unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 38280
diff changeset
302 return [unwrapvalue(context, mapping, x) for x in xs]
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
303
38296
e72697893c93 templater: promote tomap() to an interface type
Yuya Nishihara <yuya@tcha.org>
parents: 38295
diff changeset
304 class hybriditem(mappable, wrapped):
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
305 """Wrapper for non-list/dict object to support map operation
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
306
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
307 This class allows us to handle both:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
308 - "{manifest}"
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
309 - "{manifest % '{rev}:{node}'}"
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
310 - "{manifest.rev}"
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
311 """
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
312
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
313 def __init__(self, gen, key, value, makemap):
37278
b4630e332a99 templater: drop unneeded generator from mappable object
Yuya Nishihara <yuya@tcha.org>
parents: 37277
diff changeset
314 self._gen = gen # generator or function returning generator
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
315 self._key = key
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
316 self._value = value # may be generator of strings
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
317 self._makemap = makemap
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
318
38296
e72697893c93 templater: promote tomap() to an interface type
Yuya Nishihara <yuya@tcha.org>
parents: 38295
diff changeset
319 def tomap(self, context):
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
320 return self._makemap(self._key)
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
321
38279
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38278
diff changeset
322 def contains(self, context, mapping, item):
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38278
diff changeset
323 w = makewrapped(context, mapping, self._value)
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38278
diff changeset
324 return w.contains(context, mapping, item)
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38278
diff changeset
325
38255
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38254
diff changeset
326 def getmember(self, context, mapping, key):
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38254
diff changeset
327 w = makewrapped(context, mapping, self._value)
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38254
diff changeset
328 return w.getmember(context, mapping, key)
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38254
diff changeset
329
38277
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
330 def getmin(self, context, mapping):
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
331 w = makewrapped(context, mapping, self._value)
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
332 return w.getmin(context, mapping)
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
333
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
334 def getmax(self, context, mapping):
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
335 w = makewrapped(context, mapping, self._value)
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
336 return w.getmax(context, mapping)
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
337
37327
ebf139cbd4a1 templater: abstract away from joinfmt
Yuya Nishihara <yuya@tcha.org>
parents: 37326
diff changeset
338 def join(self, context, mapping, sep):
38240
8bded7eae26c templater: consistently join() string-like object per character (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38238
diff changeset
339 w = makewrapped(context, mapping, self._value)
8bded7eae26c templater: consistently join() string-like object per character (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38238
diff changeset
340 return w.join(context, mapping, sep)
37327
ebf139cbd4a1 templater: abstract away from joinfmt
Yuya Nishihara <yuya@tcha.org>
parents: 37326
diff changeset
341
37275
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
342 def show(self, context, mapping):
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
343 # TODO: switch gen to (context, mapping) API?
37277
8c84dc8264dc templater: mark .gen as a private attribute
Yuya Nishihara <yuya@tcha.org>
parents: 37275
diff changeset
344 gen = self._gen
37278
b4630e332a99 templater: drop unneeded generator from mappable object
Yuya Nishihara <yuya@tcha.org>
parents: 37277
diff changeset
345 if gen is None:
b4630e332a99 templater: drop unneeded generator from mappable object
Yuya Nishihara <yuya@tcha.org>
parents: 37277
diff changeset
346 return pycompat.bytestr(self._value)
37275
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
347 if callable(gen):
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
348 return gen()
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
349 return gen
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
350
38301
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38298
diff changeset
351 def tobool(self, context, mapping):
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38298
diff changeset
352 return bool(self.tovalue(context, mapping))
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38298
diff changeset
353
37281
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37280
diff changeset
354 def tovalue(self, context, mapping):
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37280
diff changeset
355 return _unthunk(context, mapping, self._value)
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37280
diff changeset
356
37399
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
357 class _mappingsequence(wrapped):
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
358 """Wrapper for sequence of template mappings
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
359
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
360 This represents an inner template structure (i.e. a list of dicts),
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
361 which can also be rendered by the specified named/literal template.
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
362
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
363 Template mappings may be nested.
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
364 """
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
365
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
366 def __init__(self, name=None, tmpl=None, sep=''):
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
367 if name is not None and tmpl is not None:
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
368 raise error.ProgrammingError('name and tmpl are mutually exclusive')
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
369 self._name = name
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
370 self._tmpl = tmpl
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
371 self._defaultsep = sep
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
372
38279
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38278
diff changeset
373 def contains(self, context, mapping, item):
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38278
diff changeset
374 raise error.ParseError(_('not comparable'))
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38278
diff changeset
375
38255
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38254
diff changeset
376 def getmember(self, context, mapping, key):
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38254
diff changeset
377 raise error.ParseError(_('not a dictionary'))
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38254
diff changeset
378
38277
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
379 def getmin(self, context, mapping):
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
380 raise error.ParseError(_('not comparable'))
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
381
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
382 def getmax(self, context, mapping):
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
383 raise error.ParseError(_('not comparable'))
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
384
37399
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
385 def join(self, context, mapping, sep):
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
386 mapsiter = _iteroverlaymaps(context, mapping, self.itermaps(context))
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
387 if self._name:
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
388 itemiter = (context.process(self._name, m) for m in mapsiter)
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
389 elif self._tmpl:
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
390 itemiter = (context.expand(self._tmpl, m) for m in mapsiter)
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
391 else:
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
392 raise error.ParseError(_('not displayable without template'))
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
393 return joinitems(itemiter, sep)
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
394
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
395 def show(self, context, mapping):
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
396 return self.join(context, mapping, self._defaultsep)
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
397
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
398 def tovalue(self, context, mapping):
37502
40c7347f6848 formatter: remove template resources from nested items before generating JSON
Yuya Nishihara <yuya@tcha.org>
parents: 37499
diff changeset
399 knownres = context.knownresourcekeys()
40c7347f6848 formatter: remove template resources from nested items before generating JSON
Yuya Nishihara <yuya@tcha.org>
parents: 37499
diff changeset
400 items = []
40c7347f6848 formatter: remove template resources from nested items before generating JSON
Yuya Nishihara <yuya@tcha.org>
parents: 37499
diff changeset
401 for nm in self.itermaps(context):
40c7347f6848 formatter: remove template resources from nested items before generating JSON
Yuya Nishihara <yuya@tcha.org>
parents: 37499
diff changeset
402 # drop internal resources (recursively) which shouldn't be displayed
40c7347f6848 formatter: remove template resources from nested items before generating JSON
Yuya Nishihara <yuya@tcha.org>
parents: 37499
diff changeset
403 lm = context.overlaymap(mapping, nm)
40c7347f6848 formatter: remove template resources from nested items before generating JSON
Yuya Nishihara <yuya@tcha.org>
parents: 37499
diff changeset
404 items.append({k: unwrapvalue(context, lm, v)
40c7347f6848 formatter: remove template resources from nested items before generating JSON
Yuya Nishihara <yuya@tcha.org>
parents: 37499
diff changeset
405 for k, v in nm.iteritems() if k not in knownres})
40c7347f6848 formatter: remove template resources from nested items before generating JSON
Yuya Nishihara <yuya@tcha.org>
parents: 37499
diff changeset
406 return items
37399
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
407
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
408 class mappinggenerator(_mappingsequence):
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
409 """Wrapper for generator of template mappings
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
410
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
411 The function ``make(context, *args)`` should return a generator of
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
412 mapping dicts.
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
413 """
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
414
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
415 def __init__(self, make, args=(), name=None, tmpl=None, sep=''):
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
416 super(mappinggenerator, self).__init__(name, tmpl, sep)
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
417 self._make = make
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
418 self._args = args
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
419
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
420 def itermaps(self, context):
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
421 return self._make(context, *self._args)
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
422
38301
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38298
diff changeset
423 def tobool(self, context, mapping):
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38298
diff changeset
424 return _nonempty(self.itermaps(context))
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38298
diff changeset
425
37399
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
426 class mappinglist(_mappingsequence):
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
427 """Wrapper for list of template mappings"""
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
428
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
429 def __init__(self, mappings, name=None, tmpl=None, sep=''):
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
430 super(mappinglist, self).__init__(name, tmpl, sep)
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
431 self._mappings = mappings
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
432
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
433 def itermaps(self, context):
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
434 return iter(self._mappings)
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
435
38301
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38298
diff changeset
436 def tobool(self, context, mapping):
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38298
diff changeset
437 return bool(self._mappings)
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38298
diff changeset
438
37499
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
439 class mappedgenerator(wrapped):
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
440 """Wrapper for generator of strings which acts as a list
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
441
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
442 The function ``make(context, *args)`` should return a generator of
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
443 byte strings, or a generator of (possibly nested) generators of byte
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
444 strings (i.e. a generator for a list of byte strings.)
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
445 """
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
446
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
447 def __init__(self, make, args=()):
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
448 self._make = make
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
449 self._args = args
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
450
38279
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38278
diff changeset
451 def contains(self, context, mapping, item):
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38278
diff changeset
452 item = stringify(context, mapping, item)
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38278
diff changeset
453 return item in self.tovalue(context, mapping)
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38278
diff changeset
454
37499
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
455 def _gen(self, context):
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
456 return self._make(context, *self._args)
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
457
38255
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38254
diff changeset
458 def getmember(self, context, mapping, key):
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38254
diff changeset
459 raise error.ParseError(_('not a dictionary'))
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38254
diff changeset
460
38277
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
461 def getmin(self, context, mapping):
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
462 return self._getby(context, mapping, min)
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
463
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
464 def getmax(self, context, mapping):
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
465 return self._getby(context, mapping, max)
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
466
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
467 def _getby(self, context, mapping, func):
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
468 xs = self.tovalue(context, mapping)
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
469 if not xs:
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
470 raise error.ParseError(_('empty sequence'))
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
471 return func(xs)
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38256
diff changeset
472
37499
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
473 def itermaps(self, context):
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
474 raise error.ParseError(_('list of strings is not mappable'))
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
475
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
476 def join(self, context, mapping, sep):
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
477 return joinitems(self._gen(context), sep)
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
478
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
479 def show(self, context, mapping):
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
480 return self.join(context, mapping, '')
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
481
38301
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38298
diff changeset
482 def tobool(self, context, mapping):
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38298
diff changeset
483 return _nonempty(self._gen(context))
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38298
diff changeset
484
37499
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
485 def tovalue(self, context, mapping):
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
486 return [stringify(context, mapping, x) for x in self._gen(context)]
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
487
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
488 def hybriddict(data, key='key', value='value', fmt=None, gen=None):
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
489 """Wrap data to support both dict-like and string-like operations"""
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
490 prefmt = pycompat.identity
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
491 if fmt is None:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
492 fmt = '%s=%s'
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
493 prefmt = pycompat.bytestr
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
494 return hybrid(gen, data, lambda k: {key: k, value: data[k]},
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
495 lambda k: fmt % (prefmt(k), prefmt(data[k])))
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
496
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
497 def hybridlist(data, name, fmt=None, gen=None):
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
498 """Wrap data to support both list-like and string-like operations"""
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
499 prefmt = pycompat.identity
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
500 if fmt is None:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
501 fmt = '%s'
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
502 prefmt = pycompat.bytestr
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
503 return hybrid(gen, data, lambda x: {name: x}, lambda x: fmt % prefmt(x))
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
504
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
505 def compatdict(context, mapping, name, data, key='key', value='value',
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
506 fmt=None, plural=None, separator=' '):
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
507 """Wrap data like hybriddict(), but also supports old-style list template
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
508
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
509 This exists for backward compatibility with the old-style template. Use
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
510 hybriddict() for new template keywords.
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
511 """
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
512 c = [{key: k, value: v} for k, v in data.iteritems()]
37071
aa97e06a1912 templater: use template context to render old-style list template
Yuya Nishihara <yuya@tcha.org>
parents: 37022
diff changeset
513 f = _showcompatlist(context, mapping, name, c, plural, separator)
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
514 return hybriddict(data, key=key, value=value, fmt=fmt, gen=f)
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
515
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
516 def compatlist(context, mapping, name, data, element=None, fmt=None,
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
517 plural=None, separator=' '):
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
518 """Wrap data like hybridlist(), but also supports old-style list template
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
519
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
520 This exists for backward compatibility with the old-style template. Use
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
521 hybridlist() for new template keywords.
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
522 """
37071
aa97e06a1912 templater: use template context to render old-style list template
Yuya Nishihara <yuya@tcha.org>
parents: 37022
diff changeset
523 f = _showcompatlist(context, mapping, name, data, plural, separator)
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
524 return hybridlist(data, name=element or name, fmt=fmt, gen=f)
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
525
37071
aa97e06a1912 templater: use template context to render old-style list template
Yuya Nishihara <yuya@tcha.org>
parents: 37022
diff changeset
526 def _showcompatlist(context, mapping, name, values, plural=None, separator=' '):
aa97e06a1912 templater: use template context to render old-style list template
Yuya Nishihara <yuya@tcha.org>
parents: 37022
diff changeset
527 """Return a generator that renders old-style list template
aa97e06a1912 templater: use template context to render old-style list template
Yuya Nishihara <yuya@tcha.org>
parents: 37022
diff changeset
528
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
529 name is name of key in template map.
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
530 values is list of strings or dicts.
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
531 plural is plural of name, if not simply name + 's'.
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
532 separator is used to join values as a string
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
533
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
534 expansion works like this, given name 'foo'.
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
535
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
536 if values is empty, expand 'no_foos'.
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
537
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
538 if 'foo' not in template map, return values as a string,
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
539 joined by 'separator'.
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
540
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
541 expand 'start_foos'.
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
542
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
543 for each value, expand 'foo'. if 'last_foo' in template
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
544 map, expand it instead of 'foo' for last key.
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
545
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
546 expand 'end_foos'.
37071
aa97e06a1912 templater: use template context to render old-style list template
Yuya Nishihara <yuya@tcha.org>
parents: 37022
diff changeset
547 """
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
548 if not plural:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
549 plural = name + 's'
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
550 if not values:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
551 noname = 'no_' + plural
37071
aa97e06a1912 templater: use template context to render old-style list template
Yuya Nishihara <yuya@tcha.org>
parents: 37022
diff changeset
552 if context.preload(noname):
aa97e06a1912 templater: use template context to render old-style list template
Yuya Nishihara <yuya@tcha.org>
parents: 37022
diff changeset
553 yield context.process(noname, mapping)
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
554 return
37071
aa97e06a1912 templater: use template context to render old-style list template
Yuya Nishihara <yuya@tcha.org>
parents: 37022
diff changeset
555 if not context.preload(name):
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
556 if isinstance(values[0], bytes):
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
557 yield separator.join(values)
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
558 else:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
559 for v in values:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
560 r = dict(v)
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
561 r.update(mapping)
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
562 yield r
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
563 return
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
564 startname = 'start_' + plural
37071
aa97e06a1912 templater: use template context to render old-style list template
Yuya Nishihara <yuya@tcha.org>
parents: 37022
diff changeset
565 if context.preload(startname):
aa97e06a1912 templater: use template context to render old-style list template
Yuya Nishihara <yuya@tcha.org>
parents: 37022
diff changeset
566 yield context.process(startname, mapping)
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
567 def one(v, tag=name):
37077
2891079fb0c0 templater: factor out function to create mapping dict for nested evaluation
Yuya Nishihara <yuya@tcha.org>
parents: 37076
diff changeset
568 vmapping = {}
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
569 try:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
570 vmapping.update(v)
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
571 # Python 2 raises ValueError if the type of v is wrong. Python
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
572 # 3 raises TypeError.
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
573 except (AttributeError, TypeError, ValueError):
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
574 try:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
575 # Python 2 raises ValueError trying to destructure an e.g.
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
576 # bytes. Python 3 raises TypeError.
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
577 for a, b in v:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
578 vmapping[a] = b
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
579 except (TypeError, ValueError):
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
580 vmapping[name] = v
37077
2891079fb0c0 templater: factor out function to create mapping dict for nested evaluation
Yuya Nishihara <yuya@tcha.org>
parents: 37076
diff changeset
581 vmapping = context.overlaymap(mapping, vmapping)
37071
aa97e06a1912 templater: use template context to render old-style list template
Yuya Nishihara <yuya@tcha.org>
parents: 37022
diff changeset
582 return context.process(tag, vmapping)
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
583 lastname = 'last_' + name
37071
aa97e06a1912 templater: use template context to render old-style list template
Yuya Nishihara <yuya@tcha.org>
parents: 37022
diff changeset
584 if context.preload(lastname):
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
585 last = values.pop()
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
586 else:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
587 last = None
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
588 for v in values:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
589 yield one(v)
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
590 if last is not None:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
591 yield one(last, tag=lastname)
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
592 endname = 'end_' + plural
37071
aa97e06a1912 templater: use template context to render old-style list template
Yuya Nishihara <yuya@tcha.org>
parents: 37022
diff changeset
593 if context.preload(endname):
aa97e06a1912 templater: use template context to render old-style list template
Yuya Nishihara <yuya@tcha.org>
parents: 37022
diff changeset
594 yield context.process(endname, mapping)
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
595
37274
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37233
diff changeset
596 def flatten(context, mapping, thing):
37159
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
597 """Yield a single stream from a possibly nested set of iterators"""
38282
630c62804383 templater: inline unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 38281
diff changeset
598 if isinstance(thing, wrapped):
630c62804383 templater: inline unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 38281
diff changeset
599 thing = thing.show(context, mapping)
37159
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
600 if isinstance(thing, bytes):
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
601 yield thing
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
602 elif isinstance(thing, str):
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
603 # We can only hit this on Python 3, and it's here to guard
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
604 # against infinite recursion.
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
605 raise error.ProgrammingError('Mercurial IO including templates is done'
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
606 ' with bytes, not strings, got %r' % thing)
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
607 elif thing is None:
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
608 pass
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
609 elif not util.safehasattr(thing, '__iter__'):
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
610 yield pycompat.bytestr(thing)
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
611 else:
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
612 for i in thing:
38282
630c62804383 templater: inline unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 38281
diff changeset
613 if isinstance(i, wrapped):
630c62804383 templater: inline unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 38281
diff changeset
614 i = i.show(context, mapping)
37159
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
615 if isinstance(i, bytes):
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
616 yield i
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
617 elif i is None:
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
618 pass
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
619 elif not util.safehasattr(i, '__iter__'):
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
620 yield pycompat.bytestr(i)
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
621 else:
37274
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37233
diff changeset
622 for j in flatten(context, mapping, i):
37159
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
623 yield j
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
624
37274
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37233
diff changeset
625 def stringify(context, mapping, thing):
36926
6ff6e1d6b5b8 templater: move stringify() to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36919
diff changeset
626 """Turn values into bytes by converting into text and concatenating them"""
37160
e09d2183e226 templateutil: reimplement stringify() using flatten()
Yuya Nishihara <yuya@tcha.org>
parents: 37159
diff changeset
627 if isinstance(thing, bytes):
e09d2183e226 templateutil: reimplement stringify() using flatten()
Yuya Nishihara <yuya@tcha.org>
parents: 37159
diff changeset
628 return thing # retain localstr to be round-tripped
37274
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37233
diff changeset
629 return b''.join(flatten(context, mapping, thing))
36926
6ff6e1d6b5b8 templater: move stringify() to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36919
diff changeset
630
31927
2abc556dbe92 templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents: 31926
diff changeset
631 def findsymbolicname(arg):
2abc556dbe92 templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents: 31926
diff changeset
632 """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
633 if nothing found reliably"""
2abc556dbe92 templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents: 31926
diff changeset
634 while True:
2abc556dbe92 templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents: 31926
diff changeset
635 func, data = arg
2abc556dbe92 templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents: 31926
diff changeset
636 if func is runsymbol:
2abc556dbe92 templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents: 31926
diff changeset
637 return data
2abc556dbe92 templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents: 31926
diff changeset
638 elif func is runfilter:
2abc556dbe92 templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents: 31926
diff changeset
639 arg = data[0]
2abc556dbe92 templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents: 31926
diff changeset
640 else:
2abc556dbe92 templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents: 31926
diff changeset
641 return None
2abc556dbe92 templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents: 31926
diff changeset
642
38301
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38298
diff changeset
643 def _nonempty(xiter):
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38298
diff changeset
644 try:
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38298
diff changeset
645 next(xiter)
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38298
diff changeset
646 return True
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38298
diff changeset
647 except StopIteration:
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38298
diff changeset
648 return False
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38298
diff changeset
649
37280
671a01cd50b5 templater: extract private function to evaluate generator to byte string
Yuya Nishihara <yuya@tcha.org>
parents: 37279
diff changeset
650 def _unthunk(context, mapping, thing):
671a01cd50b5 templater: extract private function to evaluate generator to byte string
Yuya Nishihara <yuya@tcha.org>
parents: 37279
diff changeset
651 """Evaluate a lazy byte string into value"""
671a01cd50b5 templater: extract private function to evaluate generator to byte string
Yuya Nishihara <yuya@tcha.org>
parents: 37279
diff changeset
652 if not isinstance(thing, types.GeneratorType):
671a01cd50b5 templater: extract private function to evaluate generator to byte string
Yuya Nishihara <yuya@tcha.org>
parents: 37279
diff changeset
653 return thing
671a01cd50b5 templater: extract private function to evaluate generator to byte string
Yuya Nishihara <yuya@tcha.org>
parents: 37279
diff changeset
654 return stringify(context, mapping, thing)
671a01cd50b5 templater: extract private function to evaluate generator to byte string
Yuya Nishihara <yuya@tcha.org>
parents: 37279
diff changeset
655
34333
e60c601953d7 templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents: 34332
diff changeset
656 def evalrawexp(context, mapping, arg):
e60c601953d7 templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents: 34332
diff changeset
657 """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
658 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
659 func, data = arg
34333
e60c601953d7 templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents: 34332
diff changeset
660 return func(context, mapping, data)
e60c601953d7 templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents: 34332
diff changeset
661
38238
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
662 def evalwrapped(context, mapping, arg):
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
663 """Evaluate given argument to wrapped object"""
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
664 thing = evalrawexp(context, mapping, arg)
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
665 return makewrapped(context, mapping, thing)
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
666
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
667 def makewrapped(context, mapping, thing):
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
668 """Lift object to a wrapped type"""
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
669 if isinstance(thing, wrapped):
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
670 return thing
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
671 thing = _unthunk(context, mapping, thing)
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
672 if isinstance(thing, bytes):
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
673 return wrappedbytes(thing)
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
674 return wrappedvalue(thing)
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
675
34333
e60c601953d7 templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents: 34332
diff changeset
676 def evalfuncarg(context, mapping, arg):
e60c601953d7 templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents: 34332
diff changeset
677 """Evaluate given argument as value type"""
38237
d48b80d58848 templater: unify unwrapvalue() with _unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 38236
diff changeset
678 return unwrapvalue(context, mapping, evalrawexp(context, mapping, arg))
37163
0023da2910c9 templater: extract type conversion from evalfuncarg()
Yuya Nishihara <yuya@tcha.org>
parents: 37162
diff changeset
679
38237
d48b80d58848 templater: unify unwrapvalue() with _unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 38236
diff changeset
680 def unwrapvalue(context, mapping, thing):
d48b80d58848 templater: unify unwrapvalue() with _unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 38236
diff changeset
681 """Move the inner value object out of the wrapper"""
38236
61cecab0cc20 templater: inline unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37502
diff changeset
682 if isinstance(thing, wrapped):
61cecab0cc20 templater: inline unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37502
diff changeset
683 return thing.tovalue(context, mapping)
34333
e60c601953d7 templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents: 34332
diff changeset
684 # 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
685 # such as date tuple, but filter does not want generator.
37280
671a01cd50b5 templater: extract private function to evaluate generator to byte string
Yuya Nishihara <yuya@tcha.org>
parents: 37279
diff changeset
686 return _unthunk(context, mapping, thing)
26124
604a7c941103 templater: extract helper that evaluates filter or function argument
Yuya Nishihara <yuya@tcha.org>
parents: 26106
diff changeset
687
29827
034412ca28c3 templater: fix if() to not evaluate False as bool('False')
Yuya Nishihara <yuya@tcha.org>
parents: 29826
diff changeset
688 def evalboolean(context, mapping, arg):
29828
cc11079644fc templater: make pad() evaluate boolean argument (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 29827
diff changeset
689 """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
690 func, data = arg
29828
cc11079644fc templater: make pad() evaluate boolean argument (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 29827
diff changeset
691 if func is runsymbol:
cc11079644fc templater: make pad() evaluate boolean argument (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 29827
diff changeset
692 thing = func(context, mapping, data, default=None)
cc11079644fc templater: make pad() evaluate boolean argument (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 29827
diff changeset
693 if thing is None:
cc11079644fc templater: make pad() evaluate boolean argument (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 29827
diff changeset
694 # not a template keyword, takes as a boolean literal
37087
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 37077
diff changeset
695 thing = stringutil.parsebool(data)
29828
cc11079644fc templater: make pad() evaluate boolean argument (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 29827
diff changeset
696 else:
cc11079644fc templater: make pad() evaluate boolean argument (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 29827
diff changeset
697 thing = func(context, mapping, data)
38301
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38298
diff changeset
698 return makewrapped(context, mapping, thing).tobool(context, mapping)
29827
034412ca28c3 templater: fix if() to not evaluate False as bool('False')
Yuya Nishihara <yuya@tcha.org>
parents: 29826
diff changeset
699
37226
67efce231633 templater: factor out function that parses argument as date tuple
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
700 def evaldate(context, mapping, arg, err=None):
67efce231633 templater: factor out function that parses argument as date tuple
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
701 """Evaluate given argument as a date tuple or a date string; returns
67efce231633 templater: factor out function that parses argument as date tuple
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
702 a (unixtime, offset) tuple"""
37274
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37233
diff changeset
703 thing = evalrawexp(context, mapping, arg)
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37233
diff changeset
704 return unwrapdate(context, mapping, thing, err)
37226
67efce231633 templater: factor out function that parses argument as date tuple
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
705
37274
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37233
diff changeset
706 def unwrapdate(context, mapping, thing, err=None):
38297
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38296
diff changeset
707 if isinstance(thing, date):
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38296
diff changeset
708 return thing.tovalue(context, mapping)
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38296
diff changeset
709 # TODO: update hgweb to not return bare tuple; then just stringify 'thing'
38237
d48b80d58848 templater: unify unwrapvalue() with _unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 38236
diff changeset
710 thing = unwrapvalue(context, mapping, thing)
37226
67efce231633 templater: factor out function that parses argument as date tuple
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
711 try:
67efce231633 templater: factor out function that parses argument as date tuple
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
712 return dateutil.parsedate(thing)
67efce231633 templater: factor out function that parses argument as date tuple
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
713 except AttributeError:
67efce231633 templater: factor out function that parses argument as date tuple
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
714 raise error.ParseError(err or _('not a date tuple nor a string'))
37227
e70a90a72b80 templatefuncs: use evaldate() where seems appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37226
diff changeset
715 except error.ParseError:
e70a90a72b80 templatefuncs: use evaldate() where seems appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37226
diff changeset
716 if not err:
e70a90a72b80 templatefuncs: use evaldate() where seems appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37226
diff changeset
717 raise
e70a90a72b80 templatefuncs: use evaldate() where seems appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37226
diff changeset
718 raise error.ParseError(err)
37226
67efce231633 templater: factor out function that parses argument as date tuple
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
719
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
720 def evalinteger(context, mapping, arg, err=None):
37274
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37233
diff changeset
721 thing = evalrawexp(context, mapping, arg)
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37233
diff changeset
722 return unwrapinteger(context, mapping, thing, err)
37164
9ab3491f84c2 templater: extract unwrapinteger() function from evalinteger()
Yuya Nishihara <yuya@tcha.org>
parents: 37163
diff changeset
723
37274
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37233
diff changeset
724 def unwrapinteger(context, mapping, thing, err=None):
38237
d48b80d58848 templater: unify unwrapvalue() with _unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 38236
diff changeset
725 thing = unwrapvalue(context, mapping, thing)
28343
a6c2310b3827 templater: factor out function that evaluates argument as integer
Yuya Nishihara <yuya@tcha.org>
parents: 28334
diff changeset
726 try:
37164
9ab3491f84c2 templater: extract unwrapinteger() function from evalinteger()
Yuya Nishihara <yuya@tcha.org>
parents: 37163
diff changeset
727 return int(thing)
28344
ac371d4c007f templater: drop redundant type conversion when evaluating integer argument
Yuya Nishihara <yuya@tcha.org>
parents: 28343
diff changeset
728 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
729 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
730
28348
ccedb17a5657 templater: factor out thin helper that evaluates argument as string
Yuya Nishihara <yuya@tcha.org>
parents: 28346
diff changeset
731 def evalstring(context, mapping, arg):
37274
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37233
diff changeset
732 return stringify(context, mapping, 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
733
28373
9a9dd71e882c templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents: 28349
diff changeset
734 def evalstringliteral(context, mapping, arg):
9a9dd71e882c templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents: 28349
diff changeset
735 """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
736 if it is unknown"""
9a9dd71e882c templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents: 28349
diff changeset
737 func, data = arg
9a9dd71e882c templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents: 28349
diff changeset
738 if func is runsymbol:
9a9dd71e882c templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents: 28349
diff changeset
739 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
740 else:
9a9dd71e882c templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents: 28349
diff changeset
741 thing = func(context, mapping, data)
37274
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37233
diff changeset
742 return stringify(context, mapping, thing)
28373
9a9dd71e882c templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents: 28349
diff changeset
743
37165
0fb28899e81a templater: factor out unwrapastype() from evalastype()
Yuya Nishihara <yuya@tcha.org>
parents: 37164
diff changeset
744 _unwrapfuncbytype = {
38237
d48b80d58848 templater: unify unwrapvalue() with _unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 38236
diff changeset
745 None: unwrapvalue,
37165
0fb28899e81a templater: factor out unwrapastype() from evalastype()
Yuya Nishihara <yuya@tcha.org>
parents: 37164
diff changeset
746 bytes: stringify,
37229
9bcf096a2da2 templatefilters: declare input type as date where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37228
diff changeset
747 date: unwrapdate,
37165
0fb28899e81a templater: factor out unwrapastype() from evalastype()
Yuya Nishihara <yuya@tcha.org>
parents: 37164
diff changeset
748 int: unwrapinteger,
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
749 }
ee0d74083a22 templater: store revisions as ints so min/max won't compare them as strings
Yuya Nishihara <yuya@tcha.org>
parents: 34536
diff changeset
750
37274
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37233
diff changeset
751 def unwrapastype(context, mapping, thing, typ):
37165
0fb28899e81a templater: factor out unwrapastype() from evalastype()
Yuya Nishihara <yuya@tcha.org>
parents: 37164
diff changeset
752 """Move the inner value object out of the wrapper and coerce its type"""
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
753 try:
37165
0fb28899e81a templater: factor out unwrapastype() from evalastype()
Yuya Nishihara <yuya@tcha.org>
parents: 37164
diff changeset
754 f = _unwrapfuncbytype[typ]
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
755 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
756 raise error.ProgrammingError('invalid type specified: %r' % typ)
37274
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37233
diff changeset
757 return f(context, mapping, thing)
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
758
25002
829faf8ab605 templater: tokenize decimal integer literal (issue4638) (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25001
diff changeset
759 def runinteger(context, mapping, data):
829faf8ab605 templater: tokenize decimal integer literal (issue4638) (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25001
diff changeset
760 return int(data)
829faf8ab605 templater: tokenize decimal integer literal (issue4638) (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25001
diff changeset
761
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
762 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
763 return data
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
764
27939
7ed3a3c0cef1 templater: abort if infinite recursion detected while evaluation (issue4758)
Yuya Nishihara <yuya@tcha.org>
parents: 27892
diff changeset
765 def _recursivesymbolblocker(key):
7ed3a3c0cef1 templater: abort if infinite recursion detected while evaluation (issue4758)
Yuya Nishihara <yuya@tcha.org>
parents: 27892
diff changeset
766 def showrecursion(**args):
7ed3a3c0cef1 templater: abort if infinite recursion detected while evaluation (issue4758)
Yuya Nishihara <yuya@tcha.org>
parents: 27892
diff changeset
767 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
768 return showrecursion
7ed3a3c0cef1 templater: abort if infinite recursion detected while evaluation (issue4758)
Yuya Nishihara <yuya@tcha.org>
parents: 27892
diff changeset
769
28373
9a9dd71e882c templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents: 28349
diff changeset
770 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
771 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
772 if v is None:
27939
7ed3a3c0cef1 templater: abort if infinite recursion detected while evaluation (issue4758)
Yuya Nishihara <yuya@tcha.org>
parents: 27892
diff changeset
773 # 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
774 # 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
775 safemapping = mapping.copy()
7ed3a3c0cef1 templater: abort if infinite recursion detected while evaluation (issue4758)
Yuya Nishihara <yuya@tcha.org>
parents: 27892
diff changeset
776 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
777 try:
27939
7ed3a3c0cef1 templater: abort if infinite recursion detected while evaluation (issue4758)
Yuya Nishihara <yuya@tcha.org>
parents: 27892
diff changeset
778 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
779 except TemplateNotFound:
28373
9a9dd71e882c templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents: 28349
diff changeset
780 v = default
36475
e8d37838f5df templatekw: add 'requires' flag to switch to exception-safe interface
Yuya Nishihara <yuya@tcha.org>
parents: 36474
diff changeset
781 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
782 # old templatekw: expand all keywords and resources
37073
1101d6747d2d templater: drop 'templ' from resources dict
Yuya Nishihara <yuya@tcha.org>
parents: 37071
diff changeset
783 # (TODO: deprecate this after porting web template keywords to new API)
37076
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 37073
diff changeset
784 props = {k: context._resources.lookup(context, mapping, k)
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 37073
diff changeset
785 for k in context._resources.knownkeys()}
37073
1101d6747d2d templater: drop 'templ' from resources dict
Yuya Nishihara <yuya@tcha.org>
parents: 37071
diff changeset
786 # pass context to _showcompatlist() through templatekw._showlist()
1101d6747d2d templater: drop 'templ' from resources dict
Yuya Nishihara <yuya@tcha.org>
parents: 37071
diff changeset
787 props['templ'] = context
35472
32c278eb876f templater: keep default resources per template engine (API)
Yuya Nishihara <yuya@tcha.org>
parents: 35471
diff changeset
788 props.update(mapping)
35588
dadbf213a765 py3: convert dict keys' to str before passing as kwargs
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35485
diff changeset
789 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
790 if callable(v):
e8d37838f5df templatekw: add 'requires' flag to switch to exception-safe interface
Yuya Nishihara <yuya@tcha.org>
parents: 36474
diff changeset
791 # new templatekw
e8d37838f5df templatekw: add 'requires' flag to switch to exception-safe interface
Yuya Nishihara <yuya@tcha.org>
parents: 36474
diff changeset
792 try:
e8d37838f5df templatekw: add 'requires' flag to switch to exception-safe interface
Yuya Nishihara <yuya@tcha.org>
parents: 36474
diff changeset
793 return v(context, mapping)
e8d37838f5df templatekw: add 'requires' flag to switch to exception-safe interface
Yuya Nishihara <yuya@tcha.org>
parents: 36474
diff changeset
794 except ResourceUnavailable:
e8d37838f5df templatekw: add 'requires' flag to switch to exception-safe interface
Yuya Nishihara <yuya@tcha.org>
parents: 36474
diff changeset
795 # 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
796 return None
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
797 return v
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
798
25595
a7dd6692e5cb templater: move runtemplate function out of buildmap/runmap pair
Yuya Nishihara <yuya@tcha.org>
parents: 25580
diff changeset
799 def runtemplate(context, mapping, template):
34333
e60c601953d7 templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents: 34332
diff changeset
800 for arg in template:
e60c601953d7 templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents: 34332
diff changeset
801 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
802
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
803 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
804 arg, filt = data
37224
54355c243042 templatefilters: allow declaration of input data type
Yuya Nishihara <yuya@tcha.org>
parents: 37165
diff changeset
805 thing = evalrawexp(context, mapping, arg)
37274
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37233
diff changeset
806 intype = getattr(filt, '_intype', None)
17383
099c778ceb33 templater: abort when a template filter raises an exception (issue2987)
Neil Kodner <neilk@fb.com>
parents: 17334
diff changeset
807 try:
37274
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37233
diff changeset
808 thing = unwrapastype(context, mapping, thing, intype)
24280
6c55e37ba5f2 templater: allow piping generator-type function output to filters
Yuya Nishihara <yuya@tcha.org>
parents: 24240
diff changeset
809 return filt(thing)
37228
920589f52be9 templater: attach hint to input-type error of runfilter()
Yuya Nishihara <yuya@tcha.org>
parents: 37227
diff changeset
810 except error.ParseError as e:
920589f52be9 templater: attach hint to input-type error of runfilter()
Yuya Nishihara <yuya@tcha.org>
parents: 37227
diff changeset
811 raise error.ParseError(bytes(e), hint=_formatfiltererror(arg, filt))
920589f52be9 templater: attach hint to input-type error of runfilter()
Yuya Nishihara <yuya@tcha.org>
parents: 37227
diff changeset
812
920589f52be9 templater: attach hint to input-type error of runfilter()
Yuya Nishihara <yuya@tcha.org>
parents: 37227
diff changeset
813 def _formatfiltererror(arg, filt):
920589f52be9 templater: attach hint to input-type error of runfilter()
Yuya Nishihara <yuya@tcha.org>
parents: 37227
diff changeset
814 fn = pycompat.sysbytes(filt.__name__)
920589f52be9 templater: attach hint to input-type error of runfilter()
Yuya Nishihara <yuya@tcha.org>
parents: 37227
diff changeset
815 sym = findsymbolicname(arg)
920589f52be9 templater: attach hint to input-type error of runfilter()
Yuya Nishihara <yuya@tcha.org>
parents: 37227
diff changeset
816 if not sym:
920589f52be9 templater: attach hint to input-type error of runfilter()
Yuya Nishihara <yuya@tcha.org>
parents: 37227
diff changeset
817 return _("incompatible use of template filter '%s'") % fn
920589f52be9 templater: attach hint to input-type error of runfilter()
Yuya Nishihara <yuya@tcha.org>
parents: 37227
diff changeset
818 return (_("template filter '%s' is not compatible with keyword '%s'")
920589f52be9 templater: attach hint to input-type error of runfilter()
Yuya Nishihara <yuya@tcha.org>
parents: 37227
diff changeset
819 % (fn, sym))
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
820
37399
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
821 def _iteroverlaymaps(context, origmapping, newmappings):
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
822 """Generate combined mappings from the original mapping and an iterable
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
823 of partial mappings to override the original"""
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
824 for i, nm in enumerate(newmappings):
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
825 lm = context.overlaymap(origmapping, nm)
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
826 lm['index'] = i
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
827 yield lm
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
828
38283
4b0f39e7406e templater: show slightly better hint on map operation error
Yuya Nishihara <yuya@tcha.org>
parents: 38282
diff changeset
829 def _applymap(context, mapping, d, darg, targ):
4b0f39e7406e templater: show slightly better hint on map operation error
Yuya Nishihara <yuya@tcha.org>
parents: 38282
diff changeset
830 try:
4b0f39e7406e templater: show slightly better hint on map operation error
Yuya Nishihara <yuya@tcha.org>
parents: 38282
diff changeset
831 diter = d.itermaps(context)
4b0f39e7406e templater: show slightly better hint on map operation error
Yuya Nishihara <yuya@tcha.org>
parents: 38282
diff changeset
832 except error.ParseError as err:
4b0f39e7406e templater: show slightly better hint on map operation error
Yuya Nishihara <yuya@tcha.org>
parents: 38282
diff changeset
833 sym = findsymbolicname(darg)
4b0f39e7406e templater: show slightly better hint on map operation error
Yuya Nishihara <yuya@tcha.org>
parents: 38282
diff changeset
834 if not sym:
4b0f39e7406e templater: show slightly better hint on map operation error
Yuya Nishihara <yuya@tcha.org>
parents: 38282
diff changeset
835 raise
4b0f39e7406e templater: show slightly better hint on map operation error
Yuya Nishihara <yuya@tcha.org>
parents: 38282
diff changeset
836 hint = _("keyword '%s' does not support map operation") % sym
4b0f39e7406e templater: show slightly better hint on map operation error
Yuya Nishihara <yuya@tcha.org>
parents: 38282
diff changeset
837 raise error.ParseError(bytes(err), hint=hint)
4b0f39e7406e templater: show slightly better hint on map operation error
Yuya Nishihara <yuya@tcha.org>
parents: 38282
diff changeset
838 for lm in _iteroverlaymaps(context, mapping, diter):
37499
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
839 yield evalrawexp(context, lm, targ)
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
840
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
841 def runmap(context, mapping, data):
34333
e60c601953d7 templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents: 34332
diff changeset
842 darg, targ = data
38241
7701c2d4a438 templater: always map over a wrapped object
Yuya Nishihara <yuya@tcha.org>
parents: 38240
diff changeset
843 d = evalwrapped(context, mapping, darg)
38283
4b0f39e7406e templater: show slightly better hint on map operation error
Yuya Nishihara <yuya@tcha.org>
parents: 38282
diff changeset
844 return mappedgenerator(_applymap, args=(mapping, d, darg, targ))
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
845
34535
78590585c0db templater: add dot operator to easily access a sub item
Yuya Nishihara <yuya@tcha.org>
parents: 34534
diff changeset
846 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
847 darg, memb = data
38252
c2456a7726c1 templater: do dict lookup over a wrapped object
Yuya Nishihara <yuya@tcha.org>
parents: 38241
diff changeset
848 d = evalwrapped(context, mapping, darg)
38296
e72697893c93 templater: promote tomap() to an interface type
Yuya Nishihara <yuya@tcha.org>
parents: 38295
diff changeset
849 if isinstance(d, mappable):
e72697893c93 templater: promote tomap() to an interface type
Yuya Nishihara <yuya@tcha.org>
parents: 38295
diff changeset
850 lm = context.overlaymap(mapping, d.tomap(context))
34535
78590585c0db templater: add dot operator to easily access a sub item
Yuya Nishihara <yuya@tcha.org>
parents: 34534
diff changeset
851 return runsymbol(context, lm, memb)
38253
ad06a4264daf templater: add try-except stub to runmember()
Yuya Nishihara <yuya@tcha.org>
parents: 38252
diff changeset
852 try:
38255
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38254
diff changeset
853 return d.getmember(context, mapping, memb)
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38254
diff changeset
854 except error.ParseError as err:
38253
ad06a4264daf templater: add try-except stub to runmember()
Yuya Nishihara <yuya@tcha.org>
parents: 38252
diff changeset
855 sym = findsymbolicname(darg)
38255
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38254
diff changeset
856 if not sym:
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38254
diff changeset
857 raise
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38254
diff changeset
858 hint = _("keyword '%s' does not support member operation") % sym
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38254
diff changeset
859 raise error.ParseError(bytes(err), hint=hint)
34535
78590585c0db templater: add dot operator to easily access a sub item
Yuya Nishihara <yuya@tcha.org>
parents: 34534
diff changeset
860
30115
8e42dfde93d1 templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents: 30083
diff changeset
861 def runnegate(context, mapping, data):
8e42dfde93d1 templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents: 30083
diff changeset
862 data = evalinteger(context, mapping, data,
8e42dfde93d1 templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents: 30083
diff changeset
863 _('negation needs an integer argument'))
8e42dfde93d1 templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents: 30083
diff changeset
864 return -data
8e42dfde93d1 templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents: 30083
diff changeset
865
8e42dfde93d1 templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents: 30083
diff changeset
866 def runarithmetic(context, mapping, data):
8e42dfde93d1 templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents: 30083
diff changeset
867 func, left, right = data
8e42dfde93d1 templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents: 30083
diff changeset
868 left = evalinteger(context, mapping, left,
8e42dfde93d1 templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents: 30083
diff changeset
869 _('arithmetic only defined on integers'))
8e42dfde93d1 templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents: 30083
diff changeset
870 right = evalinteger(context, mapping, right,
8e42dfde93d1 templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents: 30083
diff changeset
871 _('arithmetic only defined on integers'))
30116
1c01fa29630f templater: handle division by zero in arithmetic
Simon Farnsworth <simonfar@fb.com>
parents: 30115
diff changeset
872 try:
1c01fa29630f templater: handle division by zero in arithmetic
Simon Farnsworth <simonfar@fb.com>
parents: 30115
diff changeset
873 return func(left, right)
1c01fa29630f templater: handle division by zero in arithmetic
Simon Farnsworth <simonfar@fb.com>
parents: 30115
diff changeset
874 except ZeroDivisionError:
1c01fa29630f templater: handle division by zero in arithmetic
Simon Farnsworth <simonfar@fb.com>
parents: 30115
diff changeset
875 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
876
37325
41a5d815d2c1 templater: factor out generator of join()-ed items
Yuya Nishihara <yuya@tcha.org>
parents: 37324
diff changeset
877 def joinitems(itemiter, sep):
41a5d815d2c1 templater: factor out generator of join()-ed items
Yuya Nishihara <yuya@tcha.org>
parents: 37324
diff changeset
878 """Join items with the separator; Returns generator of bytes"""
41a5d815d2c1 templater: factor out generator of join()-ed items
Yuya Nishihara <yuya@tcha.org>
parents: 37324
diff changeset
879 first = True
41a5d815d2c1 templater: factor out generator of join()-ed items
Yuya Nishihara <yuya@tcha.org>
parents: 37324
diff changeset
880 for x in itemiter:
41a5d815d2c1 templater: factor out generator of join()-ed items
Yuya Nishihara <yuya@tcha.org>
parents: 37324
diff changeset
881 if first:
41a5d815d2c1 templater: factor out generator of join()-ed items
Yuya Nishihara <yuya@tcha.org>
parents: 37324
diff changeset
882 first = False
37326
9cd88dd3bf64 templater: micro-optimize join() with empty separator
Yuya Nishihara <yuya@tcha.org>
parents: 37325
diff changeset
883 elif sep:
37325
41a5d815d2c1 templater: factor out generator of join()-ed items
Yuya Nishihara <yuya@tcha.org>
parents: 37324
diff changeset
884 yield sep
41a5d815d2c1 templater: factor out generator of join()-ed items
Yuya Nishihara <yuya@tcha.org>
parents: 37324
diff changeset
885 yield x