1 """This module provides features to help with debugging ROX applications."""
8 from rox
import g
, ButtonMixed
, toplevel_ref
, toplevel_unref
, _
9 from rox
import info
, alert
10 from saving
import StringSaver
14 def show_exception(type, value
, tb
, auto_details
= False):
15 """Display this exception in an error box. The user has the options
16 of ignoring the error, quitting the application and examining the
17 exception in more detail. See also rox.report_exception()."""
23 brief
= ''.join(traceback
.format_exception_only(type, value
))
26 box
= g
.MessageDialog(None, 0, g
.MESSAGE_ERROR
, g
.BUTTONS_NONE
, brief
)
29 button
= ButtonMixed(g
.STOCK_ZOOM_IN
, _('_Details'))
30 button
.set_flags(g
.CAN_DEFAULT
)
32 box
.add_action_widget(button
, DETAILS
)
34 box
.add_button(g
.STOCK_OK
, g
.RESPONSE_OK
)
35 box
.set_default_response(g
.RESPONSE_OK
)
37 box
.set_position(g
.WIN_POS_CENTER
)
38 box
.set_title(_('Error'))
40 def response(box
, resp
):
43 box
.connect('response', response
)
46 bug_report
= 'Traceback (most recent call last):\n' + \
47 ''.join(traceback
.format_stack(tb
.tb_frame
.f_back
) +
48 traceback
.format_tb(tb
) +
49 traceback
.format_exception_only(type, value
))
58 if resp
== g
.RESPONSE_OK
or resp
== g
.RESPONSE_DELETE_EVENT
:
66 savebox
= StringSaver(bug_report
, 'BugReport')
67 savebox
.connect('destroy', destroy
)
72 assert resp
== DETAILS
73 box
.set_response_sensitive(DETAILS
, False)
74 box
.set_has_separator(False)
76 button
= ButtonMixed(g
.STOCK_SAVE
, _('_Bug Report'))
77 button
.set_flags(g
.CAN_DEFAULT
)
79 box
.add_action_widget(button
, SAVE
)
80 box
.action_area
.set_child_secondary(button
, True)
82 button
= ButtonMixed(g
.STOCK_QUIT
, _('Forced Quit'))
83 button
.set_flags(g
.CAN_DEFAULT
)
85 box
.add_action_widget(button
, QUIT
)
86 box
.action_area
.set_child_secondary(button
, True)
88 ee
= ExceptionExplorer(tb
)
89 box
.vbox
.pack_start(ee
)
94 class ExceptionExplorer(g
.Frame
):
99 def __init__(self
, tb
):
100 g
.Frame
.__init
__(self
, _('Stack trace (innermost last)'))
102 vbox
= g
.VBox(False, 0)
106 inner
.set_shadow_type(g
.SHADOW_IN
)
107 vbox
.pack_start(inner
, False, True, 0)
113 self
.model
= g
.ListStore(gobject
.TYPE_STRING
, gobject
.TYPE_INT
,
114 gobject
.TYPE_STRING
, gobject
.TYPE_STRING
)
115 tree
= g
.TreeView(self
.model
)
118 cell
= g
.CellRendererText()
120 column
= g
.TreeViewColumn('File', cell
, text
= ExceptionExplorer
.FILE
)
121 cell
.set_property('xalign', 1)
122 tree
.append_column(column
)
124 cell
= g
.CellRendererText()
125 column
= g
.TreeViewColumn('Line', cell
, text
= ExceptionExplorer
.LINE
)
126 tree
.append_column(column
)
127 column
= g
.TreeViewColumn('Func', cell
, text
= ExceptionExplorer
.FUNC
)
128 tree
.append_column(column
)
129 column
= g
.TreeViewColumn('Code', cell
, text
= ExceptionExplorer
.CODE
)
130 tree
.append_column(column
)
132 inner
.set_border_width(5)
135 while tb
is not None:
136 frames
.insert(0, (tb
.tb_frame
, traceback
.tb_lineno(tb
)))
140 f
= f
.f_back
# Skip the reporting frame
142 frames
.append((f
, f
.f_lineno
))
148 for f
, lineno
in frames
:
150 filename
= co
.co_filename
152 line
= linecache
.getline(filename
, lineno
).strip()
154 filename
= os
.path
.basename(filename
)
156 new
= self
.model
.append()
157 self
.model
.set(new
, ExceptionExplorer
.FILE
, filename
,
158 ExceptionExplorer
.LINE
, lineno
,
159 ExceptionExplorer
.FUNC
, name
,
160 ExceptionExplorer
.CODE
, line
)
162 def selected_frame():
163 selected
= sel
.get_selected()
165 model
, iter = selected
166 frame
, = model
.get_path(iter)
167 return frames
[frame
][0]
169 vars = g
.ListStore(str, str)
170 sel
= tree
.get_selection()
171 sel
.set_mode(g
.SELECTION_BROWSE
)
172 def select_frame(tree
):
174 for n
, v
in selected_frame().f_locals
.iteritems():
177 value
= value
[:500] + ' ...'
179 vars.set(new
, 0, str(n
), 1, value
)
180 sel
.connect('changed', select_frame
)
182 # Area to show the local variables
183 tree
= g
.TreeView(vars)
185 vbox
.pack_start(g
.Label(_('Local variables in selected frame:')),
188 cell
= g
.CellRendererText()
189 column
= g
.TreeViewColumn('Name', cell
, text
= 0)
190 cell
.set_property('xalign', 1)
191 tree
.append_column(column
)
192 cell
= g
.CellRendererText()
193 column
= g
.TreeViewColumn('Value', cell
, text
= 1)
194 tree
.append_column(column
)
196 inner
= g
.ScrolledWindow()
197 inner
.set_size_request(-1, 200)
198 inner
.set_policy(g
.POLICY_AUTOMATIC
, g
.POLICY_ALWAYS
)
199 inner
.set_shadow_type(g
.SHADOW_IN
)
201 inner
.set_border_width(5)
202 vbox
.pack_start(inner
, True, True, 0)
207 hbox
= g
.HBox(False, 4)
208 hbox
.set_border_width(5)
209 vbox
.pack_start(hbox
, False, True, 0)
210 hbox
.pack_start(g
.Label('>>>'), False, True, 0)
213 hbox
.pack_start(expr
, True, True, 0)
215 expr
= entry
.get_text()
216 frame
= selected_frame()
218 info(`
eval(expr
, frame
.f_locals
, frame
.f_globals
)`
)
220 type, value
= sys
.exc_info()[:2]
221 brief
= ''.join(traceback
.format_exception_only(type, value
))
224 expr
.connect('activate', activate
)