1
+ import inspect
1
2
import os .path
2
3
import django
3
4
import SocketServer
5
+ import sys
4
6
5
7
from django .conf import settings
6
8
from django .views .debug import linebreak_iter
@@ -21,7 +23,7 @@ def tidy_stacktrace(stack):
21
23
1. Are part of Django (except contrib apps)
22
24
2. Are part of SocketServer (used by Django's dev server)
23
25
3. Are the last entry (which is part of our stacktracing code)
24
-
26
+
25
27
``stack`` should be a list of frame tuples from ``inspect.stack()``
26
28
"""
27
29
trace = []
@@ -84,9 +86,63 @@ def get_name_from_obj(obj):
84
86
name = obj .__class__ .__name__
85
87
else :
86
88
name = '<unknown>'
87
-
89
+
88
90
if hasattr (obj , '__module__' ):
89
91
module = obj .__module__
90
92
name = '%s.%s' % (module , name )
91
93
92
- return name
94
+ return name
95
+
96
+ def getframeinfo (frame , context = 1 ):
97
+ """
98
+ Get information about a frame or traceback object.
99
+
100
+ A tuple of five things is returned: the filename, the line number of
101
+ the current line, the function name, a list of lines of context from
102
+ the source code, and the index of the current line within that list.
103
+ The optional second argument specifies the number of lines of context
104
+ to return, which are centered around the current line.
105
+
106
+ This originally comes from ``inspect`` but is modified to handle issues
107
+ with ``findsource()``.
108
+ """
109
+ if inspect .istraceback (frame ):
110
+ lineno = frame .tb_lineno
111
+ frame = frame .tb_frame
112
+ else :
113
+ lineno = frame .f_lineno
114
+ if not inspect .isframe (frame ):
115
+ raise TypeError ('arg is not a frame or traceback object' )
116
+
117
+ filename = inspect .getsourcefile (frame ) or inspect .getfile (frame )
118
+ if context > 0 :
119
+ start = lineno - 1 - context // 2
120
+ try :
121
+ lines , lnum = inspect .findsource (frame )
122
+ except (IOError , IndexError ):
123
+ lines = index = None
124
+ else :
125
+ start = max (start , 1 )
126
+ start = max (0 , min (start , len (lines ) - context ))
127
+ lines = lines [start :start + context ]
128
+ index = lineno - 1 - start
129
+ else :
130
+ lines = index = None
131
+
132
+ return inspect .Traceback (filename , lineno , frame .f_code .co_name , lines , index )
133
+
134
+ def get_stack (context = 1 ):
135
+ """
136
+ Get a list of records for a frame and all higher (calling) frames.
137
+
138
+ Each record contains a frame object, filename, line number, function
139
+ name, a list of lines of context, and index within the context.
140
+
141
+ Modified version of ``inspect.stack()`` which calls our own ``getframeinfo()``
142
+ """
143
+ frame = sys ._getframe (1 )
144
+ framelist = []
145
+ while frame :
146
+ framelist .append ((frame ,) + getframeinfo (frame , context ))
147
+ frame = frame .f_back
148
+ return framelist
0 commit comments