Django

Code

Changeset 947

Show
Ignore:
Timestamp:
10/18/05 19:19:47 (3 years ago)
Author:
rjwittams
Message:

Added TemplateDebugMiddleware?. This intercepts TemplateSyntaxErrors? that have been annotated with origin information and highlights where the problems are.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/branches/new-admin/django/core/handlers/base.py

    r881 r947  
    7575                    if response: 
    7676                        return response 
    77                 raise e 
     77                raise 
    7878 
    7979            # Complain if the view returned None (a common error). 
  • django/branches/new-admin/django/core/template/__init__.py

    r906 r947  
    108108    pass 
    109109 
     110class Origin(object): 
     111    def __init__(self, name): 
     112        self.name = name 
     113         
     114    def reload(self): 
     115        raise NotImplementedException 
     116 
     117    def __str__(self): 
     118        return self.name 
     119 
     120class StringOrigin(Origin): 
     121    def __init__(self, source): 
     122        super(StringOrigin, self).__init__(UNKNOWN_SOURCE) 
     123        self.source = source 
     124     
     125    def reload(self): 
     126        return (self.source, self.name) 
     127 
    110128class Template: 
    111     def __init__(self, template_string, filename=UNKNOWN_SOURCE): 
     129    def __init__(self, template_string, origin=None): 
    112130        "Compilation stage" 
    113         self.nodelist = compile_string(template_string, filename) 
     131        if origin == None: 
     132            origin = StringOrigin(template_string) 
     133        self.nodelist = compile_string(template_string, origin) 
    114134        
    115135    def __iter__(self): 
     
    121141        "Display stage -- can be called many times" 
    122142        return self.nodelist.render(context) 
    123  
    124 def compile_string(template_string, filename): 
     143         
     144 
     145def compile_string(template_string, origin): 
    125146    "Compiles template_string into NodeList ready for rendering" 
    126147    if DEBUG: 
     
    131152        parser_factory = Parser 
    132153         
    133     lexer = lexer_factory(template_string, filename
     154    lexer = lexer_factory(template_string, origin
    134155    parser = parser_factory(lexer.tokenize()) 
    135156    return parser.parse() 
     
    199220 
    200221class Lexer(object): 
    201     def __init__(self, template_string, filename): 
     222    def __init__(self, template_string, origin): 
    202223        self.template_string = template_string 
    203         self.filename = filename 
     224        self.origin = origin 
    204225     
    205226    def tokenize(self): 
     
    219240 
    220241class DebugLexer(Lexer): 
    221     def __init__(self, template_string, filename): 
    222         super(DebugLexer,self).__init__(template_string, filename
     242    def __init__(self, template_string, origin): 
     243        super(DebugLexer,self).__init__(template_string, origin
    223244 
    224245    def find_linebreaks(self, template_string): 
     
    234255        for match in tag_re.finditer(self.template_string): 
    235256            while next_linebreak <= upto: 
    236                 line, next_linebreak = lines.next()     
     257                line, next_linebreak = lines.next() 
    237258            start, end = match.span() 
    238259            if start > upto:        
     
    240261                upto = start 
    241262                while next_linebreak <= upto: 
    242                     line, next_linebreak = lines.next()               
     263                    line, next_linebreak = lines.next() 
    243264            token_tups.append( (self.template_string[start:end], line) ) 
    244265            upto = end 
     
    246267        if last_bit: 
    247268           token_tups.append( (last_bit, line) ) 
    248         return [ self.create_token(tok, (self.filename, line)) for tok, line in token_tups] 
     269        return [ self.create_token(tok, (self.origin, line)) for tok, line in token_tups] 
    249270 
    250271    def create_token(self, token_string, source): 
     
    257278        self.tokens = tokens 
    258279         
    259  
    260280    def parse(self, parse_until=[]): 
    261         nodelist = NodeList() 
     281        nodelist = self.create_nodelist() 
    262282        while self.tokens: 
    263283            token = self.next_token() 
     
    284304                except KeyError: 
    285305                    self.invalid_block_tag(token, command) 
     306                 
     307                try: 
     308                    compiled_result = compile_func(self, token) 
     309                except TemplateSyntaxError, e: 
     310                    if not self.compile_function_error(token, e): 
     311                       raise 
    286312                     
    287                 self.extend_nodelist(nodelist, compile_func(self, token), token) 
     313                self.extend_nodelist(nodelist, compiled_result, token) 
    288314                self.exit_command(); 
    289315                 
     
    293319        return nodelist 
    294320 
     321    def create_nodelist(self): 
     322        return NodeList() 
     323     
    295324    def extend_nodelist(self, nodelist, node, token): 
    296325        nodelist.append(node) 
     
    313342    def unclosed_block_tag(self, token, parse_until): 
    314343        raise TemplateSyntaxError, "Unclosed tags: %s " %  ', '.join(parse_until) 
     344 
     345    def compile_function_error(self, token, e): 
     346        pass 
    315347         
    316348    def next_token(self): 
     
    335367        self.command_stack.pop() 
    336368 
     369    def error(self, source, msg): 
     370        e = TemplateSyntaxError(msg) 
     371        e.source = source 
     372        return e 
     373 
    337374    def format_source(self, source): 
    338375        return "at %s, line %d" % source 
     376 
     377    def create_nodelist(self): 
     378        return DebugNodeList() 
    339379 
    340380    def extend_nodelist(self, nodelist, node, token): 
     
    343383 
    344384    def empty_variable(self, token): 
    345         raise TemplateSyntaxError, "Empty variable tag %s" % self.format_source(token.source
     385        raise self.error( token.source, "Empty variable tag %s" % self.format_source(token.source)
    346386     
    347387    def empty_block_tag(self, token): 
    348         raise TemplateSyntaxError, "Empty block tag %s" % self.format_source(token.source
     388        raise self.error( token.source, "Empty block tag %s" % self.format_source(token.source)
    349389     
    350390    def invalid_block_tag(self, token, command): 
    351         raise TemplateSyntaxError, "Invalid block tag: '%s' %s" % (command, self.format_source(token.source)) 
     391        raise self.error( token.source, "Invalid block tag: '%s' %s" % (command, self.format_source(token.source))) 
    352392     
    353393    def unclosed_block_tag(self, token, parse_until): 
    354         (command, (file,line)) = self.command_stack.pop() 
     394        (command, (origin,line)) = self.command_stack.pop() 
    355395        msg = "Unclosed tag '%s' starting at %s, line %d. Looking for one of: %s " % \ 
    356               (command, file, line, ', '.join(parse_until) )  
    357         raise TemplateSyntaxError, msg 
     396              (command, origin, line, ', '.join(parse_until) )  
     397        raise self.error( token.source, msg) 
     398 
     399    def compile_function_error(self, token, e): 
     400        if not hasattr(e, 'source'): 
     401            e.source = token.source 
    358402 
    359403class FilterParser: 
     
    563607        for node in self: 
    564608            if isinstance(node, Node): 
    565                 bits.append(node.render(context)) 
     609                try: 
     610                   result = node.render(context) 
     611                except TemplateSyntaxError, e: 
     612                    if not self.handle_render_error(node, e): 
     613                       raise 
     614                bits.append(result) 
    566615            else: 
    567616                bits.append(node) 
     
    574623            nodes.extend(node.get_nodes_by_type(nodetype)) 
    575624        return nodes 
     625 
     626    def handle_render_error(self, node, exception): 
     627        pass 
     628 
     629class DebugNodeList(NodeList): 
     630    def handle_render_error(self, node, exception): 
     631        if not hasattr(exception, 'source'): 
     632            exception.source = node.source 
     633 
    576634 
    577635class TextNode(Node): 
  • django/branches/new-admin/django/core/template/loader.py

    r906 r947  
    2121 
    2222from django.core.exceptions import ImproperlyConfigured 
    23 from django.core.template import Template, Context, Node, TemplateDoesNotExist, TemplateSyntaxError, resolve_variable_with_filters, register_tag, UNKNOWN_SOURCE 
     23from django.core.template import Origin, StringOrigin, Template, Context, Node, TemplateDoesNotExist, TemplateSyntaxError, resolve_variable_with_filters, register_tag 
    2424from django.conf.settings import TEMPLATE_LOADERS 
    2525 
     
    4242        template_source_loaders.append(func) 
    4343 
     44 
     45 
     46 
     47class LoaderOrigin(Origin): 
     48    def __init__(self, name, loader): 
     49        super(LoaderOrigin, self).__init__(name) 
     50        self.loader = loader 
     51     
     52    def reload(self): 
     53        if self.loader: 
     54            return self.loader() 
     55        else: 
     56            raise NotImplementedException 
     57 
     58 
    4459def find_template_source(name, dirs=None): 
    4560    for loader in template_source_loaders: 
    4661        try: 
    47             return loader(name, dirs) 
     62            source, display_name  = loader(name, dirs)  
     63             
     64            def reload(): 
     65                return loader(name, dirs)[0] 
     66             
     67            return (source, LoaderOrigin(display_name, reload)) 
    4868        except TemplateDoesNotExist: 
    4969            pass 
     
    6383    return get_template_from_string(*find_template_source(template_name)) 
    6484 
    65 def get_template_from_string(source, filename=UNKNOWN_SOURCE): 
     85def get_template_from_string(source, origin=None ): 
    6686    """ 
    6787    Returns a compiled Template object for the given template code, 
    6888    handling template inheritance recursively. 
    6989    """ 
    70     return Template(source, filename) 
     90    if origin==None: 
     91        #Could do some crazy stack frame stuff to record where this string came from.  
     92        origin = StringOrigin(source) 
     93    return Template(source, origin) 
    7194 
    7295def render_to_string(template_name, dictionary=None, context_instance=None):