Mercurial > public > mercurial-scm > hg
comparison mercurial/templateutil.py @ 43077:687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Done with
python3.7 contrib/byteify-strings.py -i $(hg files 'set:mercurial/**.py - mercurial/thirdparty/** + hgext/**.py - hgext/fsmonitor/pywatchman/** - mercurial/__init__.py')
black -l 80 -t py33 -S $(hg files 'set:**.py - mercurial/thirdparty/** - "contrib/python-zstandard/**" - hgext/fsmonitor/pywatchman/**')
# skip-blame mass-reformatting only
Differential Revision: https://phab.mercurial-scm.org/D6972
author | Augie Fackler <augie@google.com> |
---|---|
date | Sun, 06 Oct 2019 09:48:39 -0400 |
parents | 2372284d9457 |
children | c59eb1560c44 |
comparison
equal
deleted
inserted
replaced
43076:2372284d9457 | 43077:687b865b95ad |
---|---|
128 item = stringify(context, mapping, item) | 128 item = stringify(context, mapping, item) |
129 return item in self._value | 129 return item in self._value |
130 | 130 |
131 def getmember(self, context, mapping, key): | 131 def getmember(self, context, mapping, key): |
132 raise error.ParseError( | 132 raise error.ParseError( |
133 _('%r is not a dictionary') % pycompat.bytestr(self._value) | 133 _(b'%r is not a dictionary') % pycompat.bytestr(self._value) |
134 ) | 134 ) |
135 | 135 |
136 def getmin(self, context, mapping): | 136 def getmin(self, context, mapping): |
137 return self._getby(context, mapping, min) | 137 return self._getby(context, mapping, min) |
138 | 138 |
139 def getmax(self, context, mapping): | 139 def getmax(self, context, mapping): |
140 return self._getby(context, mapping, max) | 140 return self._getby(context, mapping, max) |
141 | 141 |
142 def _getby(self, context, mapping, func): | 142 def _getby(self, context, mapping, func): |
143 if not self._value: | 143 if not self._value: |
144 raise error.ParseError(_('empty string')) | 144 raise error.ParseError(_(b'empty string')) |
145 return func(pycompat.iterbytestr(self._value)) | 145 return func(pycompat.iterbytestr(self._value)) |
146 | 146 |
147 def filter(self, context, mapping, select): | 147 def filter(self, context, mapping, select): |
148 raise error.ParseError( | 148 raise error.ParseError( |
149 _('%r is not filterable') % pycompat.bytestr(self._value) | 149 _(b'%r is not filterable') % pycompat.bytestr(self._value) |
150 ) | 150 ) |
151 | 151 |
152 def itermaps(self, context): | 152 def itermaps(self, context): |
153 raise error.ParseError( | 153 raise error.ParseError( |
154 _('%r is not iterable of mappings') % pycompat.bytestr(self._value) | 154 _(b'%r is not iterable of mappings') % pycompat.bytestr(self._value) |
155 ) | 155 ) |
156 | 156 |
157 def join(self, context, mapping, sep): | 157 def join(self, context, mapping, sep): |
158 return joinitems(pycompat.iterbytestr(self._value), sep) | 158 return joinitems(pycompat.iterbytestr(self._value), sep) |
159 | 159 |
172 | 172 |
173 def __init__(self, value): | 173 def __init__(self, value): |
174 self._value = value | 174 self._value = value |
175 | 175 |
176 def contains(self, context, mapping, item): | 176 def contains(self, context, mapping, item): |
177 raise error.ParseError(_("%r is not iterable") % self._value) | 177 raise error.ParseError(_(b"%r is not iterable") % self._value) |
178 | 178 |
179 def getmember(self, context, mapping, key): | 179 def getmember(self, context, mapping, key): |
180 raise error.ParseError(_('%r is not a dictionary') % self._value) | 180 raise error.ParseError(_(b'%r is not a dictionary') % self._value) |
181 | 181 |
182 def getmin(self, context, mapping): | 182 def getmin(self, context, mapping): |
183 raise error.ParseError(_("%r is not iterable") % self._value) | 183 raise error.ParseError(_(b"%r is not iterable") % self._value) |
184 | 184 |
185 def getmax(self, context, mapping): | 185 def getmax(self, context, mapping): |
186 raise error.ParseError(_("%r is not iterable") % self._value) | 186 raise error.ParseError(_(b"%r is not iterable") % self._value) |
187 | 187 |
188 def filter(self, context, mapping, select): | 188 def filter(self, context, mapping, select): |
189 raise error.ParseError(_("%r is not iterable") % self._value) | 189 raise error.ParseError(_(b"%r is not iterable") % self._value) |
190 | 190 |
191 def itermaps(self, context): | 191 def itermaps(self, context): |
192 raise error.ParseError( | 192 raise error.ParseError( |
193 _('%r is not iterable of mappings') % self._value | 193 _(b'%r is not iterable of mappings') % self._value |
194 ) | 194 ) |
195 | 195 |
196 def join(self, context, mapping, sep): | 196 def join(self, context, mapping, sep): |
197 raise error.ParseError(_('%r is not iterable') % self._value) | 197 raise error.ParseError(_(b'%r is not iterable') % self._value) |
198 | 198 |
199 def show(self, context, mapping): | 199 def show(self, context, mapping): |
200 if self._value is None: | 200 if self._value is None: |
201 return b'' | 201 return b'' |
202 return pycompat.bytestr(self._value) | 202 return pycompat.bytestr(self._value) |
214 | 214 |
215 | 215 |
216 class date(mappable, wrapped): | 216 class date(mappable, wrapped): |
217 """Wrapper for date tuple""" | 217 """Wrapper for date tuple""" |
218 | 218 |
219 def __init__(self, value, showfmt='%d %d'): | 219 def __init__(self, value, showfmt=b'%d %d'): |
220 # value may be (float, int), but public interface shouldn't support | 220 # value may be (float, int), but public interface shouldn't support |
221 # floating-point timestamp | 221 # floating-point timestamp |
222 self._unixtime, self._tzoffset = map(int, value) | 222 self._unixtime, self._tzoffset = map(int, value) |
223 self._showfmt = showfmt | 223 self._showfmt = showfmt |
224 | 224 |
225 def contains(self, context, mapping, item): | 225 def contains(self, context, mapping, item): |
226 raise error.ParseError(_('date is not iterable')) | 226 raise error.ParseError(_(b'date is not iterable')) |
227 | 227 |
228 def getmember(self, context, mapping, key): | 228 def getmember(self, context, mapping, key): |
229 raise error.ParseError(_('date is not a dictionary')) | 229 raise error.ParseError(_(b'date is not a dictionary')) |
230 | 230 |
231 def getmin(self, context, mapping): | 231 def getmin(self, context, mapping): |
232 raise error.ParseError(_('date is not iterable')) | 232 raise error.ParseError(_(b'date is not iterable')) |
233 | 233 |
234 def getmax(self, context, mapping): | 234 def getmax(self, context, mapping): |
235 raise error.ParseError(_('date is not iterable')) | 235 raise error.ParseError(_(b'date is not iterable')) |
236 | 236 |
237 def filter(self, context, mapping, select): | 237 def filter(self, context, mapping, select): |
238 raise error.ParseError(_('date is not iterable')) | 238 raise error.ParseError(_(b'date is not iterable')) |
239 | 239 |
240 def join(self, context, mapping, sep): | 240 def join(self, context, mapping, sep): |
241 raise error.ParseError(_("date is not iterable")) | 241 raise error.ParseError(_(b"date is not iterable")) |
242 | 242 |
243 def show(self, context, mapping): | 243 def show(self, context, mapping): |
244 return self._showfmt % (self._unixtime, self._tzoffset) | 244 return self._showfmt % (self._unixtime, self._tzoffset) |
245 | 245 |
246 def tomap(self, context): | 246 def tomap(self, context): |
247 return {'unixtime': self._unixtime, 'tzoffset': self._tzoffset} | 247 return {b'unixtime': self._unixtime, b'tzoffset': self._tzoffset} |
248 | 248 |
249 def tobool(self, context, mapping): | 249 def tobool(self, context, mapping): |
250 return True | 250 return True |
251 | 251 |
252 def tovalue(self, context, mapping): | 252 def tovalue(self, context, mapping): |
276 item = unwrapastype(context, mapping, item, self._keytype) | 276 item = unwrapastype(context, mapping, item, self._keytype) |
277 return item in self._values | 277 return item in self._values |
278 | 278 |
279 def getmember(self, context, mapping, key): | 279 def getmember(self, context, mapping, key): |
280 # TODO: maybe split hybrid list/dict types? | 280 # TODO: maybe split hybrid list/dict types? |
281 if not util.safehasattr(self._values, 'get'): | 281 if not util.safehasattr(self._values, b'get'): |
282 raise error.ParseError(_('not a dictionary')) | 282 raise error.ParseError(_(b'not a dictionary')) |
283 key = unwrapastype(context, mapping, key, self._keytype) | 283 key = unwrapastype(context, mapping, key, self._keytype) |
284 return self._wrapvalue(key, self._values.get(key)) | 284 return self._wrapvalue(key, self._values.get(key)) |
285 | 285 |
286 def getmin(self, context, mapping): | 286 def getmin(self, context, mapping): |
287 return self._getby(context, mapping, min) | 287 return self._getby(context, mapping, min) |
289 def getmax(self, context, mapping): | 289 def getmax(self, context, mapping): |
290 return self._getby(context, mapping, max) | 290 return self._getby(context, mapping, max) |
291 | 291 |
292 def _getby(self, context, mapping, func): | 292 def _getby(self, context, mapping, func): |
293 if not self._values: | 293 if not self._values: |
294 raise error.ParseError(_('empty sequence')) | 294 raise error.ParseError(_(b'empty sequence')) |
295 val = func(self._values) | 295 val = func(self._values) |
296 return self._wrapvalue(val, val) | 296 return self._wrapvalue(val, val) |
297 | 297 |
298 def _wrapvalue(self, key, val): | 298 def _wrapvalue(self, key, val): |
299 if val is None: | 299 if val is None: |
300 return | 300 return |
301 if util.safehasattr(val, '_makemap'): | 301 if util.safehasattr(val, b'_makemap'): |
302 # a nested hybrid list/dict, which has its own way of map operation | 302 # a nested hybrid list/dict, which has its own way of map operation |
303 return val | 303 return val |
304 return hybriditem(None, key, val, self._makemap) | 304 return hybriditem(None, key, val, self._makemap) |
305 | 305 |
306 def filter(self, context, mapping, select): | 306 def filter(self, context, mapping, select): |
307 if util.safehasattr(self._values, 'get'): | 307 if util.safehasattr(self._values, b'get'): |
308 values = { | 308 values = { |
309 k: v | 309 k: v |
310 for k, v in self._values.iteritems() | 310 for k, v in self._values.iteritems() |
311 if select(self._wrapvalue(k, v)) | 311 if select(self._wrapvalue(k, v)) |
312 } | 312 } |
325 | 325 |
326 def show(self, context, mapping): | 326 def show(self, context, mapping): |
327 # TODO: switch gen to (context, mapping) API? | 327 # TODO: switch gen to (context, mapping) API? |
328 gen = self._gen | 328 gen = self._gen |
329 if gen is None: | 329 if gen is None: |
330 return self.join(context, mapping, ' ') | 330 return self.join(context, mapping, b' ') |
331 if callable(gen): | 331 if callable(gen): |
332 return gen() | 332 return gen() |
333 return gen | 333 return gen |
334 | 334 |
335 def tobool(self, context, mapping): | 335 def tobool(self, context, mapping): |
336 return bool(self._values) | 336 return bool(self._values) |
337 | 337 |
338 def tovalue(self, context, mapping): | 338 def tovalue(self, context, mapping): |
339 # TODO: make it non-recursive for trivial lists/dicts | 339 # TODO: make it non-recursive for trivial lists/dicts |
340 xs = self._values | 340 xs = self._values |
341 if util.safehasattr(xs, 'get'): | 341 if util.safehasattr(xs, b'get'): |
342 return { | 342 return { |
343 k: unwrapvalue(context, mapping, v) for k, v in xs.iteritems() | 343 k: unwrapvalue(context, mapping, v) for k, v in xs.iteritems() |
344 } | 344 } |
345 return [unwrapvalue(context, mapping, x) for x in xs] | 345 return [unwrapvalue(context, mapping, x) for x in xs] |
346 | 346 |
411 which can also be rendered by the specified named/literal template. | 411 which can also be rendered by the specified named/literal template. |
412 | 412 |
413 Template mappings may be nested. | 413 Template mappings may be nested. |
414 """ | 414 """ |
415 | 415 |
416 def __init__(self, name=None, tmpl=None, sep=''): | 416 def __init__(self, name=None, tmpl=None, sep=b''): |
417 if name is not None and tmpl is not None: | 417 if name is not None and tmpl is not None: |
418 raise error.ProgrammingError('name and tmpl are mutually exclusive') | 418 raise error.ProgrammingError( |
419 b'name and tmpl are mutually exclusive' | |
420 ) | |
419 self._name = name | 421 self._name = name |
420 self._tmpl = tmpl | 422 self._tmpl = tmpl |
421 self._defaultsep = sep | 423 self._defaultsep = sep |
422 | 424 |
423 def contains(self, context, mapping, item): | 425 def contains(self, context, mapping, item): |
424 raise error.ParseError(_('not comparable')) | 426 raise error.ParseError(_(b'not comparable')) |
425 | 427 |
426 def getmember(self, context, mapping, key): | 428 def getmember(self, context, mapping, key): |
427 raise error.ParseError(_('not a dictionary')) | 429 raise error.ParseError(_(b'not a dictionary')) |
428 | 430 |
429 def getmin(self, context, mapping): | 431 def getmin(self, context, mapping): |
430 raise error.ParseError(_('not comparable')) | 432 raise error.ParseError(_(b'not comparable')) |
431 | 433 |
432 def getmax(self, context, mapping): | 434 def getmax(self, context, mapping): |
433 raise error.ParseError(_('not comparable')) | 435 raise error.ParseError(_(b'not comparable')) |
434 | 436 |
435 def filter(self, context, mapping, select): | 437 def filter(self, context, mapping, select): |
436 # implement if necessary; we'll need a wrapped type for a mapping dict | 438 # implement if necessary; we'll need a wrapped type for a mapping dict |
437 raise error.ParseError(_('not filterable without template')) | 439 raise error.ParseError(_(b'not filterable without template')) |
438 | 440 |
439 def join(self, context, mapping, sep): | 441 def join(self, context, mapping, sep): |
440 mapsiter = _iteroverlaymaps(context, mapping, self.itermaps(context)) | 442 mapsiter = _iteroverlaymaps(context, mapping, self.itermaps(context)) |
441 if self._name: | 443 if self._name: |
442 itemiter = (context.process(self._name, m) for m in mapsiter) | 444 itemiter = (context.process(self._name, m) for m in mapsiter) |
443 elif self._tmpl: | 445 elif self._tmpl: |
444 itemiter = (context.expand(self._tmpl, m) for m in mapsiter) | 446 itemiter = (context.expand(self._tmpl, m) for m in mapsiter) |
445 else: | 447 else: |
446 raise error.ParseError(_('not displayable without template')) | 448 raise error.ParseError(_(b'not displayable without template')) |
447 return joinitems(itemiter, sep) | 449 return joinitems(itemiter, sep) |
448 | 450 |
449 def show(self, context, mapping): | 451 def show(self, context, mapping): |
450 return self.join(context, mapping, self._defaultsep) | 452 return self.join(context, mapping, self._defaultsep) |
451 | 453 |
470 | 472 |
471 The function ``make(context, *args)`` should return a generator of | 473 The function ``make(context, *args)`` should return a generator of |
472 mapping dicts. | 474 mapping dicts. |
473 """ | 475 """ |
474 | 476 |
475 def __init__(self, make, args=(), name=None, tmpl=None, sep=''): | 477 def __init__(self, make, args=(), name=None, tmpl=None, sep=b''): |
476 super(mappinggenerator, self).__init__(name, tmpl, sep) | 478 super(mappinggenerator, self).__init__(name, tmpl, sep) |
477 self._make = make | 479 self._make = make |
478 self._args = args | 480 self._args = args |
479 | 481 |
480 def itermaps(self, context): | 482 def itermaps(self, context): |
485 | 487 |
486 | 488 |
487 class mappinglist(_mappingsequence): | 489 class mappinglist(_mappingsequence): |
488 """Wrapper for list of template mappings""" | 490 """Wrapper for list of template mappings""" |
489 | 491 |
490 def __init__(self, mappings, name=None, tmpl=None, sep=''): | 492 def __init__(self, mappings, name=None, tmpl=None, sep=b''): |
491 super(mappinglist, self).__init__(name, tmpl, sep) | 493 super(mappinglist, self).__init__(name, tmpl, sep) |
492 self._mappings = mappings | 494 self._mappings = mappings |
493 | 495 |
494 def itermaps(self, context): | 496 def itermaps(self, context): |
495 return iter(self._mappings) | 497 return iter(self._mappings) |
554 | 556 |
555 def _gen(self, context): | 557 def _gen(self, context): |
556 return self._make(context, *self._args) | 558 return self._make(context, *self._args) |
557 | 559 |
558 def getmember(self, context, mapping, key): | 560 def getmember(self, context, mapping, key): |
559 raise error.ParseError(_('not a dictionary')) | 561 raise error.ParseError(_(b'not a dictionary')) |
560 | 562 |
561 def getmin(self, context, mapping): | 563 def getmin(self, context, mapping): |
562 return self._getby(context, mapping, min) | 564 return self._getby(context, mapping, min) |
563 | 565 |
564 def getmax(self, context, mapping): | 566 def getmax(self, context, mapping): |
565 return self._getby(context, mapping, max) | 567 return self._getby(context, mapping, max) |
566 | 568 |
567 def _getby(self, context, mapping, func): | 569 def _getby(self, context, mapping, func): |
568 xs = self.tovalue(context, mapping) | 570 xs = self.tovalue(context, mapping) |
569 if not xs: | 571 if not xs: |
570 raise error.ParseError(_('empty sequence')) | 572 raise error.ParseError(_(b'empty sequence')) |
571 return func(xs) | 573 return func(xs) |
572 | 574 |
573 @staticmethod | 575 @staticmethod |
574 def _filteredgen(context, mapping, make, args, select): | 576 def _filteredgen(context, mapping, make, args, select): |
575 for x in make(context, *args): | 577 for x in make(context, *args): |
580 def filter(self, context, mapping, select): | 582 def filter(self, context, mapping, select): |
581 args = (mapping, self._make, self._args, select) | 583 args = (mapping, self._make, self._args, select) |
582 return mappedgenerator(self._filteredgen, args) | 584 return mappedgenerator(self._filteredgen, args) |
583 | 585 |
584 def itermaps(self, context): | 586 def itermaps(self, context): |
585 raise error.ParseError(_('list of strings is not mappable')) | 587 raise error.ParseError(_(b'list of strings is not mappable')) |
586 | 588 |
587 def join(self, context, mapping, sep): | 589 def join(self, context, mapping, sep): |
588 return joinitems(self._gen(context), sep) | 590 return joinitems(self._gen(context), sep) |
589 | 591 |
590 def show(self, context, mapping): | 592 def show(self, context, mapping): |
591 return self.join(context, mapping, '') | 593 return self.join(context, mapping, b'') |
592 | 594 |
593 def tobool(self, context, mapping): | 595 def tobool(self, context, mapping): |
594 return _nonempty(self._gen(context)) | 596 return _nonempty(self._gen(context)) |
595 | 597 |
596 def tovalue(self, context, mapping): | 598 def tovalue(self, context, mapping): |
597 return [stringify(context, mapping, x) for x in self._gen(context)] | 599 return [stringify(context, mapping, x) for x in self._gen(context)] |
598 | 600 |
599 | 601 |
600 def hybriddict(data, key='key', value='value', fmt=None, gen=None): | 602 def hybriddict(data, key=b'key', value=b'value', fmt=None, gen=None): |
601 """Wrap data to support both dict-like and string-like operations""" | 603 """Wrap data to support both dict-like and string-like operations""" |
602 prefmt = pycompat.identity | 604 prefmt = pycompat.identity |
603 if fmt is None: | 605 if fmt is None: |
604 fmt = '%s=%s' | 606 fmt = b'%s=%s' |
605 prefmt = pycompat.bytestr | 607 prefmt = pycompat.bytestr |
606 return hybrid( | 608 return hybrid( |
607 gen, | 609 gen, |
608 data, | 610 data, |
609 lambda k: {key: k, value: data[k]}, | 611 lambda k: {key: k, value: data[k]}, |
613 | 615 |
614 def hybridlist(data, name, fmt=None, gen=None): | 616 def hybridlist(data, name, fmt=None, gen=None): |
615 """Wrap data to support both list-like and string-like operations""" | 617 """Wrap data to support both list-like and string-like operations""" |
616 prefmt = pycompat.identity | 618 prefmt = pycompat.identity |
617 if fmt is None: | 619 if fmt is None: |
618 fmt = '%s' | 620 fmt = b'%s' |
619 prefmt = pycompat.bytestr | 621 prefmt = pycompat.bytestr |
620 return hybrid(gen, data, lambda x: {name: x}, lambda x: fmt % prefmt(x)) | 622 return hybrid(gen, data, lambda x: {name: x}, lambda x: fmt % prefmt(x)) |
621 | 623 |
622 | 624 |
623 def compatdict( | 625 def compatdict( |
624 context, | 626 context, |
625 mapping, | 627 mapping, |
626 name, | 628 name, |
627 data, | 629 data, |
628 key='key', | 630 key=b'key', |
629 value='value', | 631 value=b'value', |
630 fmt=None, | 632 fmt=None, |
631 plural=None, | 633 plural=None, |
632 separator=' ', | 634 separator=b' ', |
633 ): | 635 ): |
634 """Wrap data like hybriddict(), but also supports old-style list template | 636 """Wrap data like hybriddict(), but also supports old-style list template |
635 | 637 |
636 This exists for backward compatibility with the old-style template. Use | 638 This exists for backward compatibility with the old-style template. Use |
637 hybriddict() for new template keywords. | 639 hybriddict() for new template keywords. |
647 name, | 649 name, |
648 data, | 650 data, |
649 element=None, | 651 element=None, |
650 fmt=None, | 652 fmt=None, |
651 plural=None, | 653 plural=None, |
652 separator=' ', | 654 separator=b' ', |
653 ): | 655 ): |
654 """Wrap data like hybridlist(), but also supports old-style list template | 656 """Wrap data like hybridlist(), but also supports old-style list template |
655 | 657 |
656 This exists for backward compatibility with the old-style template. Use | 658 This exists for backward compatibility with the old-style template. Use |
657 hybridlist() for new template keywords. | 659 hybridlist() for new template keywords. |
666 | 668 |
667 This exists for backward compatibility. Use hybriddict for new template | 669 This exists for backward compatibility. Use hybriddict for new template |
668 keywords. | 670 keywords. |
669 """ | 671 """ |
670 # no need to provide {path} to old-style list template | 672 # no need to provide {path} to old-style list template |
671 c = [{'name': k, 'source': v} for k, v in copies] | 673 c = [{b'name': k, b'source': v} for k, v in copies] |
672 f = _showcompatlist(context, mapping, name, c, plural='file_copies') | 674 f = _showcompatlist(context, mapping, name, c, plural=b'file_copies') |
673 copies = util.sortdict(copies) | 675 copies = util.sortdict(copies) |
674 return hybrid( | 676 return hybrid( |
675 f, | 677 f, |
676 copies, | 678 copies, |
677 lambda k: {'name': k, 'path': k, 'source': copies[k]}, | 679 lambda k: {b'name': k, b'path': k, b'source': copies[k]}, |
678 lambda k: '%s (%s)' % (k, copies[k]), | 680 lambda k: b'%s (%s)' % (k, copies[k]), |
679 ) | 681 ) |
680 | 682 |
681 | 683 |
682 def compatfileslist(context, mapping, name, files): | 684 def compatfileslist(context, mapping, name, files): |
683 """Wrap list of file names to support old-style list template and field | 685 """Wrap list of file names to support old-style list template and field |
685 | 687 |
686 This exists for backward compatibility. Use hybridlist for new template | 688 This exists for backward compatibility. Use hybridlist for new template |
687 keywords. | 689 keywords. |
688 """ | 690 """ |
689 f = _showcompatlist(context, mapping, name, files) | 691 f = _showcompatlist(context, mapping, name, files) |
690 return hybrid(f, files, lambda x: {'file': x, 'path': x}, pycompat.identity) | 692 return hybrid( |
691 | 693 f, files, lambda x: {b'file': x, b'path': x}, pycompat.identity |
692 | 694 ) |
693 def _showcompatlist(context, mapping, name, values, plural=None, separator=' '): | 695 |
696 | |
697 def _showcompatlist( | |
698 context, mapping, name, values, plural=None, separator=b' ' | |
699 ): | |
694 """Return a generator that renders old-style list template | 700 """Return a generator that renders old-style list template |
695 | 701 |
696 name is name of key in template map. | 702 name is name of key in template map. |
697 values is list of strings or dicts. | 703 values is list of strings or dicts. |
698 plural is plural of name, if not simply name + 's'. | 704 plural is plural of name, if not simply name + 's'. |
711 map, expand it instead of 'foo' for last key. | 717 map, expand it instead of 'foo' for last key. |
712 | 718 |
713 expand 'end_foos'. | 719 expand 'end_foos'. |
714 """ | 720 """ |
715 if not plural: | 721 if not plural: |
716 plural = name + 's' | 722 plural = name + b's' |
717 if not values: | 723 if not values: |
718 noname = 'no_' + plural | 724 noname = b'no_' + plural |
719 if context.preload(noname): | 725 if context.preload(noname): |
720 yield context.process(noname, mapping) | 726 yield context.process(noname, mapping) |
721 return | 727 return |
722 if not context.preload(name): | 728 if not context.preload(name): |
723 if isinstance(values[0], bytes): | 729 if isinstance(values[0], bytes): |
726 for v in values: | 732 for v in values: |
727 r = dict(v) | 733 r = dict(v) |
728 r.update(mapping) | 734 r.update(mapping) |
729 yield r | 735 yield r |
730 return | 736 return |
731 startname = 'start_' + plural | 737 startname = b'start_' + plural |
732 if context.preload(startname): | 738 if context.preload(startname): |
733 yield context.process(startname, mapping) | 739 yield context.process(startname, mapping) |
734 | 740 |
735 def one(v, tag=name): | 741 def one(v, tag=name): |
736 vmapping = {} | 742 vmapping = {} |
747 except (TypeError, ValueError): | 753 except (TypeError, ValueError): |
748 vmapping[name] = v | 754 vmapping[name] = v |
749 vmapping = context.overlaymap(mapping, vmapping) | 755 vmapping = context.overlaymap(mapping, vmapping) |
750 return context.process(tag, vmapping) | 756 return context.process(tag, vmapping) |
751 | 757 |
752 lastname = 'last_' + name | 758 lastname = b'last_' + name |
753 if context.preload(lastname): | 759 if context.preload(lastname): |
754 last = values.pop() | 760 last = values.pop() |
755 else: | 761 else: |
756 last = None | 762 last = None |
757 for v in values: | 763 for v in values: |
758 yield one(v) | 764 yield one(v) |
759 if last is not None: | 765 if last is not None: |
760 yield one(last, tag=lastname) | 766 yield one(last, tag=lastname) |
761 endname = 'end_' + plural | 767 endname = b'end_' + plural |
762 if context.preload(endname): | 768 if context.preload(endname): |
763 yield context.process(endname, mapping) | 769 yield context.process(endname, mapping) |
764 | 770 |
765 | 771 |
766 def flatten(context, mapping, thing): | 772 def flatten(context, mapping, thing): |
771 yield thing | 777 yield thing |
772 elif isinstance(thing, str): | 778 elif isinstance(thing, str): |
773 # We can only hit this on Python 3, and it's here to guard | 779 # We can only hit this on Python 3, and it's here to guard |
774 # against infinite recursion. | 780 # against infinite recursion. |
775 raise error.ProgrammingError( | 781 raise error.ProgrammingError( |
776 'Mercurial IO including templates is done' | 782 b'Mercurial IO including templates is done' |
777 ' with bytes, not strings, got %r' % thing | 783 b' with bytes, not strings, got %r' % thing |
778 ) | 784 ) |
779 elif thing is None: | 785 elif thing is None: |
780 pass | 786 pass |
781 elif not util.safehasattr(thing, '__iter__'): | 787 elif not util.safehasattr(thing, b'__iter__'): |
782 yield pycompat.bytestr(thing) | 788 yield pycompat.bytestr(thing) |
783 else: | 789 else: |
784 for i in thing: | 790 for i in thing: |
785 if isinstance(i, wrapped): | 791 if isinstance(i, wrapped): |
786 i = i.show(context, mapping) | 792 i = i.show(context, mapping) |
787 if isinstance(i, bytes): | 793 if isinstance(i, bytes): |
788 yield i | 794 yield i |
789 elif i is None: | 795 elif i is None: |
790 pass | 796 pass |
791 elif not util.safehasattr(i, '__iter__'): | 797 elif not util.safehasattr(i, b'__iter__'): |
792 yield pycompat.bytestr(i) | 798 yield pycompat.bytestr(i) |
793 else: | 799 else: |
794 for j in flatten(context, mapping, i): | 800 for j in flatten(context, mapping, i): |
795 yield j | 801 yield j |
796 | 802 |
893 # TODO: update hgweb to not return bare tuple; then just stringify 'thing' | 899 # TODO: update hgweb to not return bare tuple; then just stringify 'thing' |
894 thing = unwrapvalue(context, mapping, thing) | 900 thing = unwrapvalue(context, mapping, thing) |
895 try: | 901 try: |
896 return dateutil.parsedate(thing) | 902 return dateutil.parsedate(thing) |
897 except AttributeError: | 903 except AttributeError: |
898 raise error.ParseError(err or _('not a date tuple nor a string')) | 904 raise error.ParseError(err or _(b'not a date tuple nor a string')) |
899 except error.ParseError: | 905 except error.ParseError: |
900 if not err: | 906 if not err: |
901 raise | 907 raise |
902 raise error.ParseError(err) | 908 raise error.ParseError(err) |
903 | 909 |
910 def unwrapinteger(context, mapping, thing, err=None): | 916 def unwrapinteger(context, mapping, thing, err=None): |
911 thing = unwrapvalue(context, mapping, thing) | 917 thing = unwrapvalue(context, mapping, thing) |
912 try: | 918 try: |
913 return int(thing) | 919 return int(thing) |
914 except (TypeError, ValueError): | 920 except (TypeError, ValueError): |
915 raise error.ParseError(err or _('not an integer')) | 921 raise error.ParseError(err or _(b'not an integer')) |
916 | 922 |
917 | 923 |
918 def evalstring(context, mapping, arg): | 924 def evalstring(context, mapping, arg): |
919 return stringify(context, mapping, evalrawexp(context, mapping, arg)) | 925 return stringify(context, mapping, evalrawexp(context, mapping, arg)) |
920 | 926 |
941 def unwrapastype(context, mapping, thing, typ): | 947 def unwrapastype(context, mapping, thing, typ): |
942 """Move the inner value object out of the wrapper and coerce its type""" | 948 """Move the inner value object out of the wrapper and coerce its type""" |
943 try: | 949 try: |
944 f = _unwrapfuncbytype[typ] | 950 f = _unwrapfuncbytype[typ] |
945 except KeyError: | 951 except KeyError: |
946 raise error.ProgrammingError('invalid type specified: %r' % typ) | 952 raise error.ProgrammingError(b'invalid type specified: %r' % typ) |
947 return f(context, mapping, thing) | 953 return f(context, mapping, thing) |
948 | 954 |
949 | 955 |
950 def runinteger(context, mapping, data): | 956 def runinteger(context, mapping, data): |
951 return int(data) | 957 return int(data) |
955 return data | 961 return data |
956 | 962 |
957 | 963 |
958 def _recursivesymbolblocker(key): | 964 def _recursivesymbolblocker(key): |
959 def showrecursion(context, mapping): | 965 def showrecursion(context, mapping): |
960 raise error.Abort(_("recursive reference '%s' in template") % key) | 966 raise error.Abort(_(b"recursive reference '%s' in template") % key) |
961 | 967 |
962 return showrecursion | 968 return showrecursion |
963 | 969 |
964 | 970 |
965 def runsymbol(context, mapping, key, default=''): | 971 def runsymbol(context, mapping, key, default=b''): |
966 v = context.symbol(mapping, key) | 972 v = context.symbol(mapping, key) |
967 if v is None: | 973 if v is None: |
968 # put poison to cut recursion. we can't move this to parsing phase | 974 # put poison to cut recursion. we can't move this to parsing phase |
969 # because "x = {x}" is allowed if "x" is a keyword. (issue4758) | 975 # because "x = {x}" is allowed if "x" is a keyword. (issue4758) |
970 safemapping = mapping.copy() | 976 safemapping = mapping.copy() |
1001 | 1007 |
1002 def _formatfiltererror(arg, filt): | 1008 def _formatfiltererror(arg, filt): |
1003 fn = pycompat.sysbytes(filt.__name__) | 1009 fn = pycompat.sysbytes(filt.__name__) |
1004 sym = findsymbolicname(arg) | 1010 sym = findsymbolicname(arg) |
1005 if not sym: | 1011 if not sym: |
1006 return _("incompatible use of template filter '%s'") % fn | 1012 return _(b"incompatible use of template filter '%s'") % fn |
1007 return _("template filter '%s' is not compatible with keyword '%s'") % ( | 1013 return _(b"template filter '%s' is not compatible with keyword '%s'") % ( |
1008 fn, | 1014 fn, |
1009 sym, | 1015 sym, |
1010 ) | 1016 ) |
1011 | 1017 |
1012 | 1018 |
1013 def _iteroverlaymaps(context, origmapping, newmappings): | 1019 def _iteroverlaymaps(context, origmapping, newmappings): |
1014 """Generate combined mappings from the original mapping and an iterable | 1020 """Generate combined mappings from the original mapping and an iterable |
1015 of partial mappings to override the original""" | 1021 of partial mappings to override the original""" |
1016 for i, nm in enumerate(newmappings): | 1022 for i, nm in enumerate(newmappings): |
1017 lm = context.overlaymap(origmapping, nm) | 1023 lm = context.overlaymap(origmapping, nm) |
1018 lm['index'] = i | 1024 lm[b'index'] = i |
1019 yield lm | 1025 yield lm |
1020 | 1026 |
1021 | 1027 |
1022 def _applymap(context, mapping, d, darg, targ): | 1028 def _applymap(context, mapping, d, darg, targ): |
1023 try: | 1029 try: |
1024 diter = d.itermaps(context) | 1030 diter = d.itermaps(context) |
1025 except error.ParseError as err: | 1031 except error.ParseError as err: |
1026 sym = findsymbolicname(darg) | 1032 sym = findsymbolicname(darg) |
1027 if not sym: | 1033 if not sym: |
1028 raise | 1034 raise |
1029 hint = _("keyword '%s' does not support map operation") % sym | 1035 hint = _(b"keyword '%s' does not support map operation") % sym |
1030 raise error.ParseError(bytes(err), hint=hint) | 1036 raise error.ParseError(bytes(err), hint=hint) |
1031 for lm in _iteroverlaymaps(context, mapping, diter): | 1037 for lm in _iteroverlaymaps(context, mapping, diter): |
1032 yield evalrawexp(context, lm, targ) | 1038 yield evalrawexp(context, lm, targ) |
1033 | 1039 |
1034 | 1040 |
1048 return d.getmember(context, mapping, memb) | 1054 return d.getmember(context, mapping, memb) |
1049 except error.ParseError as err: | 1055 except error.ParseError as err: |
1050 sym = findsymbolicname(darg) | 1056 sym = findsymbolicname(darg) |
1051 if not sym: | 1057 if not sym: |
1052 raise | 1058 raise |
1053 hint = _("keyword '%s' does not support member operation") % sym | 1059 hint = _(b"keyword '%s' does not support member operation") % sym |
1054 raise error.ParseError(bytes(err), hint=hint) | 1060 raise error.ParseError(bytes(err), hint=hint) |
1055 | 1061 |
1056 | 1062 |
1057 def runnegate(context, mapping, data): | 1063 def runnegate(context, mapping, data): |
1058 data = evalinteger( | 1064 data = evalinteger( |
1059 context, mapping, data, _('negation needs an integer argument') | 1065 context, mapping, data, _(b'negation needs an integer argument') |
1060 ) | 1066 ) |
1061 return -data | 1067 return -data |
1062 | 1068 |
1063 | 1069 |
1064 def runarithmetic(context, mapping, data): | 1070 def runarithmetic(context, mapping, data): |
1065 func, left, right = data | 1071 func, left, right = data |
1066 left = evalinteger( | 1072 left = evalinteger( |
1067 context, mapping, left, _('arithmetic only defined on integers') | 1073 context, mapping, left, _(b'arithmetic only defined on integers') |
1068 ) | 1074 ) |
1069 right = evalinteger( | 1075 right = evalinteger( |
1070 context, mapping, right, _('arithmetic only defined on integers') | 1076 context, mapping, right, _(b'arithmetic only defined on integers') |
1071 ) | 1077 ) |
1072 try: | 1078 try: |
1073 return func(left, right) | 1079 return func(left, right) |
1074 except ZeroDivisionError: | 1080 except ZeroDivisionError: |
1075 raise error.Abort(_('division by zero is not defined')) | 1081 raise error.Abort(_(b'division by zero is not defined')) |
1076 | 1082 |
1077 | 1083 |
1078 def joinitems(itemiter, sep): | 1084 def joinitems(itemiter, sep): |
1079 """Join items with the separator; Returns generator of bytes""" | 1085 """Join items with the separator; Returns generator of bytes""" |
1080 first = True | 1086 first = True |