app/django/template/debug.py
changeset 54 03e267d67478
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/app/django/template/debug.py	Fri Jul 18 18:22:23 2008 +0000
@@ -0,0 +1,97 @@
+from django.template import Lexer, Parser, tag_re, NodeList, VariableNode, TemplateSyntaxError
+from django.utils.encoding import force_unicode
+from django.utils.html import escape
+from django.utils.safestring import SafeData, EscapeData
+
+class DebugLexer(Lexer):
+    def __init__(self, template_string, origin):
+        super(DebugLexer, self).__init__(template_string, origin)
+
+    def tokenize(self):
+        "Return a list of tokens from a given template_string"
+        result, upto = [], 0
+        for match in tag_re.finditer(self.template_string):
+            start, end = match.span()
+            if start > upto:
+                result.append(self.create_token(self.template_string[upto:start], (upto, start), False))
+                upto = start
+            result.append(self.create_token(self.template_string[start:end], (start, end), True))
+            upto = end
+        last_bit = self.template_string[upto:]
+        if last_bit:
+            result.append(self.create_token(last_bit, (upto, upto + len(last_bit)), False))
+        return result
+
+    def create_token(self, token_string, source, in_tag):
+        token = super(DebugLexer, self).create_token(token_string, in_tag)
+        token.source = self.origin, source
+        return token
+
+class DebugParser(Parser):
+    def __init__(self, lexer):
+        super(DebugParser, self).__init__(lexer)
+        self.command_stack = []
+
+    def enter_command(self, command, token):
+        self.command_stack.append( (command, token.source) )
+
+    def exit_command(self):
+        self.command_stack.pop()
+
+    def error(self, token, msg):
+        return self.source_error(token.source, msg)
+
+    def source_error(self, source,msg):
+        e = TemplateSyntaxError(msg)
+        e.source = source
+        return e
+
+    def create_nodelist(self):
+        return DebugNodeList()
+
+    def create_variable_node(self, contents):
+        return DebugVariableNode(contents)
+
+    def extend_nodelist(self, nodelist, node, token):
+        node.source = token.source
+        super(DebugParser, self).extend_nodelist(nodelist, node, token)
+
+    def unclosed_block_tag(self, parse_until):
+        command, source = self.command_stack.pop()
+        msg = "Unclosed tag '%s'. Looking for one of: %s " % (command, ', '.join(parse_until))
+        raise self.source_error(source, msg)
+
+    def compile_function_error(self, token, e):
+        if not hasattr(e, 'source'):
+            e.source = token.source
+
+class DebugNodeList(NodeList):
+    def render_node(self, node, context):
+        try:
+            result = node.render(context)
+        except TemplateSyntaxError, e:
+            if not hasattr(e, 'source'):
+                e.source = node.source
+            raise
+        except Exception, e:
+            from sys import exc_info
+            wrapped = TemplateSyntaxError(u'Caught an exception while rendering: %s' % force_unicode(e, errors='replace'))
+            wrapped.source = node.source
+            wrapped.exc_info = exc_info()
+            raise wrapped
+        return result
+
+class DebugVariableNode(VariableNode):
+    def render(self, context):
+        try:
+            output = force_unicode(self.filter_expression.resolve(context))
+        except TemplateSyntaxError, e:
+            if not hasattr(e, 'source'):
+                e.source = self.source
+            raise
+        except UnicodeDecodeError:
+            return ''
+        if (context.autoescape and not isinstance(output, SafeData)) or isinstance(output, EscapeData):
+            return escape(output)
+        else:
+            return output