The template context holds the variables of a template. It stores the values passed to the template and also the names the template exports. Creating instances is neither supported nor useful as it's created automatically at various stages of the template evaluation and should not b
| 131 | |
| 132 | |
| 133 | class Context(with_metaclass(ContextMeta)): |
| 134 | """The template context holds the variables of a template. It stores the |
| 135 | values passed to the template and also the names the template exports. |
| 136 | Creating instances is neither supported nor useful as it's created |
| 137 | automatically at various stages of the template evaluation and should not |
| 138 | be created by hand. |
| 139 | |
| 140 | The context is immutable. Modifications on :attr:`parent` **must not** |
| 141 | happen and modifications on :attr:`vars` are allowed from generated |
| 142 | template code only. Template filters and global functions marked as |
| 143 | :func:`contextfunction`\\s get the active context passed as first argument |
| 144 | and are allowed to access the context read-only. |
| 145 | |
| 146 | The template context supports read only dict operations (`get`, |
| 147 | `keys`, `values`, `items`, `iterkeys`, `itervalues`, `iteritems`, |
| 148 | `__getitem__`, `__contains__`). Additionally there is a :meth:`resolve` |
| 149 | method that doesn't fail with a `KeyError` but returns an |
| 150 | :class:`Undefined` object for missing variables. |
| 151 | """ |
| 152 | # XXX: we want to eventually make this be a deprecation warning and |
| 153 | # remove it. |
| 154 | _legacy_resolve_mode = False |
| 155 | _fast_resolve_mode = False |
| 156 | |
| 157 | def __init__(self, environment, parent, name, blocks): |
| 158 | self.parent = parent |
| 159 | self.vars = {} |
| 160 | self.environment = environment |
| 161 | self.eval_ctx = EvalContext(self.environment, name) |
| 162 | self.exported_vars = set() |
| 163 | self.name = name |
| 164 | |
| 165 | # create the initial mapping of blocks. Whenever template inheritance |
| 166 | # takes place the runtime will update this mapping with the new blocks |
| 167 | # from the template. |
| 168 | self.blocks = dict((k, [v]) for k, v in iteritems(blocks)) |
| 169 | |
| 170 | # In case we detect the fast resolve mode we can set up an alias |
| 171 | # here that bypasses the legacy code logic. |
| 172 | if self._fast_resolve_mode: |
| 173 | self.resolve_or_missing = MethodType(resolve_or_missing, self) |
| 174 | |
| 175 | def super(self, name, current): |
| 176 | """Render a parent block.""" |
| 177 | try: |
| 178 | blocks = self.blocks[name] |
| 179 | index = blocks.index(current) + 1 |
| 180 | blocks[index] |
| 181 | except LookupError: |
| 182 | return self.environment.undefined('there is no parent block ' |
| 183 | 'called %r.' % name, |
| 184 | name='super') |
| 185 | return BlockReference(name, self, blocks, index) |
| 186 | |
| 187 | def get(self, key, default=None): |
| 188 | """Returns an item from the template context, if it doesn't exist |
| 189 | `default` is returned. |
| 190 | """ |
nothing calls this directly
no test coverage detected
searching dependent graphs…