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'))
48 bug_report
= 'Traceback (most recent call last):\n' + \
49 ''.join(traceback
.format_stack(tb
.tb_frame
.f_back
) +
50 traceback
.format_tb(tb
) +
51 traceback
.format_exception_only(type, value
))
53 bug_report
= 'No stack trace.'
61 if resp
== int(g
.RESPONSE_OK
) or resp
== int(g
.RESPONSE_DELETE_EVENT
):
68 global savebox
# For pychecker
70 from saving
import StringSaver
71 savebox
= StringSaver(bug_report
, 'BugReport')
72 savebox
.connect('destroy', destroy
)
77 elif resp
== int(g
.RESPONSE_HELP
):
80 assert resp
== DETAILS
81 box
.set_response_sensitive(DETAILS
, False)
83 button
= ButtonMixed(g
.STOCK_SAVE
, _('_Bug Report'))
84 button
.set_flags(g
.CAN_DEFAULT
)
86 box
.add_action_widget(button
, SAVE
)
87 box
.action_area
.set_child_secondary(button
, True)
89 button
= ButtonMixed(g
.STOCK_QUIT
, _('Forced Quit'))
90 button
.set_flags(g
.CAN_DEFAULT
)
92 box
.add_action_widget(button
, QUIT
)
93 box
.action_area
.set_child_secondary(button
, True)
96 ee
= ExceptionExplorer(tb
)
97 box
.vbox
.pack_start(ee
)
100 no_trace
= g
.Label('No traceback object!')
101 box
.vbox
.pack_start(no_trace
)
106 class ExceptionExplorer(g
.Frame
):
107 """Displays details from a traceback object."""
113 def __init__(self
, tb
):
114 g
.Frame
.__init
__(self
, _('Stack trace (innermost last)'))
116 vbox
= g
.VBox(False, 0)
120 inner
.set_shadow_type(g
.SHADOW_IN
)
121 vbox
.pack_start(inner
, False, True, 0)
127 self
.model
= g
.ListStore(gobject
.TYPE_STRING
, gobject
.TYPE_INT
,
128 gobject
.TYPE_STRING
, gobject
.TYPE_STRING
,
130 tree
= g
.TreeView(self
.model
)
133 cell
= g
.CellRendererText()
135 column
= g
.TreeViewColumn('File', cell
, text
= ExceptionExplorer
.LEAF
)
136 cell
.set_property('xalign', 1)
137 tree
.append_column(column
)
139 cell
= g
.CellRendererText()
140 column
= g
.TreeViewColumn('Line', cell
, text
= ExceptionExplorer
.LINE
)
141 tree
.append_column(column
)
142 column
= g
.TreeViewColumn('Func', cell
, text
= ExceptionExplorer
.FUNC
)
143 tree
.append_column(column
)
144 column
= g
.TreeViewColumn('Code', cell
, text
= ExceptionExplorer
.CODE
)
145 tree
.append_column(column
)
147 inner
.set_border_width(5)
150 while tb
is not None:
151 frames
.insert(0, (tb
.tb_frame
, traceback
.tb_lineno(tb
)))
155 f
= f
.f_back
# Skip the reporting frame
157 frames
.append((f
, f
.f_lineno
))
163 for f
, lineno
in frames
:
165 filename
= co
.co_filename
167 line
= linecache
.getline(filename
, lineno
).strip()
169 leafname
= os
.path
.basename(filename
)
171 new
= self
.model
.append()
172 self
.model
.set(new
, ExceptionExplorer
.LEAF
, leafname
,
173 ExceptionExplorer
.LINE
, lineno
,
174 ExceptionExplorer
.FUNC
, name
,
175 ExceptionExplorer
.CODE
, line
,
176 ExceptionExplorer
.FILE
, filename
)
178 def selected_frame():
179 selected
= sel
.get_selected()
181 model
, titer
= selected
182 frame
, = model
.get_path(titer
)
183 return frames
[frame
][0]
185 vars = g
.ListStore(str, str)
186 sel
= tree
.get_selection()
187 sel
.set_mode(g
.SELECTION_BROWSE
)
188 def select_frame(tree
):
190 for n
, v
in selected_frame().f_locals
.iteritems():
193 value
= value
[:500] + ' ...'
195 vars.set(new
, 0, str(n
), 1, value
)
196 sel
.connect('changed', select_frame
)
197 def show_source(tree
, path
, column
):
198 line
= self
.model
[path
][ExceptionExplorer
.LINE
]
199 file = self
.model
[path
][ExceptionExplorer
.FILE
]
201 launch
.launch('http://rox.sourceforge.net/2005/interfaces/Edit',
204 tree
.connect('row-activated', show_source
)
206 # Area to show the local variables
207 tree
= g
.TreeView(vars)
209 vbox
.pack_start(g
.Label(_('Local variables in selected frame:')),
212 cell
= g
.CellRendererText()
213 column
= g
.TreeViewColumn('Name', cell
, text
= 0)
214 cell
.set_property('xalign', 1)
215 tree
.append_column(column
)
216 cell
= g
.CellRendererText()
217 column
= g
.TreeViewColumn('Value', cell
, text
= 1)
218 tree
.append_column(column
)
220 inner
= g
.ScrolledWindow()
221 inner
.set_size_request(-1, 200)
222 inner
.set_policy(g
.POLICY_AUTOMATIC
, g
.POLICY_ALWAYS
)
223 inner
.set_shadow_type(g
.SHADOW_IN
)
225 inner
.set_border_width(5)
226 vbox
.pack_start(inner
, True, True, 0)
231 hbox
= g
.HBox(False, 4)
232 hbox
.set_border_width(5)
233 vbox
.pack_start(hbox
, False, True, 0)
234 hbox
.pack_start(g
.Label('>>>'), False, True, 0)
237 hbox
.pack_start(expr
, True, True, 0)
239 expr
= entry
.get_text()
240 frame
= selected_frame()
242 info(`
eval(expr
, frame
.f_locals
, frame
.f_globals
)`
)
244 extype
, value
= sys
.exc_info()[:2]
245 brief
= ''.join(traceback
.format_exception_only(extype
, value
))
248 expr
.connect('activate', activate
)