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
13 def _show_debug_help():
14 from os
.path
import join
, dirname
15 help = join(dirname(dirname(dirname(__file__
))), 'Help', 'Errors')
17 filer
.spawn_rox((help,))
19 def show_exception(type, value
, tb
, auto_details
= False):
20 """Display this exception in an error box. The user has the options
21 of ignoring the error, quitting the application and examining the
22 exception in more detail. See also rox.report_exception()."""
28 brief
= ''.join(traceback
.format_exception_only(type, value
))
31 box
= g
.MessageDialog(None, 0, g
.MESSAGE_ERROR
, g
.BUTTONS_NONE
, brief
)
34 button
= ButtonMixed(g
.STOCK_ZOOM_IN
, _('_Details'))
35 button
.set_flags(g
.CAN_DEFAULT
)
37 box
.add_action_widget(button
, DETAILS
)
39 box
.add_button(g
.STOCK_HELP
, g
.RESPONSE_HELP
)
40 box
.add_button(g
.STOCK_OK
, g
.RESPONSE_OK
)
41 box
.set_default_response(g
.RESPONSE_OK
)
43 box
.set_position(g
.WIN_POS_CENTER
)
44 box
.set_title(_('Error'))
46 def response(box
, resp
):
49 box
.connect('response', response
)
52 bug_report
= 'Traceback (most recent call last):\n' + \
53 ''.join(traceback
.format_stack(tb
.tb_frame
.f_back
) +
54 traceback
.format_tb(tb
) +
55 traceback
.format_exception_only(type, value
))
64 if resp
== g
.RESPONSE_OK
or resp
== g
.RESPONSE_DELETE_EVENT
:
71 global savebox
# For pychecker
73 from saving
import StringSaver
74 savebox
= StringSaver(bug_report
, 'BugReport')
75 savebox
.connect('destroy', destroy
)
80 elif resp
== g
.RESPONSE_HELP
:
83 assert resp
== DETAILS
84 box
.set_response_sensitive(DETAILS
, False)
86 button
= ButtonMixed(g
.STOCK_SAVE
, _('_Bug Report'))
87 button
.set_flags(g
.CAN_DEFAULT
)
89 box
.add_action_widget(button
, SAVE
)
90 box
.action_area
.set_child_secondary(button
, True)
92 button
= ButtonMixed(g
.STOCK_QUIT
, _('Forced Quit'))
93 button
.set_flags(g
.CAN_DEFAULT
)
95 box
.add_action_widget(button
, QUIT
)
96 box
.action_area
.set_child_secondary(button
, True)
98 ee
= ExceptionExplorer(tb
)
99 box
.vbox
.pack_start(ee
)
104 class ExceptionExplorer(g
.Frame
):
105 """Displays details from a traceback object."""
110 def __init__(self
, tb
):
111 g
.Frame
.__init
__(self
, _('Stack trace (innermost last)'))
113 vbox
= g
.VBox(False, 0)
117 inner
.set_shadow_type(g
.SHADOW_IN
)
118 vbox
.pack_start(inner
, False, True, 0)
124 self
.model
= g
.ListStore(gobject
.TYPE_STRING
, gobject
.TYPE_INT
,
125 gobject
.TYPE_STRING
, gobject
.TYPE_STRING
)
126 tree
= g
.TreeView(self
.model
)
129 cell
= g
.CellRendererText()
131 column
= g
.TreeViewColumn('File', cell
, text
= ExceptionExplorer
.FILE
)
132 cell
.set_property('xalign', 1)
133 tree
.append_column(column
)
135 cell
= g
.CellRendererText()
136 column
= g
.TreeViewColumn('Line', cell
, text
= ExceptionExplorer
.LINE
)
137 tree
.append_column(column
)
138 column
= g
.TreeViewColumn('Func', cell
, text
= ExceptionExplorer
.FUNC
)
139 tree
.append_column(column
)
140 column
= g
.TreeViewColumn('Code', cell
, text
= ExceptionExplorer
.CODE
)
141 tree
.append_column(column
)
143 inner
.set_border_width(5)
146 while tb
is not None:
147 frames
.insert(0, (tb
.tb_frame
, traceback
.tb_lineno(tb
)))
151 f
= f
.f_back
# Skip the reporting frame
153 frames
.append((f
, f
.f_lineno
))
159 for f
, lineno
in frames
:
161 filename
= co
.co_filename
163 line
= linecache
.getline(filename
, lineno
).strip()
165 filename
= os
.path
.basename(filename
)
167 new
= self
.model
.append()
168 self
.model
.set(new
, ExceptionExplorer
.FILE
, filename
,
169 ExceptionExplorer
.LINE
, lineno
,
170 ExceptionExplorer
.FUNC
, name
,
171 ExceptionExplorer
.CODE
, line
)
173 def selected_frame():
174 selected
= sel
.get_selected()
176 model
, titer
= selected
177 frame
, = model
.get_path(titer
)
178 return frames
[frame
][0]
180 vars = g
.ListStore(str, str)
181 sel
= tree
.get_selection()
182 sel
.set_mode(g
.SELECTION_BROWSE
)
183 def select_frame(tree
):
185 for n
, v
in selected_frame().f_locals
.iteritems():
188 value
= value
[:500] + ' ...'
190 vars.set(new
, 0, str(n
), 1, value
)
191 sel
.connect('changed', select_frame
)
193 # Area to show the local variables
194 tree
= g
.TreeView(vars)
196 vbox
.pack_start(g
.Label(_('Local variables in selected frame:')),
199 cell
= g
.CellRendererText()
200 column
= g
.TreeViewColumn('Name', cell
, text
= 0)
201 cell
.set_property('xalign', 1)
202 tree
.append_column(column
)
203 cell
= g
.CellRendererText()
204 column
= g
.TreeViewColumn('Value', cell
, text
= 1)
205 tree
.append_column(column
)
207 inner
= g
.ScrolledWindow()
208 inner
.set_size_request(-1, 200)
209 inner
.set_policy(g
.POLICY_AUTOMATIC
, g
.POLICY_ALWAYS
)
210 inner
.set_shadow_type(g
.SHADOW_IN
)
212 inner
.set_border_width(5)
213 vbox
.pack_start(inner
, True, True, 0)
218 hbox
= g
.HBox(False, 4)
219 hbox
.set_border_width(5)
220 vbox
.pack_start(hbox
, False, True, 0)
221 hbox
.pack_start(g
.Label('>>>'), False, True, 0)
224 hbox
.pack_start(expr
, True, True, 0)
226 expr
= entry
.get_text()
227 frame
= selected_frame()
229 info(`
eval(expr
, frame
.f_locals
, frame
.f_globals
)`
)
231 extype
, value
= sys
.exc_info()[:2]
232 brief
= ''.join(traceback
.format_exception_only(extype
, value
))
235 expr
.connect('activate', activate
)