# Copyright (c) 2004 Divmod. # See LICENSE for details. # failure.py import types import linecache import re from nevow.tags import * from twisted.python import failure stylesheet = """ p.error { color: black; font-family: Verdana, Arial, helvetica, sans-serif; font-weight: bold; font-size: large; margin: 0.25em; } div { font-family: Verdana, Arial, helvetica, sans-serif; } strong.variableClass { font-size: small; } div.stackTrace { } div.frame { padding: 0.25em; background: white; border-bottom: thin black dotted; } div.firstFrame { padding: 0.25em; background: white; border-top: thin black dotted; border-bottom: thin black dotted; } div.location { font-size: small; } div.snippet { background: #FFFFDD; padding: 0.25em; } div.snippetHighlightLine { color: red; } span.lineno { font-size: small; } pre.code { margin: 0px; padding: 0px; display: inline; font-size: small; font-family: "Courier New", courier, monotype; } span.function { font-weight: bold; font-family: "Courier New", courier, monotype; } table.variables { border-collapse: collapse; width: 100%; } td.varName { width: 1in; vertical-align: top; font-style: italic; font-size: small; padding-right: 0.25em; } td.varValue { padding-left: 0.25em; padding-right: 0.25em; font-size: small; } div.variables { margin-top: 0.5em; } div.dict { background: #cccc99; padding: 2px; float: left; } td.dictKey { background: #ffff99; font-weight: bold; } td.dictValue { background: #ffff99; } div.list { background: #7777cc; padding: 2px; float: left; } div.listItem { background: #9999ff; } div.instance { width: 100%; background: #efefef; padding: 2px; float: left; } span.instanceName { font-size: small; display: block; } span.instanceRepr { font-family: "Courier New", courier, monotype; } div.function { background: orange; font-weight: bold; float: left; } """ def saferepr(x): try: rx = repr(x) except: rx = "repr failed! %s instance at 0x%x" % (x.__class__, id(x)) return rx def htmlDict(d): return div(_class="dict")[ span(_class="heading")[ "Dictionary instance @ 0x%x" % id(d) ], table(_class="dict")[[ tr[ td(_class="dictKey")[ k == '__builtins__' and 'builtin dictionary' or k ], td(_class="dictValue")[ htmlrepr(v) ] ] for k, v in d.items() ]] ] def htmlList(l): io = StringIO() w = io.write w('
List instance @ %s' % hex(id(l))) for i in l: w('
%s
' % htmlrepr(i)) w('
') return io.getvalue() def htmlList(l): return div(_class="list")[ span(_class="heading")[ "List instance @ 0x%x" % id(l) ], [div(_class="listItem")[ htmlrepr(i) ] for i in l] ] def htmlInst(i): return div(_class="instance")[ span(_class="instanceName")[ "%s instance at 0x%x" % (i.__class__, id(i)) ], span(_class="instanceRepr")[ saferepr(i) ] ] def htmlString(s): return s def htmlFunc(f): return div(_class="function")[ "Function %s in file %s at line %s" % (f.__name__, f.func_code.co_filename, f.func_code.co_firstlineno) ] def htmlMeth(m): return div(_class="method")[ "Method %s in file %s at line %s" % (m.im_func.__name__, m.im_func.func_code.co_filename, m.im_func.func_code.co_firstlineno) ] def htmlUnknown(u): return pre[ saferepr(u) ] htmlReprTypes = { types.DictType: htmlDict, types.ListType: htmlList, types.InstanceType: htmlInst, types.StringType: htmlString, types.FunctionType: htmlFunc, types.MethodType: htmlMeth, } def htmlrepr(x): return htmlReprTypes.get(type(x), htmlUnknown)(x) def varTable(usedVars): return table(_class="variables")[[ tr(_class="varRow")[ td(_class="varName")[ key ], td(_class="varValue")[ htmlrepr(value) ] ] for (key, value) in usedVars ]] def formatFailure(myFailure): if not isinstance(myFailure, failure.Failure): return pre[ str(myFailure) ] stackTrace = div(_class="stackTrace") failureOverview = p(_class="error")[ str(myFailure.type), ": ", str(myFailure.value) ] result = [ style(type="text/css")[ stylesheet, ], a(href="#tracebackEnd")[ failureOverview ], stackTrace, a(name="tracebackEnd")[ failureOverview ] ] first = 1 for method, filename, lineno, localVars, globalVars in myFailure.frames: # It's better to have a line number than nothing at all. #if filename == '': # continue if first: frame = div(_class="firstFrame") first = 0 else: frame = div(_class="frame") stackTrace[ frame ] snippet = div(_class="snippet") frame[ div(_class="location")[ filename, ", line ", lineno, " in ", span(_class="function")[ method ] ], snippet, ] textSnippet = '' for snipLineNo in range(lineno-2, lineno+2): snipLine = linecache.getline(filename, snipLineNo) textSnippet += snipLine if snipLineNo == lineno: snippetClass = "snippetHighlightLine" else: snippetClass = "snippetLine" snippet[ div(_class=snippetClass)[ span(_class="lineno")[ snipLineNo ], pre(_class="code")[ snipLine ] ] ] # Instance variables for name, var in localVars: if name == 'self' and hasattr(var, '__dict__'): usedVars = [ (key, value) for (key, value) in var.__dict__.items() if re.search(r'\W'+'self.'+key+r'\W', textSnippet) ] if usedVars: frame[ div(_class="variables")[ strong(_class="variableClass")[ "Self" ], varTable(usedVars) ] ] break # Local and global vars for nm, varList in ('Locals', localVars), ('Globals', globalVars): usedVars = [ (name, var) for (name, var) in varList if re.search(r'\W'+name+r'\W', textSnippet) ] if usedVars: frame[ div(_class="variables")[ strong(_class="variableClass")[ nm ] ], varTable(usedVars) ] return result