blob: f5646e04904254ca8e6f7bc12a41009784ac5f2b [file] [log] [blame]
David Scherer7aced172000-08-15 01:13:23 +00001import os
2import bdb
Chui Tey5d2af632002-05-26 13:36:41 +00003import types
David Scherer7aced172000-08-15 01:13:23 +00004import traceback
5from Tkinter import *
6from WindowList import ListedToplevel
7
8import StackViewer
9
10
Chui Tey5d2af632002-05-26 13:36:41 +000011class Idb(bdb.Bdb):
12
13 def __init__(self, gui):
14 self.gui = gui
15 bdb.Bdb.__init__(self)
16
17 def user_line(self, frame):
18 # get the currently executing function
19 co_filename = frame.f_code.co_filename
20 co_name = frame.f_code.co_name
21 try:
22 func = frame.f_locals[co_name]
23 if getattr(func, "DebuggerStepThrough", 0):
24 print "XXXX DEBUGGER STEPPING THROUGH"
25 self.set_step()
26 return
27 except:
28 pass
29 if co_filename in ('rpc.py', '<string>'):
30 self.set_step()
31 return
32 if co_filename.endswith('threading.py'):
33 self.set_step()
34 return
35 message = self.__frame2message(frame)
36 self.gui.interaction(message, frame)
37
38 def user_exception(self, frame, info):
39 message = self.__frame2message(frame)
40 self.gui.interaction(message, frame, info)
41
42 def __frame2message(self, frame):
43 code = frame.f_code
44 filename = code.co_filename
45 lineno = frame.f_lineno
46 basename = os.path.basename(filename)
47 message = "%s:%s" % (basename, lineno)
48 if code.co_name != "?":
49 message = "%s: %s()" % (message, code.co_name)
50 return message
51
52
53class Debugger:
David Scherer7aced172000-08-15 01:13:23 +000054
Kurt B. Kaiser0e3a5772002-06-16 03:32:24 +000055 # interacting = 0 # XXX KBK 14Jun02 move to __init__
David Scherer7aced172000-08-15 01:13:23 +000056 vstack = vsource = vlocals = vglobals = None
57
Chui Tey5d2af632002-05-26 13:36:41 +000058 def __init__(self, pyshell, idb=None):
59 if idb is None:
60 idb = Idb(self)
David Scherer7aced172000-08-15 01:13:23 +000061 self.pyshell = pyshell
Chui Tey5d2af632002-05-26 13:36:41 +000062 self.idb = idb
Kurt B. Kaiser0e3a5772002-06-16 03:32:24 +000063 self.frame = None
David Scherer7aced172000-08-15 01:13:23 +000064 self.make_gui()
Kurt B. Kaiser0e3a5772002-06-16 03:32:24 +000065 self.interacting = 0
66
Chui Tey5d2af632002-05-26 13:36:41 +000067 def run(self, *args):
68 try:
69 self.interacting = 1
70 return self.idb.run(*args)
71 finally:
72 self.interacting = 0
David Scherer7aced172000-08-15 01:13:23 +000073
74 def close(self, event=None):
75 if self.interacting:
76 self.top.bell()
77 return
78 if self.stackviewer:
79 self.stackviewer.close(); self.stackviewer = None
80 self.pyshell.close_debugger()
81 self.top.destroy()
82
David Scherer7aced172000-08-15 01:13:23 +000083 def make_gui(self):
84 pyshell = self.pyshell
85 self.flist = pyshell.flist
86 self.root = root = pyshell.root
87 self.top = top =ListedToplevel(root)
88 self.top.wm_title("Debug Control")
89 self.top.wm_iconname("Debug")
90 top.wm_protocol("WM_DELETE_WINDOW", self.close)
91 self.top.bind("<Escape>", self.close)
92 #
93 self.bframe = bframe = Frame(top)
94 self.bframe.pack(anchor="w")
95 self.buttons = bl = []
96 #
97 self.bcont = b = Button(bframe, text="Go", command=self.cont)
98 bl.append(b)
99 self.bstep = b = Button(bframe, text="Step", command=self.step)
100 bl.append(b)
101 self.bnext = b = Button(bframe, text="Over", command=self.next)
102 bl.append(b)
103 self.bret = b = Button(bframe, text="Out", command=self.ret)
104 bl.append(b)
105 self.bret = b = Button(bframe, text="Quit", command=self.quit)
106 bl.append(b)
107 #
108 for b in bl:
109 b.configure(state="disabled")
110 b.pack(side="left")
111 #
112 self.cframe = cframe = Frame(bframe)
113 self.cframe.pack(side="left")
114 #
115 if not self.vstack:
116 self.__class__.vstack = BooleanVar(top)
117 self.vstack.set(1)
118 self.bstack = Checkbutton(cframe,
119 text="Stack", command=self.show_stack, variable=self.vstack)
120 self.bstack.grid(row=0, column=0)
121 if not self.vsource:
122 self.__class__.vsource = BooleanVar(top)
123 ##self.vsource.set(1)
124 self.bsource = Checkbutton(cframe,
125 text="Source", command=self.show_source, variable=self.vsource)
126 self.bsource.grid(row=0, column=1)
127 if not self.vlocals:
128 self.__class__.vlocals = BooleanVar(top)
129 self.vlocals.set(1)
130 self.blocals = Checkbutton(cframe,
131 text="Locals", command=self.show_locals, variable=self.vlocals)
132 self.blocals.grid(row=1, column=0)
133 if not self.vglobals:
134 self.__class__.vglobals = BooleanVar(top)
135 ##self.vglobals.set(1)
136 self.bglobals = Checkbutton(cframe,
137 text="Globals", command=self.show_globals, variable=self.vglobals)
138 self.bglobals.grid(row=1, column=1)
139 #
140 self.status = Label(top, anchor="w")
141 self.status.pack(anchor="w")
142 self.error = Label(top, anchor="w")
143 self.error.pack(anchor="w", fill="x")
144 self.errorbg = self.error.cget("background")
145 #
146 self.fstack = Frame(top, height=1)
147 self.fstack.pack(expand=1, fill="both")
148 self.flocals = Frame(top)
149 self.flocals.pack(expand=1, fill="both")
150 self.fglobals = Frame(top, height=1)
151 self.fglobals.pack(expand=1, fill="both")
152 #
153 if self.vstack.get():
154 self.show_stack()
155 if self.vlocals.get():
156 self.show_locals()
157 if self.vglobals.get():
158 self.show_globals()
159
Kurt B. Kaiser0e3a5772002-06-16 03:32:24 +0000160 # frame = None # XXX KBK 14Jun02 Move to __init__
David Scherer7aced172000-08-15 01:13:23 +0000161
Chui Tey5d2af632002-05-26 13:36:41 +0000162 def interaction(self, message, frame, info=None):
David Scherer7aced172000-08-15 01:13:23 +0000163 self.frame = frame
David Scherer7aced172000-08-15 01:13:23 +0000164 self.status.configure(text=message)
165 #
166 if info:
167 type, value, tb = info
168 try:
169 m1 = type.__name__
170 except AttributeError:
171 m1 = "%s" % str(type)
172 if value is not None:
173 try:
174 m1 = "%s: %s" % (m1, str(value))
175 except:
176 pass
177 bg = "yellow"
178 else:
179 m1 = ""
180 tb = None
181 bg = self.errorbg
182 self.error.configure(text=m1, background=bg)
183 #
184 sv = self.stackviewer
185 if sv:
Chui Tey5d2af632002-05-26 13:36:41 +0000186 stack, i = self.idb.get_stack(self.frame, tb)
David Scherer7aced172000-08-15 01:13:23 +0000187 sv.load_stack(stack, i)
188 #
189 self.show_variables(1)
190 #
191 if self.vsource.get():
192 self.sync_source_line()
193 #
194 for b in self.buttons:
195 b.configure(state="normal")
196 #
197 self.top.tkraise()
198 self.root.mainloop()
199 #
200 for b in self.buttons:
201 b.configure(state="disabled")
202 self.status.configure(text="")
203 self.error.configure(text="", background=self.errorbg)
204 self.frame = None
205
206 def sync_source_line(self):
207 frame = self.frame
208 if not frame:
209 return
Chui Tey5d2af632002-05-26 13:36:41 +0000210 filename, lineno = self.__frame2fileline(frame)
211 if filename[:1] + filename[-1:] != "<>" and os.path.exists(filename):
212 self.flist.gotofileline(filename, lineno)
213
214 def __frame2fileline(self, frame):
David Scherer7aced172000-08-15 01:13:23 +0000215 code = frame.f_code
Chui Tey5d2af632002-05-26 13:36:41 +0000216 filename = code.co_filename
David Scherer7aced172000-08-15 01:13:23 +0000217 lineno = frame.f_lineno
Chui Tey5d2af632002-05-26 13:36:41 +0000218 return filename, lineno
David Scherer7aced172000-08-15 01:13:23 +0000219
220 def cont(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000221 self.idb.set_continue()
David Scherer7aced172000-08-15 01:13:23 +0000222 self.root.quit()
223
224 def step(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000225 self.idb.set_step()
David Scherer7aced172000-08-15 01:13:23 +0000226 self.root.quit()
227
228 def next(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000229 self.idb.set_next(self.frame)
David Scherer7aced172000-08-15 01:13:23 +0000230 self.root.quit()
231
232 def ret(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000233 self.idb.set_return(self.frame)
David Scherer7aced172000-08-15 01:13:23 +0000234 self.root.quit()
235
236 def quit(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000237 self.idb.set_quit()
David Scherer7aced172000-08-15 01:13:23 +0000238 self.root.quit()
239
240 stackviewer = None
241
242 def show_stack(self):
243 if not self.stackviewer and self.vstack.get():
244 self.stackviewer = sv = StackViewer.StackViewer(
245 self.fstack, self.flist, self)
246 if self.frame:
Chui Tey5d2af632002-05-26 13:36:41 +0000247 stack, i = self.idb.get_stack(self.frame, None)
David Scherer7aced172000-08-15 01:13:23 +0000248 sv.load_stack(stack, i)
249 else:
250 sv = self.stackviewer
251 if sv and not self.vstack.get():
252 self.stackviewer = None
253 sv.close()
254 self.fstack['height'] = 1
255
256 def show_source(self):
257 if self.vsource.get():
258 self.sync_source_line()
259
260 def show_frame(self, (frame, lineno)):
Chui Tey5d2af632002-05-26 13:36:41 +0000261 # Called from OldStackViewer
David Scherer7aced172000-08-15 01:13:23 +0000262 self.frame = frame
263 self.show_variables()
264
265 localsviewer = None
266 globalsviewer = None
267
268 def show_locals(self):
269 lv = self.localsviewer
270 if self.vlocals.get():
271 if not lv:
272 self.localsviewer = StackViewer.NamespaceViewer(
273 self.flocals, "Locals")
274 else:
275 if lv:
276 self.localsviewer = None
277 lv.close()
278 self.flocals['height'] = 1
279 self.show_variables()
280
281 def show_globals(self):
282 gv = self.globalsviewer
283 if self.vglobals.get():
284 if not gv:
285 self.globalsviewer = StackViewer.NamespaceViewer(
286 self.fglobals, "Globals")
287 else:
288 if gv:
289 self.globalsviewer = None
290 gv.close()
291 self.fglobals['height'] = 1
292 self.show_variables()
293
294 def show_variables(self, force=0):
295 lv = self.localsviewer
296 gv = self.globalsviewer
297 frame = self.frame
298 if not frame:
299 ldict = gdict = None
300 else:
301 ldict = frame.f_locals
302 gdict = frame.f_globals
303 if lv and gv and ldict is gdict:
304 ldict = None
Kurt B. Kaiser0e3a5772002-06-16 03:32:24 +0000305 # Calls OldStackviewer.NamespaceViewer.load_dict():
David Scherer7aced172000-08-15 01:13:23 +0000306 if lv:
Kurt B. Kaiser0e3a5772002-06-16 03:32:24 +0000307 lv.load_dict(ldict, force, self.pyshell.interp.rpcclt)
David Scherer7aced172000-08-15 01:13:23 +0000308 if gv:
Kurt B. Kaiser0e3a5772002-06-16 03:32:24 +0000309 gv.load_dict(gdict, force, self.pyshell.interp.rpcclt)
David Scherer7aced172000-08-15 01:13:23 +0000310
311 def set_breakpoint_here(self, edit):
312 text = edit.text
313 filename = edit.io.filename
314 if not filename:
315 text.bell()
316 return
317 lineno = int(float(text.index("insert")))
Kurt B. Kaiser0e3a5772002-06-16 03:32:24 +0000318 msg = self.idb.set_break(filename, lineno)
David Scherer7aced172000-08-15 01:13:23 +0000319 if msg:
320 text.bell()
321 return
322 text.tag_add("BREAK", "insert linestart", "insert lineend +1char")
323
324 # A literal copy of Bdb.set_break() without the print statement at the end
Chui Tey5d2af632002-05-26 13:36:41 +0000325 #def set_break(self, filename, lineno, temporary=0, cond = None):
326 # import linecache # Import as late as possible
327 # filename = self.canonic(filename)
328 # line = linecache.getline(filename, lineno)
329 # if not line:
330 # return 'That line does not exist!'
331 # if not self.breaks.has_key(filename):
332 # self.breaks[filename] = []
333 # list = self.breaks[filename]
334 # if not lineno in list:
335 # list.append(lineno)
336 # bp = bdb.Breakpoint(filename, lineno, temporary, cond)