comparison mercurial/templateutil.py @ 37068:aa97e06a1912

templater: use template context to render old-style list template Prepares for dropping the 'templ' resource. This means old-style list templates are processed by the same engine class as the one for the list node. I think that's fine since templates for the same list should be tightly coupled, and I believe the extension point for the engine classes isn't actually used. Now templatekw._showlist() is a compatibility wrapper for _showcompatlist(), and will be deprecated soon. The function is still marked as private since I plan to change the interface to get rid of closures capturing context and mapping.
author Yuya Nishihara <yuya@tcha.org>
date Fri, 16 Mar 2018 22:47:15 +0900
parents c97b936d8bb5
children 1101d6747d2d
comparison
equal deleted inserted replaced
37067:04aafcec00b9 37068:aa97e06a1912
146 146
147 This exists for backward compatibility with the old-style template. Use 147 This exists for backward compatibility with the old-style template. Use
148 hybriddict() for new template keywords. 148 hybriddict() for new template keywords.
149 """ 149 """
150 c = [{key: k, value: v} for k, v in data.iteritems()] 150 c = [{key: k, value: v} for k, v in data.iteritems()]
151 t = context.resource(mapping, 'templ') 151 f = _showcompatlist(context, mapping, name, c, plural, separator)
152 f = _showlist(name, c, t, mapping, plural, separator)
153 return hybriddict(data, key=key, value=value, fmt=fmt, gen=f) 152 return hybriddict(data, key=key, value=value, fmt=fmt, gen=f)
154 153
155 def compatlist(context, mapping, name, data, element=None, fmt=None, 154 def compatlist(context, mapping, name, data, element=None, fmt=None,
156 plural=None, separator=' '): 155 plural=None, separator=' '):
157 """Wrap data like hybridlist(), but also supports old-style list template 156 """Wrap data like hybridlist(), but also supports old-style list template
158 157
159 This exists for backward compatibility with the old-style template. Use 158 This exists for backward compatibility with the old-style template. Use
160 hybridlist() for new template keywords. 159 hybridlist() for new template keywords.
161 """ 160 """
162 t = context.resource(mapping, 'templ') 161 f = _showcompatlist(context, mapping, name, data, plural, separator)
163 f = _showlist(name, data, t, mapping, plural, separator)
164 return hybridlist(data, name=element or name, fmt=fmt, gen=f) 162 return hybridlist(data, name=element or name, fmt=fmt, gen=f)
165 163
166 def _showlist(name, values, templ, mapping, plural=None, separator=' '): 164 def _showcompatlist(context, mapping, name, values, plural=None, separator=' '):
167 '''expand set of values. 165 """Return a generator that renders old-style list template
166
168 name is name of key in template map. 167 name is name of key in template map.
169 values is list of strings or dicts. 168 values is list of strings or dicts.
170 plural is plural of name, if not simply name + 's'. 169 plural is plural of name, if not simply name + 's'.
171 separator is used to join values as a string 170 separator is used to join values as a string
172 171
181 180
182 for each value, expand 'foo'. if 'last_foo' in template 181 for each value, expand 'foo'. if 'last_foo' in template
183 map, expand it instead of 'foo' for last key. 182 map, expand it instead of 'foo' for last key.
184 183
185 expand 'end_foos'. 184 expand 'end_foos'.
186 ''' 185 """
187 if not plural: 186 if not plural:
188 plural = name + 's' 187 plural = name + 's'
189 if not values: 188 if not values:
190 noname = 'no_' + plural 189 noname = 'no_' + plural
191 if noname in templ: 190 if context.preload(noname):
192 yield templ.generate(noname, mapping) 191 yield context.process(noname, mapping)
193 return 192 return
194 if name not in templ: 193 if not context.preload(name):
195 if isinstance(values[0], bytes): 194 if isinstance(values[0], bytes):
196 yield separator.join(values) 195 yield separator.join(values)
197 else: 196 else:
198 for v in values: 197 for v in values:
199 r = dict(v) 198 r = dict(v)
200 r.update(mapping) 199 r.update(mapping)
201 yield r 200 yield r
202 return 201 return
203 startname = 'start_' + plural 202 startname = 'start_' + plural
204 if startname in templ: 203 if context.preload(startname):
205 yield templ.generate(startname, mapping) 204 yield context.process(startname, mapping)
206 vmapping = mapping.copy() 205 vmapping = mapping.copy()
207 def one(v, tag=name): 206 def one(v, tag=name):
208 try: 207 try:
209 vmapping.update(v) 208 vmapping.update(v)
210 # Python 2 raises ValueError if the type of v is wrong. Python 209 # Python 2 raises ValueError if the type of v is wrong. Python
215 # bytes. Python 3 raises TypeError. 214 # bytes. Python 3 raises TypeError.
216 for a, b in v: 215 for a, b in v:
217 vmapping[a] = b 216 vmapping[a] = b
218 except (TypeError, ValueError): 217 except (TypeError, ValueError):
219 vmapping[name] = v 218 vmapping[name] = v
220 return templ.generate(tag, vmapping) 219 return context.process(tag, vmapping)
221 lastname = 'last_' + name 220 lastname = 'last_' + name
222 if lastname in templ: 221 if context.preload(lastname):
223 last = values.pop() 222 last = values.pop()
224 else: 223 else:
225 last = None 224 last = None
226 for v in values: 225 for v in values:
227 yield one(v) 226 yield one(v)
228 if last is not None: 227 if last is not None:
229 yield one(last, tag=lastname) 228 yield one(last, tag=lastname)
230 endname = 'end_' + plural 229 endname = 'end_' + plural
231 if endname in templ: 230 if context.preload(endname):
232 yield templ.generate(endname, mapping) 231 yield context.process(endname, mapping)
233 232
234 def stringify(thing): 233 def stringify(thing):
235 """Turn values into bytes by converting into text and concatenating them""" 234 """Turn values into bytes by converting into text and concatenating them"""
236 thing = unwraphybrid(thing) 235 thing = unwraphybrid(thing)
237 if util.safehasattr(thing, '__iter__') and not isinstance(thing, bytes): 236 if util.safehasattr(thing, '__iter__') and not isinstance(thing, bytes):