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