--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/django/template/context.py Wed Jun 02 18:57:35 2010 +0200
@@ -0,0 +1,149 @@
+from django.core.exceptions import ImproperlyConfigured
+from django.utils.importlib import import_module
+
+# Cache of actual callables.
+_standard_context_processors = None
+# We need the CSRF processor no matter what the user has in their settings,
+# because otherwise it is a security vulnerability, and we can't afford to leave
+# this to human error or failure to read migration instructions.
+_builtin_context_processors = ('django.core.context_processors.csrf',)
+
+class ContextPopException(Exception):
+ "pop() has been called more times than push()"
+ pass
+
+class BaseContext(object):
+ def __init__(self, dict_=None):
+ dict_ = dict_ or {}
+ self.dicts = [dict_]
+
+ def __repr__(self):
+ return repr(self.dicts)
+
+ def __iter__(self):
+ for d in reversed(self.dicts):
+ yield d
+
+ def push(self):
+ d = {}
+ self.dicts.append(d)
+ return d
+
+ def pop(self):
+ if len(self.dicts) == 1:
+ raise ContextPopException
+ return self.dicts.pop()
+
+ def __setitem__(self, key, value):
+ "Set a variable in the current context"
+ self.dicts[-1][key] = value
+
+ def __getitem__(self, key):
+ "Get a variable's value, starting at the current context and going upward"
+ for d in reversed(self.dicts):
+ if key in d:
+ return d[key]
+ raise KeyError(key)
+
+ def __delitem__(self, key):
+ "Delete a variable from the current context"
+ del self.dicts[-1][key]
+
+ def has_key(self, key):
+ for d in self.dicts:
+ if key in d:
+ return True
+ return False
+
+ def __contains__(self, key):
+ return self.has_key(key)
+
+ def get(self, key, otherwise=None):
+ for d in reversed(self.dicts):
+ if key in d:
+ return d[key]
+ return otherwise
+
+class Context(BaseContext):
+ "A stack container for variable context"
+ def __init__(self, dict_=None, autoescape=True, current_app=None):
+ self.autoescape = autoescape
+ self.current_app = current_app
+ self.render_context = RenderContext()
+ super(Context, self).__init__(dict_)
+
+ def update(self, other_dict):
+ "Like dict.update(). Pushes an entire dictionary's keys and values onto the context."
+ if not hasattr(other_dict, '__getitem__'):
+ raise TypeError('other_dict must be a mapping (dictionary-like) object.')
+ self.dicts.append(other_dict)
+ return other_dict
+
+class RenderContext(BaseContext):
+ """
+ A stack container for storing Template state.
+
+ RenderContext simplifies the implementation of template Nodes by providing a
+ safe place to store state between invocations of a node's `render` method.
+
+ The RenderContext also provides scoping rules that are more sensible for
+ 'template local' variables. The render context stack is pushed before each
+ template is rendered, creating a fresh scope with nothing in it. Name
+ resolution fails if a variable is not found at the top of the RequestContext
+ stack. Thus, variables are local to a specific template and don't affect the
+ rendering of other templates as they would if they were stored in the normal
+ template context.
+ """
+ def __iter__(self):
+ for d in self.dicts[-1]:
+ yield d
+
+ def has_key(self, key):
+ return key in self.dicts[-1]
+
+ def get(self, key, otherwise=None):
+ d = self.dicts[-1]
+ if key in d:
+ return d[key]
+ return otherwise
+
+# This is a function rather than module-level procedural code because we only
+# want it to execute if somebody uses RequestContext.
+def get_standard_processors():
+ from django.conf import settings
+ global _standard_context_processors
+ if _standard_context_processors is None:
+ processors = []
+ collect = []
+ collect.extend(_builtin_context_processors)
+ collect.extend(settings.TEMPLATE_CONTEXT_PROCESSORS)
+ for path in collect:
+ i = path.rfind('.')
+ module, attr = path[:i], path[i+1:]
+ try:
+ mod = import_module(module)
+ except ImportError, e:
+ raise ImproperlyConfigured('Error importing request processor module %s: "%s"' % (module, e))
+ try:
+ func = getattr(mod, attr)
+ except AttributeError:
+ raise ImproperlyConfigured('Module "%s" does not define a "%s" callable request processor' % (module, attr))
+ processors.append(func)
+ _standard_context_processors = tuple(processors)
+ return _standard_context_processors
+
+class RequestContext(Context):
+ """
+ This subclass of template.Context automatically populates itself using
+ the processors defined in TEMPLATE_CONTEXT_PROCESSORS.
+ Additional processors can be specified as a list of callables
+ using the "processors" keyword argument.
+ """
+ def __init__(self, request, dict=None, processors=None, current_app=None):
+ Context.__init__(self, dict, current_app=current_app)
+ if processors is None:
+ processors = ()
+ else:
+ processors = tuple(processors)
+ for processor in get_standard_processors() + processors:
+ self.update(processor(request))