home *** CD-ROM | disk | FTP | other *** search
/ PC World 2001 April / PCWorld_2001-04_cd.bin / Software / TemaCD / webclean / !!!python!!! / BeOpen-Python-2.0.exe / DEBUGGER.PY < prev    next >
Encoding:
Python Source  |  2000-09-28  |  9.5 KB  |  309 lines

  1. import os
  2. import bdb
  3. import traceback
  4. from Tkinter import *
  5. from WindowList import ListedToplevel
  6.  
  7. import StackViewer
  8.  
  9.  
  10. class Debugger(bdb.Bdb):
  11.  
  12.     interacting = 0
  13.  
  14.     vstack = vsource = vlocals = vglobals = None
  15.  
  16.     def __init__(self, pyshell):
  17.         bdb.Bdb.__init__(self)
  18.         self.pyshell = pyshell
  19.         self.make_gui()
  20.     
  21.     def canonic(self, filename):
  22.         # Canonicalize filename -- called by Bdb
  23.         return os.path.normcase(os.path.abspath(filename))
  24.  
  25.     def close(self, event=None):
  26.         if self.interacting:
  27.             self.top.bell()
  28.             return
  29.         if self.stackviewer:
  30.             self.stackviewer.close(); self.stackviewer = None
  31.         self.pyshell.close_debugger()
  32.         self.top.destroy()
  33.  
  34.     def run(self, *args):
  35.         try:
  36.             self.interacting = 1
  37.             return apply(bdb.Bdb.run, (self,) + args)
  38.         finally:
  39.             self.interacting = 0
  40.  
  41.     def user_line(self, frame):
  42.         self.interaction(frame)
  43.  
  44.     def user_return(self, frame, rv):
  45.         # XXX show rv?
  46.         ##self.interaction(frame)
  47.         pass
  48.  
  49.     def user_exception(self, frame, info):
  50.         self.interaction(frame, info)
  51.  
  52.     def make_gui(self):
  53.         pyshell = self.pyshell
  54.         self.flist = pyshell.flist
  55.         self.root = root = pyshell.root
  56.         self.top = top =ListedToplevel(root)
  57.         self.top.wm_title("Debug Control")
  58.         self.top.wm_iconname("Debug")
  59.         top.wm_protocol("WM_DELETE_WINDOW", self.close)
  60.         self.top.bind("<Escape>", self.close)
  61.         #
  62.         self.bframe = bframe = Frame(top)
  63.         self.bframe.pack(anchor="w")
  64.         self.buttons = bl = []
  65.         #
  66.         self.bcont = b = Button(bframe, text="Go", command=self.cont)
  67.         bl.append(b)
  68.         self.bstep = b = Button(bframe, text="Step", command=self.step)
  69.         bl.append(b)
  70.         self.bnext = b = Button(bframe, text="Over", command=self.next)
  71.         bl.append(b)
  72.         self.bret = b = Button(bframe, text="Out", command=self.ret)
  73.         bl.append(b)
  74.         self.bret = b = Button(bframe, text="Quit", command=self.quit)
  75.         bl.append(b)
  76.         #
  77.         for b in bl:
  78.             b.configure(state="disabled")
  79.             b.pack(side="left")
  80.         #
  81.         self.cframe = cframe = Frame(bframe)
  82.         self.cframe.pack(side="left")
  83.         #
  84.         if not self.vstack:
  85.             self.__class__.vstack = BooleanVar(top)
  86.             self.vstack.set(1)
  87.         self.bstack = Checkbutton(cframe,
  88.             text="Stack", command=self.show_stack, variable=self.vstack)
  89.         self.bstack.grid(row=0, column=0)
  90.         if not self.vsource:
  91.             self.__class__.vsource = BooleanVar(top)
  92.             ##self.vsource.set(1)
  93.         self.bsource = Checkbutton(cframe,
  94.             text="Source", command=self.show_source, variable=self.vsource)
  95.         self.bsource.grid(row=0, column=1)
  96.         if not self.vlocals:
  97.             self.__class__.vlocals = BooleanVar(top)
  98.             self.vlocals.set(1)
  99.         self.blocals = Checkbutton(cframe,
  100.             text="Locals", command=self.show_locals, variable=self.vlocals)
  101.         self.blocals.grid(row=1, column=0)
  102.         if not self.vglobals:
  103.             self.__class__.vglobals = BooleanVar(top)
  104.             ##self.vglobals.set(1)
  105.         self.bglobals = Checkbutton(cframe,
  106.             text="Globals", command=self.show_globals, variable=self.vglobals)
  107.         self.bglobals.grid(row=1, column=1)
  108.         #
  109.         self.status = Label(top, anchor="w")
  110.         self.status.pack(anchor="w")
  111.         self.error = Label(top, anchor="w")
  112.         self.error.pack(anchor="w", fill="x")
  113.         self.errorbg = self.error.cget("background")
  114.         #
  115.         self.fstack = Frame(top, height=1)
  116.         self.fstack.pack(expand=1, fill="both")
  117.         self.flocals = Frame(top)
  118.         self.flocals.pack(expand=1, fill="both")
  119.         self.fglobals = Frame(top, height=1)
  120.         self.fglobals.pack(expand=1, fill="both")
  121.         #
  122.         if self.vstack.get():
  123.             self.show_stack()
  124.         if self.vlocals.get():
  125.             self.show_locals()
  126.         if self.vglobals.get():
  127.             self.show_globals()
  128.  
  129.     frame = None
  130.  
  131.     def interaction(self, frame, info=None):
  132.         self.frame = frame
  133.         code = frame.f_code
  134.         file = code.co_filename
  135.         base = os.path.basename(file)
  136.         lineno = frame.f_lineno
  137.         #
  138.         message = "%s:%s" % (base, lineno)
  139.         if code.co_name != "?":
  140.             message = "%s: %s()" % (message, code.co_name)
  141.         self.status.configure(text=message)
  142.         #
  143.         if info:
  144.             type, value, tb = info
  145.             try:
  146.                 m1 = type.__name__
  147.             except AttributeError:
  148.                 m1 = "%s" % str(type)
  149.             if value is not None:
  150.                 try:
  151.                     m1 = "%s: %s" % (m1, str(value))
  152.                 except:
  153.                     pass
  154.             bg = "yellow"
  155.         else:
  156.             m1 = ""
  157.             tb = None
  158.             bg = self.errorbg
  159.         self.error.configure(text=m1, background=bg)
  160.         #
  161.         sv = self.stackviewer
  162.         if sv:
  163.             stack, i = self.get_stack(self.frame, tb)
  164.             sv.load_stack(stack, i)
  165.         #
  166.         self.show_variables(1)
  167.         #
  168.         if self.vsource.get():
  169.             self.sync_source_line()
  170.         #
  171.         for b in self.buttons:
  172.             b.configure(state="normal")
  173.         #
  174.         self.top.tkraise()
  175.         self.root.mainloop()
  176.         #
  177.         for b in self.buttons:
  178.             b.configure(state="disabled")
  179.         self.status.configure(text="")
  180.         self.error.configure(text="", background=self.errorbg)
  181.         self.frame = None
  182.  
  183.     def sync_source_line(self):
  184.         frame = self.frame
  185.         if not frame:
  186.             return
  187.         code = frame.f_code
  188.         file = code.co_filename
  189.         lineno = frame.f_lineno
  190.         if file[:1] + file[-1:] != "<>" and os.path.exists(file):
  191.             edit = self.flist.open(file)
  192.             if edit:
  193.                 edit.gotoline(lineno)
  194.  
  195.     def cont(self):
  196.         self.set_continue()
  197.         self.root.quit()
  198.  
  199.     def step(self):
  200.         self.set_step()
  201.         self.root.quit()
  202.  
  203.     def next(self):
  204.         self.set_next(self.frame)
  205.         self.root.quit()
  206.  
  207.     def ret(self):
  208.         self.set_return(self.frame)
  209.         self.root.quit()
  210.  
  211.     def quit(self):
  212.         self.set_quit()
  213.         self.root.quit()
  214.  
  215.     stackviewer = None
  216.  
  217.     def show_stack(self):
  218.         if not self.stackviewer and self.vstack.get():
  219.             self.stackviewer = sv = StackViewer.StackViewer(
  220.                 self.fstack, self.flist, self)
  221.             if self.frame:
  222.                 stack, i = self.get_stack(self.frame, None)
  223.                 sv.load_stack(stack, i)
  224.         else:
  225.             sv = self.stackviewer
  226.             if sv and not self.vstack.get():
  227.                 self.stackviewer = None
  228.                 sv.close()
  229.             self.fstack['height'] = 1
  230.  
  231.     def show_source(self):
  232.         if self.vsource.get():
  233.             self.sync_source_line()
  234.  
  235.     def show_frame(self, (frame, lineno)):
  236.         self.frame = frame
  237.         self.show_variables()
  238.  
  239.     localsviewer = None
  240.     globalsviewer = None
  241.  
  242.     def show_locals(self):
  243.         lv = self.localsviewer
  244.         if self.vlocals.get():
  245.             if not lv:
  246.                 self.localsviewer = StackViewer.NamespaceViewer(
  247.                     self.flocals, "Locals")
  248.         else:
  249.             if lv:
  250.                 self.localsviewer = None
  251.                 lv.close()
  252.                 self.flocals['height'] = 1
  253.         self.show_variables()
  254.  
  255.     def show_globals(self):
  256.         gv = self.globalsviewer
  257.         if self.vglobals.get():
  258.             if not gv:
  259.                 self.globalsviewer = StackViewer.NamespaceViewer(
  260.                     self.fglobals, "Globals")
  261.         else:
  262.             if gv:
  263.                 self.globalsviewer = None
  264.                 gv.close()
  265.                 self.fglobals['height'] = 1
  266.         self.show_variables()
  267.  
  268.     def show_variables(self, force=0):
  269.         lv = self.localsviewer
  270.         gv = self.globalsviewer
  271.         frame = self.frame
  272.         if not frame:
  273.             ldict = gdict = None
  274.         else:
  275.             ldict = frame.f_locals
  276.             gdict = frame.f_globals
  277.             if lv and gv and ldict is gdict:
  278.                 ldict = None
  279.         if lv:
  280.             lv.load_dict(ldict, force)
  281.         if gv:
  282.             gv.load_dict(gdict, force)
  283.  
  284.     def set_breakpoint_here(self, edit):
  285.         text = edit.text
  286.         filename = edit.io.filename
  287.         if not filename:
  288.             text.bell()
  289.             return
  290.         lineno = int(float(text.index("insert")))
  291.         msg = self.set_break(filename, lineno)
  292.         if msg:
  293.             text.bell()
  294.             return
  295.         text.tag_add("BREAK", "insert linestart", "insert lineend +1char")
  296.  
  297.     # A literal copy of Bdb.set_break() without the print statement at the end
  298.     def set_break(self, filename, lineno, temporary=0, cond = None):
  299.         import linecache # Import as late as possible
  300.         line = linecache.getline(filename, lineno)
  301.         if not line:
  302.                 return 'That line does not exist!'
  303.         if not self.breaks.has_key(filename):
  304.                 self.breaks[filename] = []
  305.         list = self.breaks[filename]
  306.         if not lineno in list:
  307.                 list.append(lineno)
  308.         bp = bdb.Breakpoint(filename, lineno, temporary, cond)
  309.