-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathgtkexcepthook.py
202 lines (176 loc) · 5.91 KB
/
gtkexcepthook.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# vim: sw=4 ts=4:
#
# (c) 2003 Gustavo J A M Carneiro gjc at inescporto.pt
# 2004-2005 Filip Van Raemdonck
#
# http://www.daa.com.au/pipermail/pygtk/2003-August/005775.html
# Message-ID: <[email protected]>
# "The license is whatever you want."
import inspect, linecache, pydoc, sys, traceback
import os
from cStringIO import StringIO
from gettext import gettext as _
import pygtk
pygtk.require ('2.0')
import gtk, pango
def lookup (name, frame, lcls):
'''Find the value for a given name in the given frame'''
if name in lcls:
return 'local', lcls[name]
elif name in frame.f_globals:
return 'global', frame.f_globals[name]
elif '__builtins__' in frame.f_globals:
builtins = frame.f_globals['__builtins__']
if type (builtins) is dict:
if name in builtins:
return 'builtin', builtins[name]
else:
if hasattr (builtins, name):
return 'builtin', getattr (builtins, name)
return None, []
def saveStackTrace(trace):
dialog = gtk.FileChooserDialog("Save...", None, gtk.FILE_CHOOSER_ACTION_SAVE,
(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE,
gtk.RESPONSE_OK))
dialog.set_current_name("erminig_trace.txt")
dialog.set_current_folder(os.path.expanduser("~"))
loop = True
while loop:
resp = dialog.run()
if resp == gtk.RESPONSE_OK:
filename = dialog.get_filename()
# check file existence:
if os.path.exists(filename):
dlg = gtk.MessageDialog(dialog, 0, gtk.MESSAGE_QUESTION,
gtk.BUTTONS_YES_NO, "File already exist. Overwrite?")
overwriteResponse = dlg.run()
dlg.destroy()
if overwriteResponse == gtk.RESPONSE_NO:
continue
# Check if file can be written:
# Save trace to file:
try:
f = open(filename, 'w')
f.write(trace)
f.write("\n")
f.close()
dialog.destroy()
loop = False
except IOError:
dlg = gtk.MessageDialog(dialog, 0, gtk.MESSAGE_ERROR,
gtk.BUTTONS_OK, "Error: could not write to file (check permissions?)")
dlg.run()
dlg.destroy()
continue
elif resp == gtk.RESPONSE_CANCEL:
dialog.destroy()
loop = False
def analyse (exctyp, value, tb):
import tokenize, keyword
trace = StringIO()
nlines = 3
frecs = inspect.getinnerframes (tb, nlines)
trace.write ('Traceback (most recent call last):\n')
for frame, fname, lineno, funcname, context, cindex in frecs:
trace.write (' File "%s", line %d, ' % (fname, lineno))
args, varargs, varkw, lcls = inspect.getargvalues (frame)
def readline (lno=[lineno], *args):
if args: print args
try: return linecache.getline (fname, lno[0])
finally: lno[0] += 1
all, prev, name, scope = {}, None, '', None
for ttype, tstr, stup, etup, line in tokenize.generate_tokens (readline):
if ttype == tokenize.NAME and tstr not in keyword.kwlist:
if name:
if name[-1] == '.':
try:
val = getattr (prev, tstr)
except AttributeError:
# XXX skip the rest of this identifier only
break
name += tstr
else:
assert not name and not scope
scope, val = lookup (tstr, frame, lcls)
name = tstr
if val:
prev = val
#print ' found', scope, 'name', name, 'val', val, 'in', prev, 'for token', tstr
elif tstr == '.':
if prev:
name += '.'
else:
if name:
all[name] = (scope, prev)
prev, name, scope = None, '', None
if ttype == tokenize.NEWLINE:
break
trace.write (funcname +
inspect.formatargvalues (args, varargs, varkw, lcls, formatvalue=lambda v: '=' + pydoc.text.repr (v)) + '\n')
trace.write (''.join ([' ' + x.replace ('\t', ' ') for x in filter (lambda a: a.strip(), context)]))
if len (all):
trace.write (' variables: %s\n' % str (all))
trace.write ('%s: %s' % (exctyp.__name__, value))
return trace
def _info (exctyp, value, tb):
trace = None
dialog = gtk.MessageDialog (parent=None, flags=0, type=gtk.MESSAGE_WARNING, buttons=gtk.BUTTONS_NONE)
dialog.set_title (_("Bug Detected"))
if gtk.check_version (2, 4, 0) is not None:
dialog.set_has_separator (False)
primary = _("<big><b>A programming error has been detected during the execution of this program.</b></big>")
secondary = _("It probably isn't fatal, but should be reported to the developers nonetheless.")
try:
setsec = dialog.format_secondary_text
except AttributeError:
raise
dialog.vbox.get_children()[0].get_children()[1].set_markup ('%s\n\n%s' % (primary, secondary))
#lbl.set_property ("use-markup", True)
else:
del setsec
dialog.set_markup (primary)
dialog.format_secondary_text (secondary)
dialog.add_button (_("Details..."), 2)
dialog.add_button (gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)
dialog.add_button (gtk.STOCK_QUIT, 1)
while True:
resp = dialog.run()
if resp == 2:
if trace == None:
trace = analyse (exctyp, value, tb)
# Show details...
details = gtk.Dialog (_("Bug Details"), dialog,
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE, ))
details.set_property ("has-separator", False)
details.add_button("Save to file...", 3)
textview = gtk.TextView(); textview.show()
textview.set_editable (False)
textview.modify_font (pango.FontDescription ("Monospace"))
sw = gtk.ScrolledWindow(); sw.show()
sw.set_policy (gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
sw.add (textview)
details.vbox.add (sw)
textbuffer = textview.get_buffer()
textbuffer.set_text (trace.getvalue())
monitor = gtk.gdk.screen_get_default ().get_monitor_at_window (dialog.window)
area = gtk.gdk.screen_get_default ().get_monitor_geometry (monitor)
try:
w = area.width // 1.6
h = area.height // 1.6
except SyntaxError:
# python < 2.2
w = area.width / 1.6
h = area.height / 1.6
details.set_default_size (int (w), int (h))
detResp = details.run()
if detResp != gtk.RESPONSE_CLOSE:
saveStackTrace(trace.getvalue())
details.destroy()
elif resp == 1 and gtk.main_level() > 0:
gtk.main_quit()
break
else:
break
dialog.destroy()
sys.excepthook = _info