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