web/lib/django/template/debug.py
author ymh <ymh.work@gmail.com>
Thu, 05 Aug 2010 17:28:09 +0200
changeset 50 012451a812f1
parent 38 77b6da96e6f1
permissions -rw-r--r--
Merge with a2711e44ba5de8b1675d7e0ee6aaa4a6c56a9b46
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
38
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     1
from django.template import Lexer, Parser, tag_re, NodeList, VariableNode, TemplateSyntaxError
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     2
from django.utils.encoding import force_unicode
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     3
from django.utils.html import escape
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     4
from django.utils.safestring import SafeData, EscapeData
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     5
from django.utils.formats import localize
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     6
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     7
class DebugLexer(Lexer):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     8
    def __init__(self, template_string, origin):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     9
        super(DebugLexer, self).__init__(template_string, origin)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    10
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    11
    def tokenize(self):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    12
        "Return a list of tokens from a given template_string"
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    13
        result, upto = [], 0
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    14
        for match in tag_re.finditer(self.template_string):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    15
            start, end = match.span()
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    16
            if start > upto:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    17
                result.append(self.create_token(self.template_string[upto:start], (upto, start), False))
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    18
                upto = start
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    19
            result.append(self.create_token(self.template_string[start:end], (start, end), True))
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    20
            upto = end
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    21
        last_bit = self.template_string[upto:]
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    22
        if last_bit:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    23
            result.append(self.create_token(last_bit, (upto, upto + len(last_bit)), False))
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    24
        return result
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    25
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    26
    def create_token(self, token_string, source, in_tag):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    27
        token = super(DebugLexer, self).create_token(token_string, in_tag)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    28
        token.source = self.origin, source
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    29
        return token
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    30
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    31
class DebugParser(Parser):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    32
    def __init__(self, lexer):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    33
        super(DebugParser, self).__init__(lexer)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    34
        self.command_stack = []
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    35
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    36
    def enter_command(self, command, token):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    37
        self.command_stack.append( (command, token.source) )
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    38
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    39
    def exit_command(self):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    40
        self.command_stack.pop()
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    41
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    42
    def error(self, token, msg):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    43
        return self.source_error(token.source, msg)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    44
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    45
    def source_error(self, source,msg):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    46
        e = TemplateSyntaxError(msg)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    47
        e.source = source
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    48
        return e
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    49
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    50
    def create_nodelist(self):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    51
        return DebugNodeList()
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    52
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    53
    def create_variable_node(self, contents):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    54
        return DebugVariableNode(contents)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    55
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    56
    def extend_nodelist(self, nodelist, node, token):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    57
        node.source = token.source
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    58
        super(DebugParser, self).extend_nodelist(nodelist, node, token)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    59
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    60
    def unclosed_block_tag(self, parse_until):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    61
        command, source = self.command_stack.pop()
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    62
        msg = "Unclosed tag '%s'. Looking for one of: %s " % (command, ', '.join(parse_until))
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    63
        raise self.source_error(source, msg)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    64
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    65
    def compile_function_error(self, token, e):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    66
        if not hasattr(e, 'source'):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    67
            e.source = token.source
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    68
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    69
class DebugNodeList(NodeList):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    70
    def render_node(self, node, context):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    71
        try:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    72
            result = node.render(context)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    73
        except TemplateSyntaxError, e:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    74
            if not hasattr(e, 'source'):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    75
                e.source = node.source
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    76
            raise
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    77
        except Exception, e:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    78
            from sys import exc_info
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    79
            wrapped = TemplateSyntaxError(u'Caught %s while rendering: %s' %
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    80
                (e.__class__.__name__, force_unicode(e, errors='replace')))
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    81
            wrapped.source = node.source
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    82
            wrapped.exc_info = exc_info()
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    83
            raise wrapped, None, wrapped.exc_info[2]
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    84
        return result
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    85
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    86
class DebugVariableNode(VariableNode):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    87
    def render(self, context):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    88
        try:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    89
            output = self.filter_expression.resolve(context)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    90
            output = localize(output)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    91
            output = force_unicode(output)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    92
        except TemplateSyntaxError, e:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    93
            if not hasattr(e, 'source'):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    94
                e.source = self.source
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    95
            raise
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    96
        except UnicodeDecodeError:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    97
            return ''
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    98
        if (context.autoescape and not isinstance(output, SafeData)) or isinstance(output, EscapeData):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    99
            return escape(output)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   100
        else:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   101
            return output