Visit named imports.
(self, node: nodes.FromImport, frame: Frame)
| 1124 | self.writeline(f"context.exported_vars.discard({node.target!r})") |
| 1125 | |
| 1126 | def visit_FromImport(self, node: nodes.FromImport, frame: Frame) -> None: |
| 1127 | """Visit named imports.""" |
| 1128 | self.newline(node) |
| 1129 | self.write("included_template = ") |
| 1130 | self._import_common(node, frame) |
| 1131 | var_names = [] |
| 1132 | discarded_names = [] |
| 1133 | for name in node.names: |
| 1134 | if isinstance(name, tuple): |
| 1135 | name, alias = name |
| 1136 | else: |
| 1137 | alias = name |
| 1138 | self.writeline( |
| 1139 | f"{frame.symbols.ref(alias)} =" |
| 1140 | f" getattr(included_template, {name!r}, missing)" |
| 1141 | ) |
| 1142 | self.writeline(f"if {frame.symbols.ref(alias)} is missing:") |
| 1143 | self.indent() |
| 1144 | # The position will contain the template name, and will be formatted |
| 1145 | # into a string that will be compiled into an f-string. Curly braces |
| 1146 | # in the name must be replaced with escapes so that they will not be |
| 1147 | # executed as part of the f-string. |
| 1148 | position = self.position(node).replace("{", "{{").replace("}", "}}") |
| 1149 | message = ( |
| 1150 | "the template {included_template.__name__!r}" |
| 1151 | f" (imported on {position})" |
| 1152 | f" does not export the requested name {name!r}" |
| 1153 | ) |
| 1154 | self.writeline( |
| 1155 | f"{frame.symbols.ref(alias)} = undefined(f{message!r}, name={name!r})" |
| 1156 | ) |
| 1157 | self.outdent() |
| 1158 | if frame.toplevel: |
| 1159 | var_names.append(alias) |
| 1160 | if not alias.startswith("_"): |
| 1161 | discarded_names.append(alias) |
| 1162 | |
| 1163 | if var_names: |
| 1164 | if len(var_names) == 1: |
| 1165 | name = var_names[0] |
| 1166 | self.writeline(f"context.vars[{name!r}] = {frame.symbols.ref(name)}") |
| 1167 | else: |
| 1168 | names_kv = ", ".join( |
| 1169 | f"{name!r}: {frame.symbols.ref(name)}" for name in var_names |
| 1170 | ) |
| 1171 | self.writeline(f"context.vars.update({{{names_kv}}})") |
| 1172 | if discarded_names: |
| 1173 | if len(discarded_names) == 1: |
| 1174 | self.writeline(f"context.exported_vars.discard({discarded_names[0]!r})") |
| 1175 | else: |
| 1176 | names_str = ", ".join(map(repr, discarded_names)) |
| 1177 | self.writeline( |
| 1178 | f"context.exported_vars.difference_update(({names_str}))" |
| 1179 | ) |
| 1180 | |
| 1181 | def visit_For(self, node: nodes.For, frame: Frame) -> None: |
| 1182 | loop_frame = frame.inner() |