Calls the extender.
(self, node: nodes.Extends, frame: Frame)
| 985 | self.outdent(level) |
| 986 | |
| 987 | def visit_Extends(self, node: nodes.Extends, frame: Frame) -> None: |
| 988 | """Calls the extender.""" |
| 989 | if not frame.toplevel: |
| 990 | self.fail("cannot use extend from a non top-level scope", node.lineno) |
| 991 | |
| 992 | # if the number of extends statements in general is zero so |
| 993 | # far, we don't have to add a check if something extended |
| 994 | # the template before this one. |
| 995 | if self.extends_so_far > 0: |
| 996 | |
| 997 | # if we have a known extends we just add a template runtime |
| 998 | # error into the generated code. We could catch that at compile |
| 999 | # time too, but i welcome it not to confuse users by throwing the |
| 1000 | # same error at different times just "because we can". |
| 1001 | if not self.has_known_extends: |
| 1002 | self.writeline("if parent_template is not None:") |
| 1003 | self.indent() |
| 1004 | self.writeline('raise TemplateRuntimeError("extended multiple times")') |
| 1005 | |
| 1006 | # if we have a known extends already we don't need that code here |
| 1007 | # as we know that the template execution will end here. |
| 1008 | if self.has_known_extends: |
| 1009 | raise CompilerExit() |
| 1010 | else: |
| 1011 | self.outdent() |
| 1012 | |
| 1013 | self.writeline("parent_template = environment.get_template(", node) |
| 1014 | self.visit(node.template, frame) |
| 1015 | self.write(f", {self.name!r})") |
| 1016 | self.writeline("for name, parent_block in parent_template.blocks.items():") |
| 1017 | self.indent() |
| 1018 | self.writeline("context.blocks.setdefault(name, []).append(parent_block)") |
| 1019 | self.outdent() |
| 1020 | |
| 1021 | # if this extends statement was in the root level we can take |
| 1022 | # advantage of that information and simplify the generated code |
| 1023 | # in the top level from this point onwards |
| 1024 | if frame.rootlevel: |
| 1025 | self.has_known_extends = True |
| 1026 | |
| 1027 | # and now we have one more |
| 1028 | self.extends_so_far += 1 |
| 1029 | |
| 1030 | def visit_Include(self, node: nodes.Include, frame: Frame) -> None: |
| 1031 | """Handles includes.""" |