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