2
from pypy.rlib.objectmodel import we_are_translated
4
AUTO_DEBUG = os.getenv('PYPY_DEBUG')
5
RECORD_INTERPLEVEL_TRACEBACK = True
8
class OperationError(Exception):
9
"""Interpreter-level exception that signals an exception that should be
10
sent to the application level.
12
OperationError instances have three public attributes (and no .args),
13
w_type, w_value and application_traceback, which contain the wrapped
14
type and value describing the exception, and a chained list of
15
PyTraceback objects making the application-level traceback.
18
def __init__(self, w_type, w_value, tb=None):
20
from pypy.tool.error import FlowingError
21
raise FlowingError(w_value)
23
self.w_value = w_value
24
self.application_traceback = tb
25
if not we_are_translated():
28
def clear(self, space):
30
self.w_type = space.w_None
31
self.w_value = space.w_None
32
self.application_traceback = None
33
if not we_are_translated():
34
del self.debug_excs[:]
36
def match(self, space, w_check_class):
37
"Check if this application-level exception matches 'w_check_class'."
38
return space.exception_match(self.w_type, w_check_class)
40
def async(self, space):
41
"Check if this is an exception that should better not be caught."
42
return (self.match(space, space.w_SystemExit) or
43
self.match(space, space.w_KeyboardInterrupt))
46
"NOT_RPYTHON: Convenience for tracebacks."
47
return '[%s: %s]' % (self.w_type, self.w_value)
49
def errorstr(self, space):
50
"The exception class and value, as a string."
52
# this part NOT_RPYTHON
53
exc_typename = str(self.w_type)
54
exc_value = str(self.w_value)
57
if space.is_w(space.type(self.w_type), space.w_str):
58
exc_typename = space.str_w(self.w_type)
60
exc_typename = space.str_w(
61
space.getattr(self.w_type, w('__name__')))
62
if space.is_w(self.w_value, space.w_None):
66
exc_value = space.str_w(space.str(self.w_value))
67
except OperationError:
68
# oups, cannot __str__ the exception object
69
exc_value = "<oups, exception object itself cannot be str'd>"
73
return '%s: %s' % (exc_typename, exc_value)
76
"The frame this exception was raised in, or None."
77
if self.application_traceback:
78
return self.application_traceback.frame
82
def record_interpreter_traceback(self):
83
"""Records the current traceback inside the interpreter.
84
This traceback is only useful to debug the interpreter, not the
86
if not we_are_translated():
87
if RECORD_INTERPLEVEL_TRACEBACK:
88
self.debug_excs.append(sys.exc_info())
90
def print_application_traceback(self, space, file=None):
91
"NOT_RPYTHON: Dump a standard application-level traceback."
92
if file is None: file = sys.stderr
93
self.print_app_tb_only(file)
94
print >> file, self.errorstr(space)
96
def print_app_tb_only(self, file):
98
tb = self.application_traceback
101
print >> file, "Traceback (application-level):"
102
while tb is not None:
105
fname = co.co_filename
106
if fname.startswith('<inline>\n'):
107
lines = fname.split('\n')
108
fname = lines[0].strip()
114
l = linecache.getline(fname, lineno)
115
print >> file, " File \"%s\"," % fname,
116
print >> file, "line", lineno, "in", co.co_name
124
def print_detailed_traceback(self, space=None, file=None):
125
"""NOT_RPYTHON: Dump a nice detailed interpreter- and
126
application-level traceback, useful to debug the interpreter."""
127
import traceback, cStringIO
128
if file is None: file = sys.stderr
129
f = cStringIO.StringIO()
130
for i in range(len(self.debug_excs)-1, -1, -1):
131
print >> f, "Traceback (interpreter-level):"
132
traceback.print_tb(self.debug_excs[i][2], file=f)
134
debug_print(''.join(['|| ' + line for line in f.readlines()]), file)
136
from pypy.tool import tb_server
137
tb_server.publish_exc(self.debug_excs[-1])
138
self.print_app_tb_only(file)
139
print >> file, '(application-level)', self.errorstr(space)
144
def normalize_exception(self, space):
145
"""Normalize the OperationError. In other words, fix w_type and/or
146
w_value to make sure that the __class__ of w_value is exactly w_type.
149
w_value = self.w_value
150
if space.full_exceptions:
151
while space.is_true(space.isinstance(w_type, space.w_tuple)):
152
w_type = space.getitem(w_type, space.wrap(0))
154
if space.is_true(space.abstract_isclass(w_type)):
155
if space.is_w(w_value, space.w_None):
156
# raise Type: we assume we have to instantiate Type
157
w_value = space.call_function(w_type)
158
w_type = space.abstract_getclass(w_value)
160
w_valuetype = space.abstract_getclass(w_value)
161
if space.is_true(space.abstract_issubclass(w_valuetype,
163
# raise Type, Instance: let etype be the exact type of value
166
if space.full_exceptions and space.is_true(
167
space.isinstance(w_value, space.w_tuple)):
168
# raise Type, tuple: assume the tuple contains the
170
w_value = space.call(w_type, w_value)
172
# raise Type, X: assume X is the constructor argument
173
w_value = space.call_function(w_type, w_value)
174
w_type = space.abstract_getclass(w_value)
176
elif space.full_exceptions and space.is_w(space.type(w_type),
178
# XXX warn -- deprecated
182
# raise X: we assume that X is an already-built instance
183
if not space.is_w(w_value, space.w_None):
184
raise OperationError(space.w_TypeError,
185
space.wrap("instance exception may not "
186
"have a separate value"))
188
w_type = space.abstract_getclass(w_value)
189
if space.full_exceptions:
190
# for the sake of language consistency we should not allow
191
# things like 'raise 1', but it is probably fine (i.e.
192
# not ambiguous) to allow them in the explicit form
194
if (space.findattr(w_value, space.wrap('__dict__')) is None and
195
space.findattr(w_value, space.wrap('__slots__')) is None):
196
msg = ("raising built-in objects can be ambiguous, "
197
"use 'raise type, value' instead")
198
raise OperationError(space.w_TypeError, space.wrap(msg))
200
self.w_value = w_value
202
def write_unraisable(self, space, where, w_object=None):
207
objrepr = space.str_w(space.repr(w_object))
208
except OperationError:
210
msg = 'Exception "%s" in %s%s ignored\n' % (self.errorstr(space),
213
space.call_method(space.sys.get('stderr'), 'write', space.wrap(msg))
214
except OperationError:
219
from pypy.tool.ansi_print import ansi_print
221
def debug_print(text, file=None, newline=True):
222
# 31: ANSI color code "red"
223
ansi_print(text, esc="31", file=file, newline=newline)
225
### installing the excepthook for OperationErrors
226
##def operr_excepthook(exctype, value, traceback):
227
## if issubclass(exctype, OperationError):
228
## value.debug_excs.append((exctype, value, traceback))
229
## value.print_detailed_traceback()
231
## old_excepthook(exctype, value, traceback)
232
## from pypy.tool import tb_server
233
## tb_server.publish_exc((exctype, value, traceback))
235
##old_excepthook = sys.excepthook
236
##sys.excepthook = operr_excepthook