1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
from __future__ import unicode_literals
import inspect
import os.path
import django
import sys
from django.conf import settings
from django.views.debug import linebreak_iter
from django.utils.html import escape
from django.utils.safestring import mark_safe
from django.utils import six
from django.utils.six.moves import socketserver
# Figure out some paths
django_path = os.path.realpath(os.path.dirname(django.__file__))
socketserver_path = os.path.realpath(os.path.dirname(socketserver.__file__))
hide_django_sql = getattr(settings, 'DEBUG_TOOLBAR_CONFIG', {}).get('HIDE_DJANGO_SQL', True)
def tidy_stacktrace(stack):
"""
Clean up stacktrace and remove all entries that:
1. Are part of Django (except contrib apps)
2. Are part of socketserver (used by Django's dev server)
3. Are the last entry (which is part of our stacktracing code)
``stack`` should be a list of frame tuples from ``inspect.stack()``
"""
trace = []
for frame, path, line_no, func_name, text in (f[:5] for f in stack):
s_path = os.path.realpath(path)
# Support hiding of frames -- used in various utilities that provide
# inspection.
if '__traceback_hide__' in frame.f_locals:
continue
if hide_django_sql and django_path in s_path and not 'django/contrib' in s_path:
continue
if socketserver_path in s_path:
continue
if not text:
text = ''
else:
text = (''.join(text)).strip()
trace.append((path, line_no, func_name, text))
return trace
def render_stacktrace(trace):
stacktrace = []
for frame in trace:
params = map(escape, frame[0].rsplit(os.path.sep, 1) + list(frame[1:]))
params_dict = dict((six.text_type(idx), v) for idx, v in enumerate(params))
try:
stacktrace.append('<span class="path">%(0)s/</span>'
'<span class="file">%(1)s</span>'
' in <span class="func">%(3)s</span>'
'(<span class="lineno">%(2)s</span>)\n'
' <span class="code">%(4)s</span>'
% params_dict)
except KeyError:
# This frame doesn't have the expected format, so skip it and move on to the next one
continue
return mark_safe('\n'.join(stacktrace))
def get_template_info(source, context_lines=3):
line = 0
upto = 0
source_lines = []
# before = during = after = ""
origin, (start, end) = source
template_source = origin.reload()
for num, next in enumerate(linebreak_iter(template_source)):
if start >= upto and end <= next:
line = num
# before = template_source[upto:start]
# during = template_source[start:end]
# after = template_source[end:next]
source_lines.append((num, template_source[upto:next]))
upto = next
top = max(1, line - context_lines)
bottom = min(len(source_lines), line + 1 + context_lines)
context = []
for num, content in source_lines[top:bottom]:
context.append({
'num': num,
'content': content,
'highlight': (num == line),
})
return {
'name': origin.name,
'context': context,
}
def get_name_from_obj(obj):
if hasattr(obj, '__name__'):
name = obj.__name__
elif hasattr(obj, '__class__') and hasattr(obj.__class__, '__name__'):
name = obj.__class__.__name__
else:
name = '<unknown>'
if hasattr(obj, '__module__'):
module = obj.__module__
name = '%s.%s' % (module, name)
return name
def getframeinfo(frame, context=1):
"""
Get information about a frame or traceback object.
A tuple of five things is returned: the filename, the line number of
the current line, the function name, a list of lines of context from
the source code, and the index of the current line within that list.
The optional second argument specifies the number of lines of context
to return, which are centered around the current line.
This originally comes from ``inspect`` but is modified to handle issues
with ``findsource()``.
"""
if inspect.istraceback(frame):
lineno = frame.tb_lineno
frame = frame.tb_frame
else:
lineno = frame.f_lineno
if not inspect.isframe(frame):
raise TypeError('arg is not a frame or traceback object')
filename = inspect.getsourcefile(frame) or inspect.getfile(frame)
if context > 0:
start = lineno - 1 - context // 2
try:
lines, lnum = inspect.findsource(frame)
except Exception: # findsource raises platform-dependant exceptions
lines = index = None
else:
start = max(start, 1)
start = max(0, min(start, len(lines) - context))
lines = lines[start:(start + context)]
index = lineno - 1 - start
else:
lines = index = None
if hasattr(inspect, 'Traceback'):
return inspect.Traceback(filename, lineno, frame.f_code.co_name, lines, index)
else:
return (filename, lineno, frame.f_code.co_name, lines, index)
def get_stack(context=1):
"""
Get a list of records for a frame and all higher (calling) frames.
Each record contains a frame object, filename, line number, function
name, a list of lines of context, and index within the context.
Modified version of ``inspect.stack()`` which calls our own ``getframeinfo()``
"""
frame = sys._getframe(1)
framelist = []
while frame:
framelist.append((frame,) + getframeinfo(frame, context))
frame = frame.f_back
return framelist
|