~ubuntu-branches/ubuntu/saucy/pida/saucy

« back to all changes in this revision

Viewing changes to src/plugins/python_debugger/plugin.py

  • Committer: Bazaar Package Importer
  • Author(s): Ante Karamatic
  • Date: 2005-09-27 10:19:38 UTC
  • Revision ID: james.westby@ubuntu.com-20050927101938-o7ak8uqyuvewfuw8
Tags: upstream-0.2.2
ImportĀ upstreamĀ versionĀ 0.2.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 $
 
4
 
 
5
 
 
6
import pida.plugin as plugin
 
7
import gtk
 
8
import os
 
9
import pickle
 
10
#import tree
 
11
import gobject
 
12
import tempfile
 
13
import pida.base as base
 
14
import pida.gtkextra as gtkextra
 
15
import pida.gobjectreactor as gobjectreactor
 
16
import linecache
 
17
import marshal
 
18
import cStringIO
 
19
 
 
20
def script_directory():
 
21
    def f(): pass
 
22
    d, f = os.path.split(f.func_code.co_filename)
 
23
    return d
 
24
 
 
25
SCRIPT_DIR = script_directory()
 
26
 
 
27
class StackTree(gtkextra.Tree):
 
28
    COLUMNS = [('display', gobject.TYPE_STRING, gtk.CellRendererText, True,
 
29
                'markup'),
 
30
               ('frame', gobject.TYPE_PYOBJECT, None, False, None)]
 
31
 
 
32
    #def init(self):
 
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')
 
40
 
 
41
 
 
42
    def populate(self, stack, curindex):
 
43
        self.clear()
 
44
        last = None
 
45
        for fr in stack:
 
46
            if not fr.filename.count('bdb.py') and fr.filename != '<string>':
 
47
                last = self.add_item([fr.markup(), fr])
 
48
        if last:
 
49
            path = self.model.get_path(last)
 
50
            self.view.set_cursor(path)
 
51
 
 
52
class BreakTree(gtkextra.Tree):
 
53
    COLUMNS = [('display', gobject.TYPE_STRING, gtk.CellRendererText, True,
 
54
                'markup'),
 
55
               ('filename', gobject.TYPE_STRING, None, False, None),
 
56
               ('line', gobject.TYPE_STRING, None, False, None)]
 
57
 
 
58
    #def init(self):
 
59
    #    self.title = gtk.Label()
 
60
    #    self.toolbar.pack_start(self.title)
 
61
    #    self.refresh_label()
 
62
 
 
63
    def refresh_label(self):
 
64
        self.title.set_markup('Breakpoints')
 
65
 
 
66
    def add(self, filename, line):
 
67
        mu = self.markup(filename, line)
 
68
        self.add_item([mu, filename, line])
 
69
 
 
70
    def get_list(self):
 
71
        for row in self.model:
 
72
            # not allowed to slice row sequences
 
73
            yield [row[1], row[2]]
 
74
 
 
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'
 
79
              '%s</span>')
 
80
        return MU % (fn, line, dn)
 
81
 
 
82
def bframe(frame):
 
83
    c = frame.f_code
 
84
    return '%s %s %s %s %s' % (c.co_name,
 
85
        c.co_argcount, c.co_names, c.co_filename, c.co_firstlineno)
 
86
 
 
87
class VarTree(gtkextra.Tree):
 
88
    COLUMNS = [('display', gobject.TYPE_STRING, gtk.CellRendererText, True,
 
89
                'markup'),
 
90
               ('dispval', gobject.TYPE_STRING, gtk.CellRendererText, True,
 
91
                'markup'),
 
92
               ('name', gobject.TYPE_STRING, None, False, None),
 
93
               ('value', gobject.TYPE_STRING, None, False, None)]
 
94
    
 
95
    VAR_COLOR = '#c00000'
 
96
    
 
97
    def populate(self, varlist):
 
98
        self.clear()
 
99
        varlist.sort()
 
100
        for n, v in varlist:
 
101
            self.add_item(self.markup(n, v) + [n, v])
 
102
 
 
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)]
 
107
 
 
108
class LocalsTree(VarTree):
 
109
    VAR_COLOR = '#0000c0'
 
110
 
 
111
from cgi import escape
 
112
 
 
113
class PidaFrame(object):
 
114
    def __init__(self, fn, lineno, name, args, ret, line, locs, globs=None):
 
115
        self.filename = fn
 
116
        self.lineno = lineno
 
117
        self.name = name
 
118
        self.args = args
 
119
        self.line = line
 
120
        self.ret = ret
 
121
        self.locs = locs
 
122
        self.globs = globs
 
123
 
 
124
    def markup(self):
 
125
        t = ('<span size="small">%s\n'
 
126
            '%s (%s)\n<b>%s(</b>%s<b>)</b> &gt; %s\n<tt>%s</tt></span>')
 
127
        dirn, filen = os.path.split(self.filename)
 
128
        
 
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]])
 
132
 
 
133
class FrameViewer(gtk.Label):
 
134
    MU = ('<span size="small">'
 
135
               '<b>%s</b>'
 
136
               ' (<span color="#0000c0">%s</span>)\n'
 
137
               '%s\n<tt>%s</tt></span>')
 
138
 
 
139
    def refresh_label(self, fr):
 
140
        return
 
141
        dn, fn = os.path.split(fr['filename'])
 
142
        mu = self.MU % (fn, fr['line'], dn, fr['so'])
 
143
        self.set_markup(mu)
 
144
 
 
145
import vte
 
146
 
 
147
class DebugTerminal(base.pidaobject, vte.Terminal):
 
148
 
 
149
    def do_init(self):
 
150
        self.pid = None
 
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)
 
155
 
 
156
    def kill(self):
 
157
        if self.pid:
 
158
            try:
 
159
                os.kill(self.pid, 15)
 
160
            except OSError:
 
161
                try:
 
162
                    os.kill(self.pid, 15)
 
163
                except OSError:
 
164
                    pass
 
165
 
 
166
    def start(self, fn, parentsock, childsock):
 
167
        self.kill()
 
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)
 
172
        self.grab_focus()
 
173
        return self.pid
 
174
 
 
175
class DumpWindow(gtkextra.Transient):
 
176
 
 
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)
 
188
 
 
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)
 
194
        
 
195
 
 
196
class Plugin(plugin.Plugin):
 
197
    NAME = 'python_debugger'
 
198
    ICON = 'debug'
 
199
    DICON = 'debug', 'Load current buffer into debugger.'
 
200
 
 
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,
 
206
                                              self.childsock)
 
207
 
 
208
    def populate_widgets(self):
 
209
        self._dbg = None
 
210
        
 
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.')
 
219
 
 
220
        vp = gtk.VPaned()
 
221
        self.add(vp)
 
222
        
 
223
        tb = gtk.VBox()
 
224
        vp.pack1(tb)
 
225
 
 
226
 
 
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)
 
232
 
 
233
 
 
234
        nb = gtk.Notebook()
 
235
        vp.pack2(nb)
 
236
 
 
237
        brlb = gtk.Label()
 
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)
 
242
 
 
243
        loclb = gtk.Label()
 
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)
 
248
 
 
249
        gllb = gtk.Label()
 
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)
 
254
 
 
255
        self.dumpwin = DumpWindow()
 
256
        self.add(self.dumpwin.win, expand=False)
 
257
 
 
258
        self.term = DebugTerminal()
 
259
        self.add(self.term, expand=False)
 
260
 
 
261
        self.curindex = 0
 
262
        self.menu = gtkextra.PositionPopup('position')
 
263
        self.lfn = tempfile.mktemp('.py', 'pidatmp')
 
264
        self.debugger_loaded = False
 
265
 
 
266
    def do_list(self, s):
 
267
        f = open(self.lfn, 'w')
 
268
        f.write(s)
 
269
        f.close()
 
270
        self.do_edit('preview', self.lfn)
 
271
 
 
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)
 
276
 
 
277
    def do_started(self, *args):
 
278
        self.load_breakpoints()
 
279
 
 
280
    def do_frame(self, fs):
 
281
        self.curindex = fs.pop()
 
282
        
 
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)
 
288
        
 
289
 
 
290
    def send(self, command):
 
291
        if self.term.pid:
 
292
            self.term.feed_child('%s\n' % command)
 
293
 
 
294
    def send_breakpoint(self, fn, line):
 
295
        self.send('break %s:%s' % (fn, line))
 
296
 
 
297
    def send_breakpoint_clear(self, fn, line):
 
298
        self.send('clear %s:%s' % (fn, line))
 
299
 
 
300
    def load_breakpoints(self):
 
301
        for bp in self.breaks.get_list():
 
302
            self.send_breakpoint(*bp)
 
303
 
 
304
    def load(self):
 
305
        self.reactor.start()
 
306
        pid = self.term.start(self.fn, self.parentsock, self.childsock)
 
307
        self.debugger_loaded = True
 
308
        
 
309
    def evt_debuggerload(self):
 
310
        self.load()
 
311
        
 
312
    def evt_step(self):
 
313
        self.send('step')
 
314
        
 
315
    def evt_next(self):
 
316
        self.send('next')
 
317
        
 
318
    def evt_continue(self):
 
319
        self.send('continue')
 
320
        
 
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)
 
325
 
 
326
    def cb_stack_rclick(self, ite, time):
 
327
        frame = self.stack.get(ite, 1)
 
328
        fn = frame.filename
 
329
        line = frame.lineno
 
330
        self.menu.popup(fn, line, time)
 
331
 
 
332
    def cb_but_debug(self, *args):
 
333
        self.load()
 
334
 
 
335
    cb_alternative = cb_but_debug
 
336
 
 
337
    def cb_but_stop(self, *args):
 
338
        self.send('quit')
 
339
        self.term.kill()
 
340
 
 
341
    def cb_but_list(self, *args):
 
342
        self.goto_stack()
 
343
        
 
344
    def goto_stack(self):
 
345
        frame = self.stack.selected(1)
 
346
        fn = frame.filename
 
347
        line = frame.lineno
 
348
        if fn != self.fn:
 
349
            self.do_edit('openfile', fn)
 
350
        self.do_edit('gotoline', line)
 
351
        #self.send('list')
 
352
 
 
353
    def set_breakpoint(self, fn, line):
 
354
        exist = []
 
355
        def exists(model, path, ite, exist):
 
356
            if self.breaks.get(ite, 1) == fn:
 
357
                if self.breaks.get(ite, 2) == line:
 
358
                    exist.append(True)
 
359
        self.breaks.model.foreach(exists, exist)
 
360
        if not exist:
 
361
            self.breaks.add(fn, line)
 
362
            if self.debugger_loaded:
 
363
                self.send_breakpoint(fn, line)
 
364
 
 
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)
 
373
 
 
374
    def cb_step(self, *args):
 
375
        self.send('step')
 
376
 
 
377
    def cb_next(self, *args):
 
378
        self.send('next')
 
379
 
 
380
    def cb_continue(self, *args):
 
381
        self.send('continue')
 
382
 
 
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)
 
387
 
 
388
    def cb_stack_activate(self, tree, path, col):
 
389
        self.goto_stack()
 
390
 
 
391
    def cb_locs_activate(self, tree, path, col):
 
392
        v = self.locs.selected(2)
 
393
        self.send(v)
 
394
 
 
395
    def cb_globs_activate(self, tree, path, col):
 
396
        v = self.globs.selected(2)
 
397
        self.send(v)
 
398
 
 
399
    def evt_bufferchange(self, nr, name):
 
400
        self.fn = name
 
401
 
 
402
    def evt_die(self):
 
403
        self.term.kill()
 
404
 
 
405
    def evt_breakpointset(self, line, fn=None):
 
406
        if not fn:
 
407
            fn = self.fn
 
408
        if fn:
 
409
            self.set_breakpoint(fn, line)
 
410
 
 
411
    def evt_breakpointclear(self, line, fn=None):
 
412
        line = '%s' % line
 
413
        if not fn:
 
414
            fn = self.fn
 
415
        if fn:
 
416
            self.clear_breakpoint(fn, line)
 
417
 
 
418
    def evt_started(self, *args):
 
419
        self.dumpwin.hide()
 
420
 
 
421