Based on the runtime locals, get the context that would be available at that point in the template.
(real_locals: t.Mapping[str, t.Any])
| 148 | |
| 149 | |
| 150 | def get_template_locals(real_locals: t.Mapping[str, t.Any]) -> t.Dict[str, t.Any]: |
| 151 | """Based on the runtime locals, get the context that would be |
| 152 | available at that point in the template. |
| 153 | """ |
| 154 | # Start with the current template context. |
| 155 | ctx: t.Optional[Context] = real_locals.get("context") |
| 156 | |
| 157 | if ctx is not None: |
| 158 | data: t.Dict[str, t.Any] = ctx.get_all().copy() |
| 159 | else: |
| 160 | data = {} |
| 161 | |
| 162 | # Might be in a derived context that only sets local variables |
| 163 | # rather than pushing a context. Local variables follow the scheme |
| 164 | # l_depth_name. Find the highest-depth local that has a value for |
| 165 | # each name. |
| 166 | local_overrides: t.Dict[str, t.Tuple[int, t.Any]] = {} |
| 167 | |
| 168 | for name, value in real_locals.items(): |
| 169 | if not name.startswith("l_") or value is missing: |
| 170 | # Not a template variable, or no longer relevant. |
| 171 | continue |
| 172 | |
| 173 | try: |
| 174 | _, depth_str, name = name.split("_", 2) |
| 175 | depth = int(depth_str) |
| 176 | except ValueError: |
| 177 | continue |
| 178 | |
| 179 | cur_depth = local_overrides.get(name, (-1,))[0] |
| 180 | |
| 181 | if cur_depth < depth: |
| 182 | local_overrides[name] = (depth, value) |
| 183 | |
| 184 | # Modify the context with any derived context. |
| 185 | for name, (_, value) in local_overrides.items(): |
| 186 | if value is missing: |
| 187 | data.pop(name, None) |
| 188 | else: |
| 189 | data[name] = value |
| 190 | |
| 191 | return data |