blob: 1d9747a931416b742fdf1e573e51bff0652f602b [file] [log] [blame]
# -*- coding: utf-8 -*-
"""
jinja._native
~~~~~~~~~~~~~
This module implements the native base classes in case of not
having a jinja with the _speedups module compiled.
Note that if you change semantics here you have to edit the
_speedups.c file to in order to support those changes for jinja
setups with enabled speedup module.
:copyright: 2007 by Armin Ronacher.
:license: BSD, see LICENSE for more details.
"""
from jinja.datastructure import Deferred
from jinja.utils import deque
class BaseContext(object):
def __init__(self, undefined_singleton, globals, initial):
self._undefined_singleton = undefined_singleton
self.current = current = {}
self._stack = deque([current, initial, globals])
self.globals = globals
self.initial = initial
self._push = self._stack.appendleft
self._pop = self._stack.popleft
def stack(self):
return list(self._stack)[::-1]
stack = property(stack)
def pop(self):
"""Pop the last layer from the stack and return it."""
rv = self._pop()
self.current = self._stack[0]
return rv
def push(self, data=None):
"""
Push one layer to the stack and return it. Layer must be
a dict or omitted.
"""
data = data or {}
self._push(data)
self.current = self._stack[0]
return data
def __getitem__(self, name):
"""
Resolve one item. Restrict the access to internal variables
such as ``'::cycle1'``. Resolve deferreds.
"""
if not name.startswith('::'):
for d in self._stack:
if name in d:
rv = d[name]
if rv.__class__ is Deferred:
rv = rv(self, name)
# never touch the globals!
if d is self.globals:
self.initial[name] = rv
else:
d[name] = rv
return rv
return self._undefined_singleton
def __setitem__(self, name, value):
"""Set a variable in the outermost layer."""
self.current[name] = value
def __delitem__(self, name):
"""Delete a variable in the outermost layer."""
if name in self.current:
del self.current[name]
def __contains__(self, name):
""" Check if the context contains a given variable."""
for layer in self._stack:
if name in layer:
return True
return False