Restored template error handling for Django 1.9 and newer.

This commit is contained in:
Armin Ronacher 2016-01-13 22:50:19 +01:00
parent 8755ce3b64
commit 0a2f65df9e
4 changed files with 63 additions and 27 deletions

View File

@ -151,14 +151,23 @@ class DjangoClient(Client):
if kwargs.get('exc_info'):
exc_value = kwargs['exc_info'][1]
# As of r16833 (Django) all exceptions may contain a ``django_template_source`` attribute (rather than the
# legacy ``TemplateSyntaxError.source`` check) which describes template information.
if hasattr(exc_value, 'django_template_source') or ((isinstance(exc_value, TemplateSyntaxError) and
isinstance(getattr(exc_value, 'source', None), (tuple, list)) and isinstance(exc_value.source[0], Origin))):
source = getattr(exc_value, 'django_template_source', getattr(exc_value, 'source', None))
# As of r16833 (Django) all exceptions may contain a
# ``django_template_source`` attribute (rather than the legacy
# ``TemplateSyntaxError.source`` check) which describes
# template information. As of Django 1.9 or so the new
# template debug thing showed up.
if hasattr(exc_value, 'django_template_source') or \
((isinstance(exc_value, TemplateSyntaxError) and
isinstance(getattr(exc_value, 'source', None),
(tuple, list)) and
isinstance(exc_value.source[0], Origin))) or \
hasattr(exc_value, 'template_debug'):
source = getattr(exc_value, 'django_template_source',
getattr(exc_value, 'source', None))
debug = getattr(exc_value, 'template_debug', None)
if source is None:
self.logger.info('Unable to get template source from exception')
data.update(get_data_from_template(source))
data.update(get_data_from_template(source, debug))
result = super(DjangoClient, self).capture(event_type, **kwargs)

View File

@ -8,6 +8,7 @@ raven.contrib.django.utils
from __future__ import absolute_import
import os
from django.conf import settings
@ -20,21 +21,31 @@ def linebreak_iter(template_source):
yield len(template_source) + 1
def get_data_from_template(source):
origin, (start, end) = source
template_source = origin.reload()
def get_data_from_template(source, debug=None):
if debug is not None:
start = debug['start']
end = debug['end']
source_lines = debug['source_lines']
lineno = debug['line']
filename = debug['name']
culprit = filename.split('/templates/')[-1]
elif source:
origin, (start, end) = source
filename = culprit = getattr(origin, 'loadname', None)
template_source = origin.reload()
lineno = None
upto = 0
source_lines = []
for num, next in enumerate(linebreak_iter(template_source)):
if start >= upto and end <= next:
lineno = num
source_lines.append(template_source[upto:next])
upto = next
lineno = None
upto = 0
source_lines = []
for num, next in enumerate(linebreak_iter(template_source)):
if start >= upto and end <= next:
lineno = num
source_lines.append(template_source[upto:next])
upto = next
if not source_lines or lineno is None:
return {}
if not source_lines or lineno is None:
return {}
else:
raise TypeError('Source or debug needed')
pre_context = source_lines[max(lineno - 3, 0):lineno]
post_context = source_lines[(lineno + 1):(lineno + 4)]
@ -42,14 +53,14 @@ def get_data_from_template(source):
return {
'template': {
'filename': getattr(origin, 'loadname', None),
'abs_path': origin.name,
'filename': os.path.basename(filename),
'abs_path': filename,
'pre_context': pre_context,
'context_line': context_line,
'lineno': lineno,
'post_context': post_context,
},
'culprit': getattr(origin, 'loadname', None),
'culprit': culprit,
}

View File

@ -1 +1,20 @@
{% invalid template tag %}
1
2
3
4
5
6
7
8
9
{% invalid template tag %}
11
12
13
14
15
16
17
18
19
20

View File

@ -319,9 +319,6 @@ class DjangoClientTest(TestCase):
assert event['culprit'].startswith('django.shortcuts in ')
self.raven.include_paths = include_paths
# This is broken as of recently. It only works on older Django
# versions?
@pytest.mark.xfail
def test_template_name_as_view(self):
self.assertRaises(TemplateSyntaxError, self.client.get, reverse('sentry-template-exc'))