PyXR

c:\python24\lib \ idlelib \ Debugger.py



0001 import os
0002 import bdb
0003 import types
0004 from Tkinter import *
0005 from WindowList import ListedToplevel
0006 from ScrolledList import ScrolledList
0007 
0008 
0009 class Idb(bdb.Bdb):
0010 
0011     def __init__(self, gui):
0012         self.gui = gui
0013         bdb.Bdb.__init__(self)
0014 
0015     def user_line(self, frame):
0016         if self.in_rpc_code(frame):
0017             self.set_step()
0018             return
0019         message = self.__frame2message(frame)
0020         self.gui.interaction(message, frame)
0021 
0022     def user_exception(self, frame, info):
0023         if self.in_rpc_code(frame):
0024             self.set_step()
0025             return
0026         message = self.__frame2message(frame)
0027         self.gui.interaction(message, frame, info)
0028 
0029     def in_rpc_code(self, frame):
0030         if frame.f_code.co_filename.count('rpc.py'):
0031             return True
0032         else:
0033             prev_frame = frame.f_back
0034             if prev_frame.f_code.co_filename.count('Debugger.py'):
0035                 # (that test will catch both Debugger.py and RemoteDebugger.py)
0036                 return False
0037             return self.in_rpc_code(prev_frame)
0038 
0039     def __frame2message(self, frame):
0040         code = frame.f_code
0041         filename = code.co_filename
0042         lineno = frame.f_lineno
0043         basename = os.path.basename(filename)
0044         message = "%s:%s" % (basename, lineno)
0045         if code.co_name != "?":
0046             message = "%s: %s()" % (message, code.co_name)
0047         return message
0048 
0049 
0050 class Debugger:
0051 
0052     vstack = vsource = vlocals = vglobals = None
0053 
0054     def __init__(self, pyshell, idb=None):
0055         if idb is None:
0056             idb = Idb(self)
0057         self.pyshell = pyshell
0058         self.idb = idb
0059         self.frame = None
0060         self.make_gui()
0061         self.interacting = 0
0062 
0063     def run(self, *args):
0064         try:
0065             self.interacting = 1
0066             return self.idb.run(*args)
0067         finally:
0068             self.interacting = 0
0069 
0070     def close(self, event=None):
0071         if self.interacting:
0072             self.top.bell()
0073             return
0074         if self.stackviewer:
0075             self.stackviewer.close(); self.stackviewer = None
0076         # Clean up pyshell if user clicked debugger control close widget.
0077         # (Causes a harmless extra cycle through close_debugger() if user
0078         # toggled debugger from pyshell Debug menu)
0079         self.pyshell.close_debugger()
0080         # Now close the debugger control window....
0081         self.top.destroy()
0082 
0083     def make_gui(self):
0084         pyshell = self.pyshell
0085         self.flist = pyshell.flist
0086         self.root = root = pyshell.root
0087         self.top = top = ListedToplevel(root)
0088         self.top.wm_title("Debug Control")
0089         self.top.wm_iconname("Debug")
0090         top.wm_protocol("WM_DELETE_WINDOW", self.close)
0091         self.top.bind("<Escape>", self.close)
0092         #
0093         self.bframe = bframe = Frame(top)
0094         self.bframe.pack(anchor="w")
0095         self.buttons = bl = []
0096         #
0097         self.bcont = b = Button(bframe, text="Go", command=self.cont)
0098         bl.append(b)
0099         self.bstep = b = Button(bframe, text="Step", command=self.step)
0100         bl.append(b)
0101         self.bnext = b = Button(bframe, text="Over", command=self.next)
0102         bl.append(b)
0103         self.bret = b = Button(bframe, text="Out", command=self.ret)
0104         bl.append(b)
0105         self.bret = b = Button(bframe, text="Quit", command=self.quit)
0106         bl.append(b)
0107         #
0108         for b in bl:
0109             b.configure(state="disabled")
0110             b.pack(side="left")
0111         #
0112         self.cframe = cframe = Frame(bframe)
0113         self.cframe.pack(side="left")
0114         #
0115         if not self.vstack:
0116             self.__class__.vstack = BooleanVar(top)
0117             self.vstack.set(1)
0118         self.bstack = Checkbutton(cframe,
0119             text="Stack", command=self.show_stack, variable=self.vstack)
0120         self.bstack.grid(row=0, column=0)
0121         if not self.vsource:
0122             self.__class__.vsource = BooleanVar(top)
0123         self.bsource = Checkbutton(cframe,
0124             text="Source", command=self.show_source, variable=self.vsource)
0125         self.bsource.grid(row=0, column=1)
0126         if not self.vlocals:
0127             self.__class__.vlocals = BooleanVar(top)
0128             self.vlocals.set(1)
0129         self.blocals = Checkbutton(cframe,
0130             text="Locals", command=self.show_locals, variable=self.vlocals)
0131         self.blocals.grid(row=1, column=0)
0132         if not self.vglobals:
0133             self.__class__.vglobals = BooleanVar(top)
0134         self.bglobals = Checkbutton(cframe,
0135             text="Globals", command=self.show_globals, variable=self.vglobals)
0136         self.bglobals.grid(row=1, column=1)
0137         #
0138         self.status = Label(top, anchor="w")
0139         self.status.pack(anchor="w")
0140         self.error = Label(top, anchor="w")
0141         self.error.pack(anchor="w", fill="x")
0142         self.errorbg = self.error.cget("background")
0143         #
0144         self.fstack = Frame(top, height=1)
0145         self.fstack.pack(expand=1, fill="both")
0146         self.flocals = Frame(top)
0147         self.flocals.pack(expand=1, fill="both")
0148         self.fglobals = Frame(top, height=1)
0149         self.fglobals.pack(expand=1, fill="both")
0150         #
0151         if self.vstack.get():
0152             self.show_stack()
0153         if self.vlocals.get():
0154             self.show_locals()
0155         if self.vglobals.get():
0156             self.show_globals()
0157 
0158     def interaction(self, message, frame, info=None):
0159         self.frame = frame
0160         self.status.configure(text=message)
0161         #
0162         if info:
0163             type, value, tb = info
0164             try:
0165                 m1 = type.__name__
0166             except AttributeError:
0167                 m1 = "%s" % str(type)
0168             if value is not None:
0169                 try:
0170                     m1 = "%s: %s" % (m1, str(value))
0171                 except:
0172                     pass
0173             bg = "yellow"
0174         else:
0175             m1 = ""
0176             tb = None
0177             bg = self.errorbg
0178         self.error.configure(text=m1, background=bg)
0179         #
0180         sv = self.stackviewer
0181         if sv:
0182             stack, i = self.idb.get_stack(self.frame, tb)
0183             sv.load_stack(stack, i)
0184         #
0185         self.show_variables(1)
0186         #
0187         if self.vsource.get():
0188             self.sync_source_line()
0189         #
0190         for b in self.buttons:
0191             b.configure(state="normal")
0192         #
0193         self.top.wakeup()
0194         self.root.mainloop()
0195         #
0196         for b in self.buttons:
0197             b.configure(state="disabled")
0198         self.status.configure(text="")
0199         self.error.configure(text="", background=self.errorbg)
0200         self.frame = None
0201 
0202     def sync_source_line(self):
0203         frame = self.frame
0204         if not frame:
0205             return
0206         filename, lineno = self.__frame2fileline(frame)
0207         if filename[:1] + filename[-1:] != "<>" and os.path.exists(filename):
0208             self.flist.gotofileline(filename, lineno)
0209 
0210     def __frame2fileline(self, frame):
0211         code = frame.f_code
0212         filename = code.co_filename
0213         lineno = frame.f_lineno
0214         return filename, lineno
0215 
0216     def cont(self):
0217         self.idb.set_continue()
0218         self.root.quit()
0219 
0220     def step(self):
0221         self.idb.set_step()
0222         self.root.quit()
0223 
0224     def next(self):
0225         self.idb.set_next(self.frame)
0226         self.root.quit()
0227 
0228     def ret(self):
0229         self.idb.set_return(self.frame)
0230         self.root.quit()
0231 
0232     def quit(self):
0233         self.idb.set_quit()
0234         self.root.quit()
0235 
0236     stackviewer = None
0237 
0238     def show_stack(self):
0239         if not self.stackviewer and self.vstack.get():
0240             self.stackviewer = sv = StackViewer(self.fstack, self.flist, self)
0241             if self.frame:
0242                 stack, i = self.idb.get_stack(self.frame, None)
0243                 sv.load_stack(stack, i)
0244         else:
0245             sv = self.stackviewer
0246             if sv and not self.vstack.get():
0247                 self.stackviewer = None
0248                 sv.close()
0249             self.fstack['height'] = 1
0250 
0251     def show_source(self):
0252         if self.vsource.get():
0253             self.sync_source_line()
0254 
0255     def show_frame(self, (frame, lineno)):
0256         self.frame = frame
0257         self.show_variables()
0258 
0259     localsviewer = None
0260     globalsviewer = None
0261 
0262     def show_locals(self):
0263         lv = self.localsviewer
0264         if self.vlocals.get():
0265             if not lv:
0266                 self.localsviewer = NamespaceViewer(self.flocals, "Locals")
0267         else:
0268             if lv:
0269                 self.localsviewer = None
0270                 lv.close()
0271                 self.flocals['height'] = 1
0272         self.show_variables()
0273 
0274     def show_globals(self):
0275         gv = self.globalsviewer
0276         if self.vglobals.get():
0277             if not gv:
0278                 self.globalsviewer = NamespaceViewer(self.fglobals, "Globals")
0279         else:
0280             if gv:
0281                 self.globalsviewer = None
0282                 gv.close()
0283                 self.fglobals['height'] = 1
0284         self.show_variables()
0285 
0286     def show_variables(self, force=0):
0287         lv = self.localsviewer
0288         gv = self.globalsviewer
0289         frame = self.frame
0290         if not frame:
0291             ldict = gdict = None
0292         else:
0293             ldict = frame.f_locals
0294             gdict = frame.f_globals
0295             if lv and gv and ldict is gdict:
0296                 ldict = None
0297         if lv:
0298             lv.load_dict(ldict, force, self.pyshell.interp.rpcclt)
0299         if gv:
0300             gv.load_dict(gdict, force, self.pyshell.interp.rpcclt)
0301 
0302     def set_breakpoint_here(self, filename, lineno):
0303         self.idb.set_break(filename, lineno)
0304 
0305     def clear_breakpoint_here(self, filename, lineno):
0306         self.idb.clear_break(filename, lineno)
0307 
0308     def clear_file_breaks(self, filename):
0309         self.idb.clear_all_file_breaks(filename)
0310 
0311     def load_breakpoints(self):
0312         "Load PyShellEditorWindow breakpoints into subprocess debugger"
0313         pyshell_edit_windows = self.pyshell.flist.inversedict.keys()
0314         for editwin in pyshell_edit_windows:
0315             filename = editwin.io.filename
0316             try:
0317                 for lineno in editwin.breakpoints:
0318                     self.set_breakpoint_here(filename, lineno)
0319             except AttributeError:
0320                 continue
0321 
0322 class StackViewer(ScrolledList):
0323 
0324     def __init__(self, master, flist, gui):
0325         ScrolledList.__init__(self, master, width=80)
0326         self.flist = flist
0327         self.gui = gui
0328         self.stack = []
0329 
0330     def load_stack(self, stack, index=None):
0331         self.stack = stack
0332         self.clear()
0333         for i in range(len(stack)):
0334             frame, lineno = stack[i]
0335             try:
0336                 modname = frame.f_globals["__name__"]
0337             except:
0338                 modname = "?"
0339             code = frame.f_code
0340             filename = code.co_filename
0341             funcname = code.co_name
0342             import linecache
0343             sourceline = linecache.getline(filename, lineno)
0344             import string
0345             sourceline = string.strip(sourceline)
0346             if funcname in ("?", "", None):
0347                 item = "%s, line %d: %s" % (modname, lineno, sourceline)
0348             else:
0349                 item = "%s.%s(), line %d: %s" % (modname, funcname,
0350                                                  lineno, sourceline)
0351             if i == index:
0352                 item = "> " + item
0353             self.append(item)
0354         if index is not None:
0355             self.select(index)
0356 
0357     def popup_event(self, event):
0358         "override base method"
0359         if self.stack:
0360             return ScrolledList.popup_event(self, event)
0361 
0362     def fill_menu(self):
0363         "override base method"
0364         menu = self.menu
0365         menu.add_command(label="Go to source line",
0366                          command=self.goto_source_line)
0367         menu.add_command(label="Show stack frame",
0368                          command=self.show_stack_frame)
0369 
0370     def on_select(self, index):
0371         "override base method"
0372         if 0 <= index < len(self.stack):
0373             self.gui.show_frame(self.stack[index])
0374 
0375     def on_double(self, index):
0376         "override base method"
0377         self.show_source(index)
0378 
0379     def goto_source_line(self):
0380         index = self.listbox.index("active")
0381         self.show_source(index)
0382 
0383     def show_stack_frame(self):
0384         index = self.listbox.index("active")
0385         if 0 <= index < len(self.stack):
0386             self.gui.show_frame(self.stack[index])
0387 
0388     def show_source(self, index):
0389         if not (0 <= index < len(self.stack)):
0390             return
0391         frame, lineno = self.stack[index]
0392         code = frame.f_code
0393         filename = code.co_filename
0394         if os.path.isfile(filename):
0395             edit = self.flist.open(filename)
0396             if edit:
0397                 edit.gotoline(lineno)
0398 
0399 
0400 class NamespaceViewer:
0401 
0402     def __init__(self, master, title, dict=None):
0403         width = 0
0404         height = 40
0405         if dict:
0406             height = 20*len(dict) # XXX 20 == observed height of Entry widget
0407         self.master = master
0408         self.title = title
0409         import repr
0410         self.repr = repr.Repr()
0411         self.repr.maxstring = 60
0412         self.repr.maxother = 60
0413         self.frame = frame = Frame(master)
0414         self.frame.pack(expand=1, fill="both")
0415         self.label = Label(frame, text=title, borderwidth=2, relief="groove")
0416         self.label.pack(fill="x")
0417         self.vbar = vbar = Scrollbar(frame, name="vbar")
0418         vbar.pack(side="right", fill="y")
0419         self.canvas = canvas = Canvas(frame,
0420                                       height=min(300, max(40, height)),
0421                                       scrollregion=(0, 0, width, height))
0422         canvas.pack(side="left", fill="both", expand=1)
0423         vbar["command"] = canvas.yview
0424         canvas["yscrollcommand"] = vbar.set
0425         self.subframe = subframe = Frame(canvas)
0426         self.sfid = canvas.create_window(0, 0, window=subframe, anchor="nw")
0427         self.load_dict(dict)
0428 
0429     dict = -1
0430 
0431     def load_dict(self, dict, force=0, rpc_client=None):
0432         if dict is self.dict and not force:
0433             return
0434         subframe = self.subframe
0435         frame = self.frame
0436         for c in subframe.children.values():
0437             c.destroy()
0438         self.dict = None
0439         if not dict:
0440             l = Label(subframe, text="None")
0441             l.grid(row=0, column=0)
0442         else:
0443             names = dict.keys()
0444             names.sort()
0445             row = 0
0446             for name in names:
0447                 value = dict[name]
0448                 svalue = self.repr.repr(value) # repr(value)
0449                 # Strip extra quotes caused by calling repr on the (already)
0450                 # repr'd value sent across the RPC interface:
0451                 if rpc_client:
0452                     svalue = svalue[1:-1]
0453                 l = Label(subframe, text=name)
0454                 l.grid(row=row, column=0, sticky="nw")
0455                 l = Entry(subframe, width=0, borderwidth=0)
0456                 l.insert(0, svalue)
0457                 l.grid(row=row, column=1, sticky="nw")
0458                 row = row+1
0459         self.dict = dict
0460         # XXX Could we use a <Configure> callback for the following?
0461         subframe.update_idletasks() # Alas!
0462         width = subframe.winfo_reqwidth()
0463         height = subframe.winfo_reqheight()
0464         canvas = self.canvas
0465         self.canvas["scrollregion"] = (0, 0, width, height)
0466         if height > 300:
0467             canvas["height"] = 300
0468             frame.pack(expand=1)
0469         else:
0470             canvas["height"] = height
0471             frame.pack(expand=0)
0472 
0473     def close(self):
0474         self.frame.destroy()
0475 

Generated by PyXR 0.9.4
SourceForge.net Logo