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."""
111 def __init__(self
, tb
):
112 g
.Frame
.__init
__(self
, _('Stack trace (innermost last)'))
114 vbox
= g
.VBox(False, 0)
118 inner
.set_shadow_type(g
.SHADOW_IN
)
119 vbox
.pack_start(inner
, False, True, 0)
125 self
.model
= g
.ListStore(gobject
.TYPE_STRING
, gobject
.TYPE_INT
,
126 gobject
.TYPE_STRING
, gobject
.TYPE_STRING
,
128 tree
= g
.TreeView(self
.model
)
131 cell
= g
.CellRendererText()
133 column
= g
.TreeViewColumn('File', cell
, text
= ExceptionExplorer
.LEAF
)
134 cell
.set_property('xalign', 1)
135 tree
.append_column(column
)
137 cell
= g
.CellRendererText()
138 column
= g
.TreeViewColumn('Line', cell
, text
= ExceptionExplorer
.LINE
)
139 tree
.append_column(column
)
140 column
= g
.TreeViewColumn('Func', cell
, text
= ExceptionExplorer
.FUNC
)
141 tree
.append_column(column
)
142 column
= g
.TreeViewColumn('Code', cell
, text
= ExceptionExplorer
.CODE
)
143 tree
.append_column(column
)
145 inner
.set_border_width(5)
148 while tb
is not None:
149 frames
.insert(0, (tb
.tb_frame
, traceback
.tb_lineno(tb
)))
153 f
= f
.f_back
# Skip the reporting frame
155 frames
.append((f
, f
.f_lineno
))
161 for f
, lineno
in frames
:
163 filename
= co
.co_filename
165 line
= linecache
.getline(filename
, lineno
).strip()
167 leafname
= os
.path
.basename(filename
)
169 new
= self
.model
.append()
170 self
.model
.set(new
, ExceptionExplorer
.LEAF
, leafname
,
171 ExceptionExplorer
.LINE
, lineno
,
172 ExceptionExplorer
.FUNC
, name
,
173 ExceptionExplorer
.CODE
, line
,
174 ExceptionExplorer
.FILE
, filename
)
176 def selected_frame():
177 selected
= sel
.get_selected()
179 model
, titer
= selected
180 frame
, = model
.get_path(titer
)
181 return frames
[frame
][0]
183 vars = g
.ListStore(str, str)
184 sel
= tree
.get_selection()
185 sel
.set_mode(g
.SELECTION_BROWSE
)
186 def select_frame(tree
):
188 for n
, v
in selected_frame().f_locals
.iteritems():
191 value
= value
[:500] + ' ...'
193 vars.set(new
, 0, str(n
), 1, value
)
194 sel
.connect('changed', select_frame
)
195 def show_source(tree
, path
, column
):
196 line
= self
.model
[path
][ExceptionExplorer
.LINE
]
197 file = self
.model
[path
][ExceptionExplorer
.FILE
]
199 launch
.launch('http://rox.sourceforge.net/2005/interfaces/Edit',
202 tree
.connect('row-activated', show_source
)
204 # Area to show the local variables
205 tree
= g
.TreeView(vars)
207 vbox
.pack_start(g
.Label(_('Local variables in selected frame:')),
210 cell
= g
.CellRendererText()
211 column
= g
.TreeViewColumn('Name', cell
, text
= 0)
212 cell
.set_property('xalign', 1)
213 tree
.append_column(column
)
214 cell
= g
.CellRendererText()
215 column
= g
.TreeViewColumn('Value', cell
, text
= 1)
216 tree
.append_column(column
)
218 inner
= g
.ScrolledWindow()
219 inner
.set_size_request(-1, 200)
220 inner
.set_policy(g
.POLICY_AUTOMATIC
, g
.POLICY_ALWAYS
)
221 inner
.set_shadow_type(g
.SHADOW_IN
)
223 inner
.set_border_width(5)
224 vbox
.pack_start(inner
, True, True, 0)
229 hbox
= g
.HBox(False, 4)
230 hbox
.set_border_width(5)
231 vbox
.pack_start(hbox
, False, True, 0)
232 hbox
.pack_start(g
.Label('>>>'), False, True, 0)
235 hbox
.pack_start(expr
, True, True, 0)
237 expr
= entry
.get_text()
238 frame
= selected_frame()
240 info(`
eval(expr
, frame
.f_locals
, frame
.f_globals
)`
)
242 extype
, value
= sys
.exc_info()[:2]
243 brief
= ''.join(traceback
.format_exception_only(extype
, value
))
246 expr
.connect('activate', activate
)