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 / OLDSTACKVIEWER.PY < prev    next >
Encoding:
Python Source  |  2000-09-28  |  8.9 KB  |  277 lines

  1. import string
  2. import sys
  3. import os
  4. from Tkinter import *
  5. import linecache
  6. from repr import Repr
  7. from WindowList import ListedToplevel
  8.  
  9. from ScrolledList import ScrolledList
  10.  
  11.  
  12. class StackBrowser:
  13.  
  14.     def __init__(self, root, flist, stack=None):
  15.         self.top = top = ListedToplevel(root)
  16.         top.protocol("WM_DELETE_WINDOW", self.close)
  17.         top.bind("<Key-Escape>", self.close)
  18.         top.wm_title("Stack viewer")
  19.         top.wm_iconname("Stack")
  20.         # Create help label
  21.         self.helplabel = Label(top,
  22.             text="Click once to view variables; twice for source",
  23.             borderwidth=2, relief="groove")
  24.         self.helplabel.pack(fill="x")
  25.         #
  26.         self.sv = StackViewer(top, flist, self)
  27.         if stack is None:
  28.             stack = get_stack()
  29.         self.sv.load_stack(stack)
  30.  
  31.     def close(self, event=None):
  32.         self.top.destroy()
  33.  
  34.     localsframe = None
  35.     localsviewer = None
  36.     localsdict = None
  37.     globalsframe = None
  38.     globalsviewer = None
  39.     globalsdict = None
  40.     curframe = None
  41.  
  42.     def show_frame(self, (frame, lineno)):
  43.         if frame is self.curframe:
  44.             return
  45.         self.curframe = None
  46.         if frame.f_globals is not self.globalsdict:
  47.             self.show_globals(frame)
  48.         self.show_locals(frame)
  49.         self.curframe = frame
  50.  
  51.     def show_globals(self, frame):
  52.         title = "Global Variables"
  53.         if frame.f_globals.has_key("__name__"):
  54.             try:
  55.                 name = str(frame.f_globals["__name__"]) + ""
  56.             except:
  57.                 name = ""
  58.             if name:
  59.                 title = title + " in module " + name
  60.         self.globalsdict = None
  61.         if self.globalsviewer:
  62.             self.globalsviewer.close()
  63.         self.globalsviewer = None
  64.         if not self.globalsframe:
  65.             self.globalsframe = Frame(self.top)
  66.         self.globalsdict = frame.f_globals
  67.         self.globalsviewer = NamespaceViewer(
  68.             self.globalsframe,
  69.             title,
  70.             self.globalsdict)
  71.         self.globalsframe.pack(fill="both", side="bottom")
  72.  
  73.     def show_locals(self, frame):
  74.         self.localsdict = None
  75.         if self.localsviewer:
  76.             self.localsviewer.close()
  77.         self.localsviewer = None
  78.         if frame.f_locals is not frame.f_globals:
  79.             title = "Local Variables"
  80.             code = frame.f_code
  81.             funcname = code.co_name
  82.             if funcname not in ("?", "", None):
  83.                 title = title + " in " + funcname
  84.             if not self.localsframe:
  85.                 self.localsframe = Frame(self.top)
  86.             self.localsdict = frame.f_locals
  87.             self.localsviewer = NamespaceViewer(
  88.                 self.localsframe,
  89.                 title,
  90.                 self.localsdict)
  91.             self.localsframe.pack(fill="both", side="top")
  92.         else:
  93.             if self.localsframe:
  94.                 self.localsframe.forget()
  95.  
  96.  
  97. class StackViewer(ScrolledList):
  98.  
  99.     def __init__(self, master, flist, browser):
  100.         ScrolledList.__init__(self, master, width=80)
  101.         self.flist = flist
  102.         self.browser = browser
  103.         self.stack = []
  104.  
  105.     def load_stack(self, stack, index=None):
  106.         self.stack = stack
  107.         self.clear()
  108. ##        if len(stack) > 10:
  109. ##            l["height"] = 10
  110. ##            self.topframe.pack(expand=1)
  111. ##        else:
  112. ##            l["height"] = len(stack)
  113. ##            self.topframe.pack(expand=0)
  114.         for i in range(len(stack)):
  115.             frame, lineno = stack[i]
  116.             try:
  117.                 modname = frame.f_globals["__name__"]
  118.             except:
  119.                 modname = "?"
  120.             code = frame.f_code
  121.             filename = code.co_filename
  122.             funcname = code.co_name
  123.             sourceline = linecache.getline(filename, lineno)
  124.             sourceline = string.strip(sourceline)
  125.             if funcname in ("?", "", None):
  126.                 item = "%s, line %d: %s" % (modname, lineno, sourceline)
  127.             else:
  128.                 item = "%s.%s(), line %d: %s" % (modname, funcname,
  129.                                                  lineno, sourceline)
  130.             if i == index:
  131.                 item = "> " + item
  132.             self.append(item)
  133.         if index is not None:
  134.             self.select(index)
  135.  
  136.     def popup_event(self, event):
  137.         if self.stack:
  138.             return ScrolledList.popup_event(self, event)
  139.  
  140.     def fill_menu(self):
  141.         menu = self.menu
  142.         menu.add_command(label="Go to source line",
  143.                          command=self.goto_source_line)
  144.         menu.add_command(label="Show stack frame",
  145.                          command=self.show_stack_frame)
  146.  
  147.     def on_select(self, index):
  148.         if 0 <= index < len(self.stack):
  149.             self.browser.show_frame(self.stack[index])
  150.  
  151.     def on_double(self, index):
  152.         self.show_source(index)
  153.  
  154.     def goto_source_line(self):
  155.         index = self.listbox.index("active")
  156.         self.show_source(index)
  157.  
  158.     def show_stack_frame(self):
  159.         index = self.listbox.index("active")
  160.         if 0 <= index < len(self.stack):
  161.             self.browser.show_frame(self.stack[index])
  162.  
  163.     def show_source(self, index):
  164.         if not (0 <= index < len(self.stack)):
  165.             return
  166.         frame, lineno = self.stack[index]
  167.         code = frame.f_code
  168.         filename = code.co_filename
  169.         if os.path.isfile(filename):
  170.             edit = self.flist.open(filename)
  171.             if edit:
  172.                 edit.gotoline(lineno)
  173.  
  174.  
  175. def get_stack(t=None, f=None):
  176.     if t is None:
  177.         t = sys.last_traceback
  178.     stack = []
  179.     if t and t.tb_frame is f:
  180.         t = t.tb_next
  181.     while f is not None:
  182.         stack.append((f, f.f_lineno))
  183.         if f is self.botframe:
  184.             break
  185.         f = f.f_back
  186.     stack.reverse()
  187.     while t is not None:
  188.         stack.append((t.tb_frame, t.tb_lineno))
  189.         t = t.tb_next
  190.     return stack
  191.  
  192.  
  193. def getexception(type=None, value=None):
  194.     if type is None:
  195.         type = sys.last_type
  196.         value = sys.last_value
  197.     if hasattr(type, "__name__"):
  198.         type = type.__name__
  199.     s = str(type)
  200.     if value is not None:
  201.         s = s + ": " + str(value)
  202.     return s
  203.  
  204.  
  205. class NamespaceViewer:
  206.  
  207.     def __init__(self, master, title, dict=None):
  208.         width = 0
  209.         height = 40
  210.         if dict:
  211.             height = 20*len(dict) # XXX 20 == observed height of Entry widget
  212.         self.master = master
  213.         self.title = title
  214.         self.repr = Repr()
  215.         self.repr.maxstring = 60
  216.         self.repr.maxother = 60
  217.         self.frame = frame = Frame(master)
  218.         self.frame.pack(expand=1, fill="both")
  219.         self.label = Label(frame, text=title, borderwidth=2, relief="groove")
  220.         self.label.pack(fill="x")
  221.         self.vbar = vbar = Scrollbar(frame, name="vbar")
  222.         vbar.pack(side="right", fill="y")
  223.         self.canvas = canvas = Canvas(frame,
  224.                                       height=min(300, max(40, height)),
  225.                                       scrollregion=(0, 0, width, height))
  226.         canvas.pack(side="left", fill="both", expand=1)
  227.         vbar["command"] = canvas.yview
  228.         canvas["yscrollcommand"] = vbar.set
  229.         self.subframe = subframe = Frame(canvas)
  230.         self.sfid = canvas.create_window(0, 0, window=subframe, anchor="nw")
  231.         self.load_dict(dict)
  232.  
  233.     dict = -1
  234.  
  235.     def load_dict(self, dict, force=0):
  236.         if dict is self.dict and not force:
  237.             return
  238.         subframe = self.subframe
  239.         frame = self.frame
  240.         for c in subframe.children.values():
  241.             c.destroy()
  242.         self.dict = None
  243.         if not dict:
  244.             l = Label(subframe, text="None")
  245.             l.grid(row=0, column=0)
  246.         else:
  247.             names = dict.keys()
  248.             names.sort()
  249.             row = 0
  250.             for name in names:
  251.                 value = dict[name]
  252.                 svalue = self.repr.repr(value) # repr(value)
  253.                 l = Label(subframe, text=name)
  254.                 l.grid(row=row, column=0, sticky="nw")
  255.     ##            l = Label(subframe, text=svalue, justify="l", wraplength=300)
  256.                 l = Entry(subframe, width=0, borderwidth=0)
  257.                 l.insert(0, svalue)
  258.     ##            l["state"] = "disabled"
  259.                 l.grid(row=row, column=1, sticky="nw")
  260.                 row = row+1
  261.         self.dict = dict
  262.         # XXX Could we use a <Configure> callback for the following?
  263.         subframe.update_idletasks() # Alas!
  264.         width = subframe.winfo_reqwidth()
  265.         height = subframe.winfo_reqheight()
  266.         canvas = self.canvas
  267.         self.canvas["scrollregion"] = (0, 0, width, height)
  268.         if height > 300:
  269.             canvas["height"] = 300
  270.             frame.pack(expand=1)
  271.         else:
  272.             canvas["height"] = height
  273.             frame.pack(expand=0)
  274.  
  275.     def close(self):
  276.         self.frame.destroy()
  277.