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