Formatter allowing Itpl style $foo replacement, for names and attribute access only. Standard {foo} replacement also works, and allows full evaluation of its arguments. Examples -------- :: In [1]: f = DollarFormatter() In [2]: f.format('{n//4}', n=8) Ou
| 570 | |
| 571 | |
| 572 | class DollarFormatter(FullEvalFormatter): |
| 573 | """Formatter allowing Itpl style $foo replacement, for names and attribute |
| 574 | access only. Standard {foo} replacement also works, and allows full |
| 575 | evaluation of its arguments. |
| 576 | |
| 577 | Examples |
| 578 | -------- |
| 579 | :: |
| 580 | |
| 581 | In [1]: f = DollarFormatter() |
| 582 | In [2]: f.format('{n//4}', n=8) |
| 583 | Out[2]: '2' |
| 584 | |
| 585 | In [3]: f.format('23 * 76 is $result', result=23*76) |
| 586 | Out[3]: '23 * 76 is 1748' |
| 587 | |
| 588 | In [4]: f.format('$a or {b}', a=1, b=2) |
| 589 | Out[4]: '1 or 2' |
| 590 | """ |
| 591 | _dollar_pattern_ignore_single_quote = re.compile(r"(.*?)\$(\$?[\w\.]+)(?=([^']*'[^']*')*[^']*$)") |
| 592 | def parse(self, fmt_string): |
| 593 | for literal_txt, field_name, format_spec, conversion \ |
| 594 | in Formatter.parse(self, fmt_string): |
| 595 | |
| 596 | # Find $foo patterns in the literal text. |
| 597 | continue_from = 0 |
| 598 | txt = "" |
| 599 | for m in self._dollar_pattern_ignore_single_quote.finditer(literal_txt): |
| 600 | new_txt, new_field = m.group(1,2) |
| 601 | # $$foo --> $foo |
| 602 | if new_field.startswith("$"): |
| 603 | txt += new_txt + new_field |
| 604 | else: |
| 605 | yield (txt + new_txt, new_field, "", None) |
| 606 | txt = "" |
| 607 | continue_from = m.end() |
| 608 | |
| 609 | # Re-yield the {foo} style pattern |
| 610 | yield (txt + literal_txt[continue_from:], field_name, format_spec, conversion) |
| 611 | |
| 612 | #----------------------------------------------------------------------------- |
| 613 | # Utils to columnize a list of string |