]> git.proxmox.com Git - mirror_edk2.git/blob - AppPkg/Applications/Python/Python-2.7.2/Lib/cgitb.py
e6e9117d24ace12eb7cfec37cd150ab7cf455eaf
[mirror_edk2.git] / AppPkg / Applications / Python / Python-2.7.2 / Lib / cgitb.py
1 """More comprehensive traceback formatting for Python scripts.
2
3 To enable this module, do:
4
5 import cgitb; cgitb.enable()
6
7 at the top of your script. The optional arguments to enable() are:
8
9 display - if true, tracebacks are displayed in the web browser
10 logdir - if set, tracebacks are written to files in this directory
11 context - number of lines of source code to show for each stack frame
12 format - 'text' or 'html' controls the output format
13
14 By default, tracebacks are displayed but not saved, the context is 5 lines
15 and the output format is 'html' (for backwards compatibility with the
16 original use of this module)
17
18 Alternatively, if you have caught an exception and want cgitb to display it
19 for you, call cgitb.handler(). The optional argument to handler() is a
20 3-item tuple (etype, evalue, etb) just like the value of sys.exc_info().
21 The default handler displays output as HTML.
22
23 """
24 import inspect
25 import keyword
26 import linecache
27 import os
28 import pydoc
29 import sys
30 import tempfile
31 import time
32 import tokenize
33 import traceback
34 import types
35
36 def reset():
37 """Return a string that resets the CGI and browser to a known state."""
38 return '''<!--: spam
39 Content-Type: text/html
40
41 <body bgcolor="#f0f0f8"><font color="#f0f0f8" size="-5"> -->
42 <body bgcolor="#f0f0f8"><font color="#f0f0f8" size="-5"> --> -->
43 </font> </font> </font> </script> </object> </blockquote> </pre>
44 </table> </table> </table> </table> </table> </font> </font> </font>'''
45
46 __UNDEF__ = [] # a special sentinel object
47 def small(text):
48 if text:
49 return '<small>' + text + '</small>'
50 else:
51 return ''
52
53 def strong(text):
54 if text:
55 return '<strong>' + text + '</strong>'
56 else:
57 return ''
58
59 def grey(text):
60 if text:
61 return '<font color="#909090">' + text + '</font>'
62 else:
63 return ''
64
65 def lookup(name, frame, locals):
66 """Find the value for a given name in the given environment."""
67 if name in locals:
68 return 'local', locals[name]
69 if name in frame.f_globals:
70 return 'global', frame.f_globals[name]
71 if '__builtins__' in frame.f_globals:
72 builtins = frame.f_globals['__builtins__']
73 if type(builtins) is type({}):
74 if name in builtins:
75 return 'builtin', builtins[name]
76 else:
77 if hasattr(builtins, name):
78 return 'builtin', getattr(builtins, name)
79 return None, __UNDEF__
80
81 def scanvars(reader, frame, locals):
82 """Scan one logical line of Python and look up values of variables used."""
83 vars, lasttoken, parent, prefix, value = [], None, None, '', __UNDEF__
84 for ttype, token, start, end, line in tokenize.generate_tokens(reader):
85 if ttype == tokenize.NEWLINE: break
86 if ttype == tokenize.NAME and token not in keyword.kwlist:
87 if lasttoken == '.':
88 if parent is not __UNDEF__:
89 value = getattr(parent, token, __UNDEF__)
90 vars.append((prefix + token, prefix, value))
91 else:
92 where, value = lookup(token, frame, locals)
93 vars.append((token, where, value))
94 elif token == '.':
95 prefix += lasttoken + '.'
96 parent = value
97 else:
98 parent, prefix = None, ''
99 lasttoken = token
100 return vars
101
102 def html(einfo, context=5):
103 """Return a nice HTML document describing a given traceback."""
104 etype, evalue, etb = einfo
105 if type(etype) is types.ClassType:
106 etype = etype.__name__
107 pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable
108 date = time.ctime(time.time())
109 head = '<body bgcolor="#f0f0f8">' + pydoc.html.heading(
110 '<big><big>%s</big></big>' %
111 strong(pydoc.html.escape(str(etype))),
112 '#ffffff', '#6622aa', pyver + '<br>' + date) + '''
113 <p>A problem occurred in a Python script. Here is the sequence of
114 function calls leading up to the error, in the order they occurred.</p>'''
115
116 indent = '<tt>' + small('&nbsp;' * 5) + '&nbsp;</tt>'
117 frames = []
118 records = inspect.getinnerframes(etb, context)
119 for frame, file, lnum, func, lines, index in records:
120 if file:
121 file = os.path.abspath(file)
122 link = '<a href="file://%s">%s</a>' % (file, pydoc.html.escape(file))
123 else:
124 file = link = '?'
125 args, varargs, varkw, locals = inspect.getargvalues(frame)
126 call = ''
127 if func != '?':
128 call = 'in ' + strong(func) + \
129 inspect.formatargvalues(args, varargs, varkw, locals,
130 formatvalue=lambda value: '=' + pydoc.html.repr(value))
131
132 highlight = {}
133 def reader(lnum=[lnum]):
134 highlight[lnum[0]] = 1
135 try: return linecache.getline(file, lnum[0])
136 finally: lnum[0] += 1
137 vars = scanvars(reader, frame, locals)
138
139 rows = ['<tr><td bgcolor="#d8bbff">%s%s %s</td></tr>' %
140 ('<big>&nbsp;</big>', link, call)]
141 if index is not None:
142 i = lnum - index
143 for line in lines:
144 num = small('&nbsp;' * (5-len(str(i))) + str(i)) + '&nbsp;'
145 if i in highlight:
146 line = '<tt>=&gt;%s%s</tt>' % (num, pydoc.html.preformat(line))
147 rows.append('<tr><td bgcolor="#ffccee">%s</td></tr>' % line)
148 else:
149 line = '<tt>&nbsp;&nbsp;%s%s</tt>' % (num, pydoc.html.preformat(line))
150 rows.append('<tr><td>%s</td></tr>' % grey(line))
151 i += 1
152
153 done, dump = {}, []
154 for name, where, value in vars:
155 if name in done: continue
156 done[name] = 1
157 if value is not __UNDEF__:
158 if where in ('global', 'builtin'):
159 name = ('<em>%s</em> ' % where) + strong(name)
160 elif where == 'local':
161 name = strong(name)
162 else:
163 name = where + strong(name.split('.')[-1])
164 dump.append('%s&nbsp;= %s' % (name, pydoc.html.repr(value)))
165 else:
166 dump.append(name + ' <em>undefined</em>')
167
168 rows.append('<tr><td>%s</td></tr>' % small(grey(', '.join(dump))))
169 frames.append('''
170 <table width="100%%" cellspacing=0 cellpadding=0 border=0>
171 %s</table>''' % '\n'.join(rows))
172
173 exception = ['<p>%s: %s' % (strong(pydoc.html.escape(str(etype))),
174 pydoc.html.escape(str(evalue)))]
175 if isinstance(evalue, BaseException):
176 for name in dir(evalue):
177 if name[:1] == '_': continue
178 value = pydoc.html.repr(getattr(evalue, name))
179 exception.append('\n<br>%s%s&nbsp;=\n%s' % (indent, name, value))
180
181 return head + ''.join(frames) + ''.join(exception) + '''
182
183
184 <!-- The above is a description of an error in a Python program, formatted
185 for a Web browser because the 'cgitb' module was enabled. In case you
186 are not reading this in a Web browser, here is the original traceback:
187
188 %s
189 -->
190 ''' % pydoc.html.escape(
191 ''.join(traceback.format_exception(etype, evalue, etb)))
192
193 def text(einfo, context=5):
194 """Return a plain text document describing a given traceback."""
195 etype, evalue, etb = einfo
196 if type(etype) is types.ClassType:
197 etype = etype.__name__
198 pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable
199 date = time.ctime(time.time())
200 head = "%s\n%s\n%s\n" % (str(etype), pyver, date) + '''
201 A problem occurred in a Python script. Here is the sequence of
202 function calls leading up to the error, in the order they occurred.
203 '''
204
205 frames = []
206 records = inspect.getinnerframes(etb, context)
207 for frame, file, lnum, func, lines, index in records:
208 file = file and os.path.abspath(file) or '?'
209 args, varargs, varkw, locals = inspect.getargvalues(frame)
210 call = ''
211 if func != '?':
212 call = 'in ' + func + \
213 inspect.formatargvalues(args, varargs, varkw, locals,
214 formatvalue=lambda value: '=' + pydoc.text.repr(value))
215
216 highlight = {}
217 def reader(lnum=[lnum]):
218 highlight[lnum[0]] = 1
219 try: return linecache.getline(file, lnum[0])
220 finally: lnum[0] += 1
221 vars = scanvars(reader, frame, locals)
222
223 rows = [' %s %s' % (file, call)]
224 if index is not None:
225 i = lnum - index
226 for line in lines:
227 num = '%5d ' % i
228 rows.append(num+line.rstrip())
229 i += 1
230
231 done, dump = {}, []
232 for name, where, value in vars:
233 if name in done: continue
234 done[name] = 1
235 if value is not __UNDEF__:
236 if where == 'global': name = 'global ' + name
237 elif where != 'local': name = where + name.split('.')[-1]
238 dump.append('%s = %s' % (name, pydoc.text.repr(value)))
239 else:
240 dump.append(name + ' undefined')
241
242 rows.append('\n'.join(dump))
243 frames.append('\n%s\n' % '\n'.join(rows))
244
245 exception = ['%s: %s' % (str(etype), str(evalue))]
246 if isinstance(evalue, BaseException):
247 for name in dir(evalue):
248 value = pydoc.text.repr(getattr(evalue, name))
249 exception.append('\n%s%s = %s' % (" "*4, name, value))
250
251 return head + ''.join(frames) + ''.join(exception) + '''
252
253 The above is a description of an error in a Python program. Here is
254 the original traceback:
255
256 %s
257 ''' % ''.join(traceback.format_exception(etype, evalue, etb))
258
259 class Hook:
260 """A hook to replace sys.excepthook that shows tracebacks in HTML."""
261
262 def __init__(self, display=1, logdir=None, context=5, file=None,
263 format="html"):
264 self.display = display # send tracebacks to browser if true
265 self.logdir = logdir # log tracebacks to files if not None
266 self.context = context # number of source code lines per frame
267 self.file = file or sys.stdout # place to send the output
268 self.format = format
269
270 def __call__(self, etype, evalue, etb):
271 self.handle((etype, evalue, etb))
272
273 def handle(self, info=None):
274 info = info or sys.exc_info()
275 if self.format == "html":
276 self.file.write(reset())
277
278 formatter = (self.format=="html") and html or text
279 plain = False
280 try:
281 doc = formatter(info, self.context)
282 except: # just in case something goes wrong
283 doc = ''.join(traceback.format_exception(*info))
284 plain = True
285
286 if self.display:
287 if plain:
288 doc = doc.replace('&', '&amp;').replace('<', '&lt;')
289 self.file.write('<pre>' + doc + '</pre>\n')
290 else:
291 self.file.write(doc + '\n')
292 else:
293 self.file.write('<p>A problem occurred in a Python script.\n')
294
295 if self.logdir is not None:
296 suffix = ['.txt', '.html'][self.format=="html"]
297 (fd, path) = tempfile.mkstemp(suffix=suffix, dir=self.logdir)
298 try:
299 file = os.fdopen(fd, 'w')
300 file.write(doc)
301 file.close()
302 msg = '<p> %s contains the description of this error.' % path
303 except:
304 msg = '<p> Tried to save traceback to %s, but failed.' % path
305 self.file.write(msg + '\n')
306 try:
307 self.file.flush()
308 except: pass
309
310 handler = Hook().handle
311 def enable(display=1, logdir=None, context=5, format="html"):
312 """Install an exception handler that formats tracebacks as HTML.
313
314 The optional argument 'display' can be set to 0 to suppress sending the
315 traceback to the browser, and 'logdir' can be set to a directory to cause
316 tracebacks to be written to files there."""
317 sys.excepthook = Hook(display=display, logdir=logdir,
318 context=context, format=format)