1 """This module provides features to help with debugging ROX applications."""
8 from rox
import g
, ButtonMixed
, TRUE
, FALSE
, toplevel_ref
, toplevel_unref
, _
9 from rox
import info
, alert
10 from saving
import StringSaver
14 def show_exception(type, value
, tb
):
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
)
28 button
= ButtonMixed(g
.STOCK_ZOOM_IN
, _('_Details'))
29 button
.set_flags(g
.CAN_DEFAULT
)
31 box
.add_action_widget(button
, DETAILS
)
33 box
.add_button(g
.STOCK_OK
, g
.RESPONSE_OK
)
34 box
.set_default_response(g
.RESPONSE_OK
)
36 box
.set_position(g
.WIN_POS_CENTER
)
37 box
.set_title(_('Error'))
39 def response(box
, resp
):
42 box
.connect('response', response
)
45 bug_report
= 'Traceback (most recent call last):\n' + \
46 ''.join(traceback
.format_stack(tb
.tb_frame
.f_back
) +
47 traceback
.format_tb(tb
) +
48 traceback
.format_exception_only(type, value
))
53 if resp
== g
.RESPONSE_OK
or resp
== g
.RESPONSE_DELETE_EVENT
:
61 savebox
= StringSaver(bug_report
, 'BugReport')
62 savebox
.connect('destroy', destroy
)
67 assert resp
== DETAILS
68 box
.set_response_sensitive(DETAILS
, FALSE
)
69 box
.set_has_separator(FALSE
)
71 button
= ButtonMixed(g
.STOCK_SAVE
, _('_Bug Report'))
72 button
.set_flags(g
.CAN_DEFAULT
)
74 box
.add_action_widget(button
, SAVE
)
75 box
.action_area
.set_child_secondary(button
, TRUE
)
77 button
= ButtonMixed(g
.STOCK_QUIT
, _('Forced Quit'))
78 button
.set_flags(g
.CAN_DEFAULT
)
80 box
.add_action_widget(button
, QUIT
)
81 box
.action_area
.set_child_secondary(button
, TRUE
)
83 ee
= ExceptionExplorer(tb
)
84 box
.vbox
.pack_start(ee
)
89 class ExceptionExplorer(g
.Frame
):
94 def __init__(self
, tb
):
95 g
.Frame
.__init
__(self
, _('Stack trace (innermost last)'))
97 vbox
= g
.VBox(FALSE
, 0)
101 inner
.set_shadow_type(g
.SHADOW_IN
)
108 self
.model
= g
.ListStore(gobject
.TYPE_STRING
, gobject
.TYPE_INT
,
109 gobject
.TYPE_STRING
, gobject
.TYPE_STRING
)
110 tree
= g
.TreeView(self
.model
)
113 cell
= g
.CellRendererText()
115 column
= g
.TreeViewColumn('File', cell
, text
= ExceptionExplorer
.FILE
)
116 cell
.set_property('xalign', 1)
117 tree
.append_column(column
)
119 cell
= g
.CellRendererText()
120 column
= g
.TreeViewColumn('Line', cell
, text
= ExceptionExplorer
.LINE
)
121 tree
.append_column(column
)
122 column
= g
.TreeViewColumn('Func', cell
, text
= ExceptionExplorer
.FUNC
)
123 tree
.append_column(column
)
124 column
= g
.TreeViewColumn('Code', cell
, text
= ExceptionExplorer
.CODE
)
125 tree
.append_column(column
)
127 inner
.set_border_width(5)
130 while tb
is not None:
131 frames
.insert(0, (tb
.tb_frame
, traceback
.tb_lineno(tb
)))
135 f
= f
.f_back
# Skip the reporting frame
137 frames
.append((f
, f
.f_lineno
))
143 for f
, lineno
in frames
:
145 filename
= co
.co_filename
147 line
= linecache
.getline(filename
, lineno
).strip()
149 filename
= os
.path
.basename(filename
)
151 new
= self
.model
.append()
152 self
.model
.set(new
, ExceptionExplorer
.FILE
, filename
,
153 ExceptionExplorer
.LINE
, lineno
,
154 ExceptionExplorer
.FUNC
, name
,
155 ExceptionExplorer
.CODE
, line
)
157 def selected_frame():
158 selected
= sel
.get_selected()
160 model
, iter = selected
161 frame
, = model
.get_path(iter)
162 return frames
[frame
][0]
164 vars = g
.ListStore(str, str)
165 sel
= tree
.get_selection()
166 sel
.set_mode(g
.SELECTION_BROWSE
)
167 def select_frame(tree
):
169 for n
, v
in selected_frame().f_locals
.iteritems():
171 vars.set(new
, 0, str(n
), 1, `v`
)
172 sel
.connect('changed', select_frame
)
174 # Area to show the local variables
175 tree
= g
.TreeView(vars)
177 vbox
.pack_start(g
.Label(_('Local variables in selected frame:')),
180 cell
= g
.CellRendererText()
181 column
= g
.TreeViewColumn('Name', cell
, text
= 0)
182 cell
.set_property('xalign', 1)
183 tree
.append_column(column
)
184 cell
= g
.CellRendererText()
185 column
= g
.TreeViewColumn('Value', cell
, text
= 1)
186 tree
.append_column(column
)
189 inner
.set_shadow_type(g
.SHADOW_IN
)
191 inner
.set_border_width(5)
192 vbox
.pack_start(inner
, TRUE
, TRUE
, 0)
197 hbox
= g
.HBox(FALSE
, 4)
198 hbox
.set_border_width(5)
199 vbox
.pack_start(hbox
, FALSE
, TRUE
, 0)
200 hbox
.pack_start(g
.Label('>>>'), FALSE
, TRUE
, 0)
203 hbox
.pack_start(expr
, TRUE
, TRUE
, 0)
205 expr
= entry
.get_text()
206 frame
= selected_frame()
208 info(`
eval(expr
, frame
.f_locals
, frame
.f_globals
)`
)
210 type, value
= sys
.exc_info()[:2]
211 brief
= ''.join(traceback
.format_exception_only(type, value
))
214 expr
.connect('activate', activate
)