1
# -*- coding: utf-8 -*-
2
# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79:
3
# $Id: plugin.py 429 2005-07-21 20:55:07Z aafshar $
6
import pida.plugin as plugin
13
import pida.base as base
14
import pida.gtkextra as gtkextra
15
import pida.gobjectreactor as gobjectreactor
20
def script_directory():
22
d, f = os.path.split(f.func_code.co_filename)
25
SCRIPT_DIR = script_directory()
27
class StackTree(gtkextra.Tree):
28
COLUMNS = [('display', gobject.TYPE_STRING, gtk.CellRendererText, True,
30
('frame', gobject.TYPE_PYOBJECT, None, False, None)]
33
# self.title = gtk.Label()
34
# self.toolbar.pack_start(self.title)
35
# self.refresh_label()
36
#def l_cb_selected(self, tv):
37
# #self.fv.refresh_label(self.selected(1))
38
#def refresh_label(self):
39
# self.title.set_markup('Stack')
42
def populate(self, stack, curindex):
46
if not fr.filename.count('bdb.py') and fr.filename != '<string>':
47
last = self.add_item([fr.markup(), fr])
49
path = self.model.get_path(last)
50
self.view.set_cursor(path)
52
class BreakTree(gtkextra.Tree):
53
COLUMNS = [('display', gobject.TYPE_STRING, gtk.CellRendererText, True,
55
('filename', gobject.TYPE_STRING, None, False, None),
56
('line', gobject.TYPE_STRING, None, False, None)]
59
# self.title = gtk.Label()
60
# self.toolbar.pack_start(self.title)
61
# self.refresh_label()
63
def refresh_label(self):
64
self.title.set_markup('Breakpoints')
66
def add(self, filename, line):
67
mu = self.markup(filename, line)
68
self.add_item([mu, filename, line])
71
for row in self.model:
72
# not allowed to slice row sequences
73
yield [row[1], row[2]]
75
def markup(self, filename, line):
76
dn, fn = os.path.split(filename)
77
MU = ('<span size="small"><b>%s</b> '
78
'(<span foreground="#0000c0">%s</span>)\n'
80
return MU % (fn, line, dn)
84
return '%s %s %s %s %s' % (c.co_name,
85
c.co_argcount, c.co_names, c.co_filename, c.co_firstlineno)
87
class VarTree(gtkextra.Tree):
88
COLUMNS = [('display', gobject.TYPE_STRING, gtk.CellRendererText, True,
90
('dispval', gobject.TYPE_STRING, gtk.CellRendererText, True,
92
('name', gobject.TYPE_STRING, None, False, None),
93
('value', gobject.TYPE_STRING, None, False, None)]
97
def populate(self, varlist):
101
self.add_item(self.markup(n, v) + [n, v])
103
def markup(self, name, value):
104
MUN = '<span size="small"><b>%s</b></span>'
105
MUV = '<span size="small" foreground="%s">%%s</span>' % self.VAR_COLOR
106
return [(MUN % name), (MUV % value)]
108
class LocalsTree(VarTree):
109
VAR_COLOR = '#0000c0'
111
from cgi import escape
113
class PidaFrame(object):
114
def __init__(self, fn, lineno, name, args, ret, line, locs, globs=None):
125
t = ('<span size="small">%s\n'
126
'%s (%s)\n<b>%s(</b>%s<b>)</b> > %s\n<tt>%s</tt></span>')
127
dirn, filen = os.path.split(self.filename)
129
return t % tuple([escape('%s' % s) for s in [dirn, filen, self.lineno,
130
self.name, ', '.join(self.args),
131
self.ret, self.line]])
133
class FrameViewer(gtk.Label):
134
MU = ('<span size="small">'
136
' (<span color="#0000c0">%s</span>)\n'
137
'%s\n<tt>%s</tt></span>')
139
def refresh_label(self, fr):
141
dn, fn = os.path.split(fr['filename'])
142
mu = self.MU % (fn, fr['line'], dn, fr['so'])
147
class DebugTerminal(base.pidaobject, vte.Terminal):
151
vte.Terminal.__init__(self)
152
font = self.prop_main_registry.terminal.font.value()
153
self.set_font_from_string(font)
154
self.set_size_request(-1, 32)
159
os.kill(self.pid, 15)
162
os.kill(self.pid, 15)
166
def start(self, fn, parentsock, childsock):
168
sn = os.path.join(SCRIPT_DIR, 'debugger.py')
169
c = self.prop_main_registry.commands.python.value()
170
args = ['python', sn, fn, parentsock, childsock]
171
self.pid = self.fork_command(c, args)
175
class DumpWindow(gtkextra.Transient):
177
def populate_widgets(self):
178
sw = gtk.ScrolledWindow()
179
sw.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
180
self.dumpbuf = gtk.TextBuffer()
181
self.dumptag = self.dumpbuf.create_tag(scale=0.8)
182
self.dumptext = gtk.TextView(self.dumpbuf)
183
self.dumptext.set_wrap_mode(gtk.WRAP_CHAR)
184
self.dumptext.set_size_request(-1, 75)
185
self.dumptext.set_editable(False)
186
sw.add(self.dumptext)
187
self.frame.pack_start(sw)
189
def set_text(self, s):
190
self.dumpbuf.set_text(s)
191
start = self.dumpbuf.get_start_iter()
192
end = self.dumpbuf.get_end_iter()
193
self.dumpbuf.apply_tag(self.dumptag, start, end)
196
class Plugin(plugin.Plugin):
197
NAME = 'python_debugger'
199
DICON = 'debug', 'Load current buffer into debugger.'
201
def create_reactor(self):
202
sockdir = self.prop_main_registry.directories.socket.value()
203
self.parentsock = os.path.join(sockdir, 'profiler_parent')
204
self.childsock = os.path.join(sockdir, 'profiler_child')
205
self.reactor = gobjectreactor.Reactor(self, self.parentsock,
208
def populate_widgets(self):
211
self.create_reactor()
212
#self.ipc = gtkextra.IPWindow(self)
213
#self.add_button('debug', self.cb_but_debug, 'start')
214
self.add_button('stop', self.cb_but_stop, 'Stop debugging.')
215
self.add_button('step', self.cb_step, 'step')
216
self.add_button('jump', self.cb_next, 'next')
217
self.add_button('continue', self.cb_continue, 'continue')
218
self.add_button('list', self.cb_but_list, 'Show source code context.')
227
self.stack = StackTree()
228
tb.pack_start(self.stack.win)
229
self.stack.connect_select(self.cb_stack_select)
230
self.stack.connect_activate(self.cb_stack_activate)
231
self.stack.connect_rightclick(self.cb_stack_rclick)
238
brlb.set_markup('<span size="small">Breaks</span>')
239
self.breaks = BreakTree()
240
self.breaks.connect_rightclick(self.cb_breaks_rclick)
241
nb.append_page(self.breaks.win, tab_label=brlb)
244
loclb.set_markup('<span size="small">Locals</span>')
245
self.locs = LocalsTree()
246
self.locs.connect_activate(self.cb_locs_activate)
247
nb.append_page(self.locs.win, tab_label=loclb)
250
gllb.set_markup('<span size="small">Globals</span>')
251
self.globs = VarTree()
252
self.globs.connect_activate(self.cb_globs_activate)
253
nb.append_page(self.globs.win, tab_label=gllb)
255
self.dumpwin = DumpWindow()
256
self.add(self.dumpwin.win, expand=False)
258
self.term = DebugTerminal()
259
self.add(self.term, expand=False)
262
self.menu = gtkextra.PositionPopup('position')
263
self.lfn = tempfile.mktemp('.py', 'pidatmp')
264
self.debugger_loaded = False
266
def do_list(self, s):
267
f = open(self.lfn, 'w')
270
self.do_edit('preview', self.lfn)
272
def do_eval(self, s, *args):
273
com, val = s.split('\n', 1)
274
self.dumpwin.set_text(val)
275
self.dumpwin.show('<span size="small">%s</span>' % com)
277
def do_started(self, *args):
278
self.load_breakpoints()
280
def do_frame(self, fs):
281
self.curindex = fs.pop()
283
def do_stack(self, stacks):
284
stack = pickle.loads(stacks)
285
self.stack.populate([PidaFrame(*fr) for fr in stack], -1)
286
curframe = PidaFrame(*stack[-1])
287
self.do_evt('debuggerframe', curframe)
290
def send(self, command):
292
self.term.feed_child('%s\n' % command)
294
def send_breakpoint(self, fn, line):
295
self.send('break %s:%s' % (fn, line))
297
def send_breakpoint_clear(self, fn, line):
298
self.send('clear %s:%s' % (fn, line))
300
def load_breakpoints(self):
301
for bp in self.breaks.get_list():
302
self.send_breakpoint(*bp)
306
pid = self.term.start(self.fn, self.parentsock, self.childsock)
307
self.debugger_loaded = True
309
def evt_debuggerload(self):
318
def evt_continue(self):
319
self.send('continue')
321
def cb_breaks_rclick(self, ite, time):
322
fn = self.breaks.get(ite, 1)
323
line = self.breaks.get(ite, 2)
324
self.menu.popup(fn, line, time)
326
def cb_stack_rclick(self, ite, time):
327
frame = self.stack.get(ite, 1)
330
self.menu.popup(fn, line, time)
332
def cb_but_debug(self, *args):
335
cb_alternative = cb_but_debug
337
def cb_but_stop(self, *args):
341
def cb_but_list(self, *args):
344
def goto_stack(self):
345
frame = self.stack.selected(1)
349
self.do_edit('openfile', fn)
350
self.do_edit('gotoline', line)
353
def set_breakpoint(self, fn, line):
355
def exists(model, path, ite, exist):
356
if self.breaks.get(ite, 1) == fn:
357
if self.breaks.get(ite, 2) == line:
359
self.breaks.model.foreach(exists, exist)
361
self.breaks.add(fn, line)
362
if self.debugger_loaded:
363
self.send_breakpoint(fn, line)
365
def clear_breakpoint(self, fn, line):
366
def remove(model, path, ite):
367
if self.breaks.get(ite, 1) == fn:
368
if self.breaks.get(ite, 2) == line:
369
self.breaks.model.remove(ite)
370
self.breaks.model.foreach(remove)
371
if self.debugger_loaded:
372
self.send_breakpoint_clear(fn, line)
374
def cb_step(self, *args):
377
def cb_next(self, *args):
380
def cb_continue(self, *args):
381
self.send('continue')
383
def cb_stack_select(self, ite):
384
frame = self.stack.selected(1)
385
self.locs.populate(frame.locs)
386
self.globs.populate(frame.globs)
388
def cb_stack_activate(self, tree, path, col):
391
def cb_locs_activate(self, tree, path, col):
392
v = self.locs.selected(2)
395
def cb_globs_activate(self, tree, path, col):
396
v = self.globs.selected(2)
399
def evt_bufferchange(self, nr, name):
405
def evt_breakpointset(self, line, fn=None):
409
self.set_breakpoint(fn, line)
411
def evt_breakpointclear(self, line, fn=None):
416
self.clear_breakpoint(fn, line)
418
def evt_started(self, *args):