(self, node: nodes.Assign, frame: Frame)
| 1580 | self.outdent() |
| 1581 | |
| 1582 | def visit_Assign(self, node: nodes.Assign, frame: Frame) -> None: |
| 1583 | self.push_assign_tracking() |
| 1584 | |
| 1585 | # ``a.b`` is allowed for assignment, and is parsed as an NSRef. However, |
| 1586 | # it is only valid if it references a Namespace object. Emit a check for |
| 1587 | # that for each ref here, before assignment code is emitted. This can't |
| 1588 | # be done in visit_NSRef as the ref could be in the middle of a tuple. |
| 1589 | seen_refs: t.Set[str] = set() |
| 1590 | |
| 1591 | for nsref in node.find_all(nodes.NSRef): |
| 1592 | if nsref.name in seen_refs: |
| 1593 | # Only emit the check for each reference once, in case the same |
| 1594 | # ref is used multiple times in a tuple, `ns.a, ns.b = c, d`. |
| 1595 | continue |
| 1596 | |
| 1597 | seen_refs.add(nsref.name) |
| 1598 | ref = frame.symbols.ref(nsref.name) |
| 1599 | self.writeline(f"if not isinstance({ref}, Namespace):") |
| 1600 | self.indent() |
| 1601 | self.writeline( |
| 1602 | "raise TemplateRuntimeError" |
| 1603 | '("cannot assign attribute on non-namespace object")' |
| 1604 | ) |
| 1605 | self.outdent() |
| 1606 | |
| 1607 | self.newline(node) |
| 1608 | self.visit(node.target, frame) |
| 1609 | self.write(" = ") |
| 1610 | self.visit(node.node, frame) |
| 1611 | self.pop_assign_tracking(frame) |
| 1612 | |
| 1613 | def visit_AssignBlock(self, node: nodes.AssignBlock, frame: Frame) -> None: |
| 1614 | self.push_assign_tracking() |
nothing calls this directly
no test coverage detected