8
from cStringIO import StringIO
13
"""A basic abstraction for an error that has occurred.
15
This is necessary because Python's built-in error mechanisms are
16
inconvenient for asynchronous communication.
21
def __init__(self, exc_value=None, exc_type=None, exc_tb=None):
22
"""Initialize me with an explanation of the error.
24
By default, this will use the current exception (sys.exc_info()).
25
However, if you want to specify a particular kind of failure, you can
26
pass an exception as an argument.
31
self.type, self.value, tb = None, None, None
33
self.type, self.value, tb = sys.exc_info()
34
elif exc_type is None:
35
self.type = exc_value.__class__
36
self.value = exc_value
39
self.value = exc_value
40
frames = self.frames = []
43
localz = f.f_locals.copy()
44
if f.f_locals is f.f_globals:
47
globalz = f.f_globals.copy()
57
def getErrorMessage(self):
58
if isinstance(self.value, Failure):
59
return self.value.getErrorMessage()
60
return str(self.value)
62
def trap(self, *errorTypes):
63
"""Trap this failure if its type is in a predetermined list.
65
This allows you to trap a Failure in an error callback. It will be
66
automatically re-raised if it is not a type that you expect.
68
for errorType in errorTypes:
69
if (self.type == errorType or
70
issubclass(self.type, errorType)):
75
def getBriefTraceback(self):
77
self.printBriefTraceback(file=io)
81
return "[Failure instance: %s]" % self.getBriefTraceback()
83
def __getstate__(self):
84
"""Avoid pickling objects in the traceback.
86
c = self.__dict__.copy()
87
frames = c['frames'] = []
88
stringize = lambda (x, y): (x, repr(y))
89
for m, f, l, lo, gl in self.frames:
90
frames.append([m, f, l, map(stringize, lo), map(stringize, gl)])
94
def printTraceback(self, file=None):
95
"""Emulate Python's standard error reporting mechanism.
97
if file is None: file = sys.stdout
99
w( 'Traceback (most recent call last):\n')
100
for method, filename, lineno, localVars, globalVars in self.frames:
101
w( ' File "%s", line %s, in %s\n' % (filename, lineno, method))
102
w( ' %s\n' % string.strip(linecache.getline(filename, lineno)))
104
w("%s: %s\n" % (str(self.type), str(self.value)))
105
if isinstance(self.value, Failure):
106
file.write(" (chained Failure)\n")
107
self.value.printTraceback(file)
109
def printBriefTraceback(self, file=None):
110
"""Print a traceback as densely as possible.
112
if file is None: file = sys.stdout
114
w("Traceback! %s, %s\n" % (self.type, self.value))
115
for method, filename, lineno, localVars, globalVars in self.frames:
116
w('%s:%s:%s\n' % (filename, lineno, method))
117
if isinstance(self.value, Failure):
118
file.write(" (chained Failure)\n")
119
self.value.printBriefTraceback(file)
121
def printDetailedTraceback(self, file=None):
122
"""Print a traceback with detailed locals and globals information.
124
if file is None: file = sys.stdout
126
w( '*--- Failure #%d%s---\n' %
128
(self.pickled and ' (pickled) ') or ' '))
129
for method, filename, lineno, localVars, globalVars in self.frames:
130
w("%s:%d: %s(...)\n" % (filename, lineno, method))
132
for name, val in localVars:
133
w(" %s : %s\n" % (name,(self.pickled and val) or repr(val)))
135
for name, val in globalVars:
136
w(" %s : %s\n" % (name,(self.pickled and val) or repr(val)))
137
if isinstance(self.value, Failure):
138
w(" (chained Failure)\n")
139
self.value.printDetailedTraceback(file)
140
w('*--- End of Failure #%d ---\n' % self.count)