Ticket #16770: unwrap_templatesyntaxerror-2.diff
File unwrap_templatesyntaxerror-2.diff, 17.9 KB (added by , 13 years ago) |
---|
-
django/views/debug.py
141 141 else: 142 142 # Cleanse only the specified parameters. 143 143 for param in sensitive_post_parameters: 144 if param in cleansed:144 if cleansed.has_key(param): 145 145 cleansed[param] = CLEANSED_SUBSTITUTE 146 146 return cleansed 147 147 else: … … 223 223 'loader': loader_name, 224 224 'templates': template_list, 225 225 }) 226 if (settings.TEMPLATE_DEBUG and hasattr(self.exc_value, 'source') and 227 isinstance(self.exc_value, TemplateSyntaxError)): 226 if (settings.TEMPLATE_DEBUG and hasattr(self.exc_value, 'django_template_source')): 228 227 self.get_template_exception_info() 229 228 230 229 frames = self.get_traceback_frames() … … 268 267 return t.render(c) 269 268 270 269 def get_template_exception_info(self): 271 origin, (start, end) = self.exc_value. source270 origin, (start, end) = self.exc_value.django_template_source 272 271 template_source = origin.reload() 273 272 context_lines = 10 274 273 line = 0 … … 626 625 {% endif %} 627 626 {% if template_info %} 628 627 <div id="template"> 629 <h2> Template error</h2>628 <h2>Error occured during template rendering</h2> 630 629 <p>In template <code>{{ template_info.name }}</code>, error at line <strong>{{ template_info.line }}</strong></p> 631 630 <h3>{{ template_info.message }}</h3> 632 631 <table class="source{% if template_info.top %} cut-top{% endif %}{% ifnotequal template_info.bottom template_info.total %} cut-bottom{% endifnotequal %}"> -
django/template/debug.py
4 4 from django.utils.safestring import SafeData, EscapeData 5 5 from django.utils.formats import localize 6 6 7 7 8 class DebugLexer(Lexer): 8 9 def __init__(self, template_string, origin): 9 10 super(DebugLexer, self).__init__(template_string, origin) … … 42 43 def error(self, token, msg): 43 44 return self.source_error(token.source, msg) 44 45 45 def source_error(self, source, msg):46 def source_error(self, source, msg): 46 47 e = TemplateSyntaxError(msg) 47 e.source = source48 e.source_template_node = source #Identify the template node that was being rendered when the error occurred. 48 49 return e 49 50 50 51 def create_nodelist(self): … … 67 68 e.source = token.source 68 69 69 70 class DebugNodeList(NodeList): 71 ''' 72 A list of nodes that is instantiated when debug is True - this is the nerve center of exceptions that occur during template rendering. 73 ''' 70 74 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 75 try: 76 return node.render(context) 77 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 = getattr(e, 'template_node_source', node.source) 82 wrapped.exc_info = exc_info() 83 raise wrapped, None, wrapped.exc_info[2] 84 return result 78 if not hasattr(e, 'source_template_node'): #Have we already identified the node where the problem occured? 79 e.django_template_source = node.source #...if not, let's annotate the exception with that - the template will use this to show information about the template just before the traceback on the exception page. 80 raise e 81 85 82 86 83 class DebugVariableNode(VariableNode): 87 84 def render(self, context): -
tests/regressiontests/templates/tests.py
1 1 # -*- coding: utf-8 -*- 2 2 from django.conf import settings 3 from django.core.urlresolvers import NoReverseMatch 3 4 4 5 if __name__ == '__main__': 5 6 # When running this file in isolation, we need to set up the configuration … … 20 21 from django.template import loader 21 22 from django.template.loaders import app_directories, filesystem, cached 22 23 from django.test.utils import (get_warnings_state, restore_warnings_state, 23 setup_test_template_loader, restore_template_loaders )24 setup_test_template_loader, restore_template_loaders, override_settings) 24 25 from django.utils import unittest 25 26 from django.utils.formats import date_format 26 27 from django.utils.translation import activate, deactivate, ugettext as _ … … 309 310 r = None 310 311 try: 311 312 r = tmpl.render(template.Context({})) 312 except template.Template SyntaxError, e:313 except template.TemplateDoesNotExist, e: 313 314 settings.TEMPLATE_DEBUG = old_td 314 self.assertEqual(e.args[0], ' Caught TemplateDoesNotExist while rendering:missing.html')315 self.assertEqual(e.args[0], 'missing.html') 315 316 self.assertEqual(r, None, 'Template rendering unexpectedly succeeded, produced: ->%r<-' % r) 316 317 finally: 317 318 loader.template_source_loaders = old_loaders … … 336 337 r = None 337 338 try: 338 339 r = tmpl.render(template.Context({})) 339 except template.Template SyntaxError, e:340 self.assertEqual(e.args[0], ' Caught TemplateDoesNotExist while rendering:missing.html')340 except template.TemplateDoesNotExist, e: 341 self.assertEqual(e.args[0], 'missing.html') 341 342 self.assertEqual(r, None, 'Template rendering unexpectedly succeeded, produced: ->%r<-' % r) 342 343 343 344 # For the cached loader, repeat the test, to ensure the first attempt did not cache a … … 345 346 tmpl = loader.get_template(load_name) 346 347 try: 347 348 tmpl.render(template.Context({})) 348 except template.Template SyntaxError, e:349 self.assertEqual(e.args[0], ' Caught TemplateDoesNotExist while rendering:missing.html')349 except template.TemplateDoesNotExist, e: 350 self.assertEqual(e.args[0], 'missing.html') 350 351 self.assertEqual(r, None, 'Template rendering unexpectedly succeeded, produced: ->%r<-' % r) 351 352 finally: 352 353 loader.template_source_loaders = old_loaders … … 370 371 371 372 t = Template('{% url will_not_match %}') 372 373 c = Context() 373 try: 374 rendered = t.render(c) 375 except TemplateSyntaxError, e: 376 # Assert that we are getting the template syntax error and not the 377 # string encoding error. 378 self.assertEqual(e.args[0], "Caught NoReverseMatch while rendering: Reverse for 'will_not_match' with arguments '()' and keyword arguments '{}' not found.") 374 self.assertRaises(NoReverseMatch, t.render, c) 379 375 380 376 settings.SETTINGS_MODULE = old_settings_module 381 377 settings.TEMPLATE_DEBUG = old_template_debug 378 379 @override_settings(DEBUG=True, TEMPLATE_DEBUG = True) 380 def test_no_wrapped_exception(self): 381 """ 382 Previously exceptions were wrapped by TemplateSyntaxError. See #16770 383 """ 384 from django.template import Template, TemplateSyntaxError 385 c = Context({'coconuts': lambda: 42 / 0}) 386 t = Template("{{coconuts}}") 387 self.assertRaises(ZeroDivisionError, t.render, c) #Dividing by zero ought to cause ZeroDivisionError; we'll instead get TemplateSyntaxError here iff it's been wrapped. 388 389 #Let's also confirm that the exception has the attribute we need to show the template information on the exception page. 390 try: 391 t.render(c) 392 except ZeroDivisionError, e: 393 self.assertTrue(hasattr(e, 'django_template_source')) 382 394 383 395 def test_invalid_block_suggestion(self): 384 396 # See #7876 … … 666 678 667 679 # In methods that raise an exception without a 668 680 # "silent_variable_attribute" set to True, the exception propagates 669 'filter-syntax14': (r'1{{ var.method4 }}2', {"var": SomeClass()}, (SomeOtherException, SomeOtherException , template.TemplateSyntaxError)),681 'filter-syntax14': (r'1{{ var.method4 }}2', {"var": SomeClass()}, (SomeOtherException, SomeOtherException)), 670 682 671 683 # Escaped backslash in argument 672 684 'filter-syntax15': (r'{{ var|default_if_none:"foo\bar" }}', {"var": None}, r'foo\bar'), … … 695 707 # In attribute and dict lookups that raise an unexpected exception 696 708 # without a "silent_variable_attribute" set to True, the exception 697 709 # propagates 698 'filter-syntax23': (r'1{{ var.noisy_fail_key }}2', {"var": SomeClass()}, (SomeOtherException, SomeOtherException , template.TemplateSyntaxError)),699 'filter-syntax24': (r'1{{ var.noisy_fail_attribute }}2', {"var": SomeClass()}, (SomeOtherException, SomeOtherException , template.TemplateSyntaxError)),710 'filter-syntax23': (r'1{{ var.noisy_fail_key }}2', {"var": SomeClass()}, (SomeOtherException, SomeOtherException)), 711 'filter-syntax24': (r'1{{ var.noisy_fail_attribute }}2', {"var": SomeClass()}, (SomeOtherException, SomeOtherException)), 700 712 701 713 ### COMMENT SYNTAX ######################################################## 702 714 'comment-syntax01': ("{# this is hidden #}hello", {}, "hello"), … … 753 765 ### EXCEPTIONS ############################################################ 754 766 755 767 # Raise exception for invalid template name 756 'exception01': ("{% extends 'nonexistent' %}", {}, (template.TemplateDoesNotExist, template.TemplateDoesNotExist , template.TemplateSyntaxError)),768 'exception01': ("{% extends 'nonexistent' %}", {}, (template.TemplateDoesNotExist, template.TemplateDoesNotExist)), 757 769 758 770 # Raise exception for invalid template name (in variable) 759 771 'exception02': ("{% extends nonexistent %}", {}, (template.TemplateSyntaxError, template.TemplateDoesNotExist)), … … 1050 1062 'include-fail2': ('{% load broken_tag %}', {}, template.TemplateSyntaxError), 1051 1063 'include-error07': ('{% include "include-fail1" %}', {}, ('', '', RuntimeError)), 1052 1064 'include-error08': ('{% include "include-fail2" %}', {}, ('', '', template.TemplateSyntaxError)), 1053 'include-error09': ('{% include failed_include %}', {'failed_include': 'include-fail1'}, ('', '', template.TemplateSyntaxError)),1065 'include-error09': ('{% include failed_include %}', {'failed_include': 'include-fail1'}, ('', '', RuntimeError)), 1054 1066 'include-error10': ('{% include failed_include %}', {'failed_include': 'include-fail2'}, ('', '', template.TemplateSyntaxError)), 1055 1067 1056 1068 … … 1481 1493 1482 1494 # Failures 1483 1495 'old-url-fail01': ('{% url %}', {}, template.TemplateSyntaxError), 1484 'old-url-fail02': ('{% url no_such_view %}', {}, (urlresolvers.NoReverseMatch, urlresolvers.NoReverseMatch , template.TemplateSyntaxError)),1485 'old-url-fail03': ('{% url regressiontests.templates.views.client %}', {}, (urlresolvers.NoReverseMatch, urlresolvers.NoReverseMatch , template.TemplateSyntaxError)),1496 'old-url-fail02': ('{% url no_such_view %}', {}, (urlresolvers.NoReverseMatch, urlresolvers.NoReverseMatch)), 1497 'old-url-fail03': ('{% url regressiontests.templates.views.client %}', {}, (urlresolvers.NoReverseMatch, urlresolvers.NoReverseMatch)), 1486 1498 'old-url-fail04': ('{% url view id, %}', {}, template.TemplateSyntaxError), 1487 1499 'old-url-fail05': ('{% url view id= %}', {}, template.TemplateSyntaxError), 1488 1500 'old-url-fail06': ('{% url view a.id=id %}', {}, template.TemplateSyntaxError), … … 1522 1534 1523 1535 # Failures 1524 1536 'url-fail01': ('{% load url from future %}{% url %}', {}, template.TemplateSyntaxError), 1525 'url-fail02': ('{% load url from future %}{% url "no_such_view" %}', {}, (urlresolvers.NoReverseMatch, urlresolvers.NoReverseMatch , template.TemplateSyntaxError)),1526 'url-fail03': ('{% load url from future %}{% url "regressiontests.templates.views.client" %}', {}, (urlresolvers.NoReverseMatch, urlresolvers.NoReverseMatch , template.TemplateSyntaxError)),1537 'url-fail02': ('{% load url from future %}{% url "no_such_view" %}', {}, (urlresolvers.NoReverseMatch, urlresolvers.NoReverseMatch)), 1538 'url-fail03': ('{% load url from future %}{% url "regressiontests.templates.views.client" %}', {}, (urlresolvers.NoReverseMatch, urlresolvers.NoReverseMatch)), 1527 1539 'url-fail04': ('{% load url from future %}{% url "view" id, %}', {}, template.TemplateSyntaxError), 1528 1540 'url-fail05': ('{% load url from future %}{% url "view" id= %}', {}, template.TemplateSyntaxError), 1529 1541 'url-fail06': ('{% load url from future %}{% url "view" a.id=id %}', {}, template.TemplateSyntaxError), … … 1531 1543 'url-fail08': ('{% load url from future %}{% url "view" id="unterminatedstring %}', {}, template.TemplateSyntaxError), 1532 1544 'url-fail09': ('{% load url from future %}{% url "view" id=", %}', {}, template.TemplateSyntaxError), 1533 1545 1534 'url-fail11': ('{% load url from future %}{% url named_url %}', {}, (urlresolvers.NoReverseMatch, urlresolvers.NoReverseMatch , template.TemplateSyntaxError)),1535 'url-fail12': ('{% load url from future %}{% url named_url %}', {'named_url': 'no_such_view'}, (urlresolvers.NoReverseMatch, urlresolvers.NoReverseMatch , template.TemplateSyntaxError)),1536 'url-fail13': ('{% load url from future %}{% url named_url %}', {'named_url': 'regressiontests.templates.views.client'}, (urlresolvers.NoReverseMatch, urlresolvers.NoReverseMatch , template.TemplateSyntaxError)),1546 'url-fail11': ('{% load url from future %}{% url named_url %}', {}, (urlresolvers.NoReverseMatch, urlresolvers.NoReverseMatch)), 1547 'url-fail12': ('{% load url from future %}{% url named_url %}', {'named_url': 'no_such_view'}, (urlresolvers.NoReverseMatch, urlresolvers.NoReverseMatch)), 1548 'url-fail13': ('{% load url from future %}{% url named_url %}', {'named_url': 'regressiontests.templates.views.client'}, (urlresolvers.NoReverseMatch, urlresolvers.NoReverseMatch)), 1537 1549 'url-fail14': ('{% load url from future %}{% url named_url id, %}', {'named_url': 'view'}, template.TemplateSyntaxError), 1538 1550 'url-fail15': ('{% load url from future %}{% url named_url id= %}', {'named_url': 'view'}, template.TemplateSyntaxError), 1539 1551 'url-fail16': ('{% load url from future %}{% url named_url a.id=id %}', {'named_url': 'view'}, template.TemplateSyntaxError), -
tests/regressiontests/templates/nodelist.py
2 2 from django.template import VariableNode, Context, TemplateSyntaxError 3 3 from django.template.loader import get_template_from_string 4 4 from django.utils.unittest import TestCase 5 from django.test.utils import override_settings 5 6 6 7 class NodelistTest(TestCase): 7 8 … … 35 36 Checks whether index of error is calculated correctly in 36 37 template debugger in for loops. Refs ticket #5831 37 38 """ 38 def setUp(self): 39 self.old_template_debug = settings.TEMPLATE_DEBUG 40 settings.TEMPLATE_DEBUG = True 41 42 def tearDown(self): 43 settings.TEMPLATE_DEBUG = self.old_template_debug 44 39 @override_settings(DEBUG=True, TEMPLATE_DEBUG = True) 45 40 def test_correct_exception_index(self): 46 tests = [ 47 ('{% load bad_tag %}{% for i in range %}{% badsimpletag %}{% endfor %}', (38, 56)), 48 ('{% load bad_tag %}{% for i in range %}{% for j in range %}{% badsimpletag %}{% endfor %}{% endfor %}', (58, 76)), 49 ('{% load bad_tag %}{% for i in range %}{% badsimpletag %}{% for j in range %}Hello{% endfor %}{% endfor %}', (38, 56)), 50 ('{% load bad_tag %}{% for i in range %}{% for j in five %}{% badsimpletag %}{% endfor %}{% endfor %}', (38, 57)), 41 ''' 42 Looks at an exception page and confirms that the information about the source of an error that occurs during template rendering appears in the appropriate location. 43 ''' 44 tests = [ #In each case, we have template contents and the lines at which we expect the template error information to occur. 45 ('{% load bad_tag %}{% for i in range %}{% badsimpletag %}{% endfor %}', (18, 38)), 46 ('{% load bad_tag %}{% for i in range %}{% for j in range %}{% badsimpletag %}{% endfor %}{% endfor %}', (18, 38)), 47 ('{% load bad_tag %}{% for i in range %}{% badsimpletag %}{% for j in range %}Hello{% endfor %}{% endfor %}', (18, 38)), 48 ('{% load bad_tag %}{% for i in range %}{% for j in five %}{% badsimpletag %}{% endfor %}{% endfor %}', (18, 38)), 51 49 ('{% load bad_tag %}{% for j in five %}{% badsimpletag %}{% endfor %}', (18, 37)), 52 50 ] 53 51 context = Context({ … … 58 56 template = get_template_from_string(source) 59 57 try: 60 58 template.render(context) 61 except TemplateSyntaxError, e:62 error_source_index = e. source[1]59 except (RuntimeError, TypeError), e: 60 error_source_index = e.django_template_source[1] 63 61 self.assertEqual(error_source_index, 64 62 expected_error_source_index)