| 721 | |
| 722 | |
| 723 | class _CodeWriter(object): |
| 724 | def __init__( |
| 725 | self, |
| 726 | file: TextIO, |
| 727 | named_blocks: Dict[str, _NamedBlock], |
| 728 | loader: Optional[BaseLoader], |
| 729 | current_template: Template, |
| 730 | ) -> None: |
| 731 | self.file = file |
| 732 | self.named_blocks = named_blocks |
| 733 | self.loader = loader |
| 734 | self.current_template = current_template |
| 735 | self.apply_counter = 0 |
| 736 | self.include_stack = [] # type: List[Tuple[Template, int]] |
| 737 | self._indent = 0 |
| 738 | |
| 739 | def indent_size(self) -> int: |
| 740 | return self._indent |
| 741 | |
| 742 | def indent(self) -> "ContextManager": |
| 743 | class Indenter(object): |
| 744 | def __enter__(_) -> "_CodeWriter": |
| 745 | self._indent += 1 |
| 746 | return self |
| 747 | |
| 748 | def __exit__(_, *args: Any) -> None: |
| 749 | assert self._indent > 0 |
| 750 | self._indent -= 1 |
| 751 | |
| 752 | return Indenter() |
| 753 | |
| 754 | def include(self, template: Template, line: int) -> "ContextManager": |
| 755 | self.include_stack.append((self.current_template, line)) |
| 756 | self.current_template = template |
| 757 | |
| 758 | class IncludeTemplate(object): |
| 759 | def __enter__(_) -> "_CodeWriter": |
| 760 | return self |
| 761 | |
| 762 | def __exit__(_, *args: Any) -> None: |
| 763 | self.current_template = self.include_stack.pop()[0] |
| 764 | |
| 765 | return IncludeTemplate() |
| 766 | |
| 767 | def write_line( |
| 768 | self, line: str, line_number: int, indent: Optional[int] = None |
| 769 | ) -> None: |
| 770 | if indent is None: |
| 771 | indent = self._indent |
| 772 | line_comment = " # %s:%d" % (self.current_template.name, line_number) |
| 773 | if self.include_stack: |
| 774 | ancestors = [ |
| 775 | "%s:%d" % (tmpl.name, lineno) for (tmpl, lineno) in self.include_stack |
| 776 | ] |
| 777 | line_comment += " (via %s)" % ", ".join(reversed(ancestors)) |
| 778 | print(" " * indent + line + line_comment, file=self.file) |
| 779 | |
| 780 | |