mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	New stack viewer, uses a tree widget.
(XXX: the debugger doesn't yet use this.)
This commit is contained in:
		
							parent
							
								
									553fa4432a
								
							
						
					
					
						commit
						b658469873
					
				
					 1 changed files with 90 additions and 231 deletions
				
			
		|  | @ -1,177 +1,106 @@ | |||
| import string | ||||
| import sys | ||||
| import os | ||||
| from Tkinter import * | ||||
| import linecache | ||||
| from repr import Repr | ||||
| from WindowList import ListedToplevel | ||||
| 
 | ||||
| from ScrolledList import ScrolledList | ||||
| from TreeWidget import TreeNode, TreeItem, ScrolledCanvas | ||||
| from ObjectBrowser import ObjectTreeItem, make_objecttreeitem | ||||
| from OldStackViewer import StackViewer, NamespaceViewer | ||||
| 
 | ||||
| def StackBrowser(root, flist=None, stack=None): | ||||
|     top = Toplevel(root) | ||||
|     sc = ScrolledCanvas(top, bg="white", highlightthickness=0) | ||||
|     sc.frame.pack(expand=1, fill="both") | ||||
|     item = StackTreeItem(flist) | ||||
|     node = TreeNode(sc.canvas, None, item) | ||||
|     node.expand() | ||||
| 
 | ||||
| class StackBrowser: | ||||
| class StackTreeItem(TreeItem): | ||||
| 
 | ||||
|     def __init__(self, root, flist, stack=None): | ||||
|         self.top = top = ListedToplevel(root) | ||||
|         top.protocol("WM_DELETE_WINDOW", self.close) | ||||
|         top.bind("<Key-Escape>", self.close) | ||||
|         top.wm_title("Stack viewer") | ||||
|         top.wm_iconname("Stack") | ||||
|         # Create help label | ||||
|         self.helplabel = Label(top, | ||||
|             text="Click once to view variables; twice for source", | ||||
|             borderwidth=2, relief="groove") | ||||
|         self.helplabel.pack(fill="x") | ||||
|         # | ||||
|         self.sv = StackViewer(top, flist, self) | ||||
|         if stack is None: | ||||
|             stack = get_stack() | ||||
|         self.sv.load_stack(stack) | ||||
| 
 | ||||
|     def close(self, event=None): | ||||
|         self.top.destroy() | ||||
| 
 | ||||
|     localsframe = None | ||||
|     localsviewer = None | ||||
|     localsdict = None | ||||
|     globalsframe = None | ||||
|     globalsviewer = None | ||||
|     globalsdict = None | ||||
|     curframe = None | ||||
| 
 | ||||
|     def show_frame(self, (frame, lineno)): | ||||
|         if frame is self.curframe: | ||||
|             return | ||||
|         self.curframe = None | ||||
|         if frame.f_globals is not self.globalsdict: | ||||
|             self.show_globals(frame) | ||||
|         self.show_locals(frame) | ||||
|         self.curframe = frame | ||||
| 
 | ||||
|     def show_globals(self, frame): | ||||
|         title = "Global Variables" | ||||
|         if frame.f_globals.has_key("__name__"): | ||||
|             try: | ||||
|                 name = str(frame.f_globals["__name__"]) + "" | ||||
|             except: | ||||
|                 name = "" | ||||
|             if name: | ||||
|                 title = title + " in module " + name | ||||
|         self.globalsdict = None | ||||
|         if self.globalsviewer: | ||||
|             self.globalsviewer.close() | ||||
|         self.globalsviewer = None | ||||
|         if not self.globalsframe: | ||||
|             self.globalsframe = Frame(self.top) | ||||
|         self.globalsdict = frame.f_globals | ||||
|         self.globalsviewer = NamespaceViewer( | ||||
|             self.globalsframe, | ||||
|             title, | ||||
|             self.globalsdict) | ||||
|         self.globalsframe.pack(fill="both", side="bottom") | ||||
| 
 | ||||
|     def show_locals(self, frame): | ||||
|         self.localsdict = None | ||||
|         if self.localsviewer: | ||||
|             self.localsviewer.close() | ||||
|         self.localsviewer = None | ||||
|         if frame.f_locals is not frame.f_globals: | ||||
|             title = "Local Variables" | ||||
|             code = frame.f_code | ||||
|             funcname = code.co_name | ||||
|             if funcname not in ("?", "", None): | ||||
|                 title = title + " in " + funcname | ||||
|             if not self.localsframe: | ||||
|                 self.localsframe = Frame(self.top) | ||||
|             self.localsdict = frame.f_locals | ||||
|             self.localsviewer = NamespaceViewer( | ||||
|                 self.localsframe, | ||||
|                 title, | ||||
|                 self.localsdict) | ||||
|             self.localsframe.pack(fill="both", side="top") | ||||
|         else: | ||||
|             if self.localsframe: | ||||
|                 self.localsframe.forget() | ||||
| 
 | ||||
| 
 | ||||
| class StackViewer(ScrolledList): | ||||
| 
 | ||||
|     def __init__(self, master, flist, browser): | ||||
|         ScrolledList.__init__(self, master, width=80) | ||||
|     def __init__(self, flist=None): | ||||
|         self.flist = flist | ||||
|         self.browser = browser | ||||
|         self.stack = [] | ||||
|         self.stack = get_stack() | ||||
|         self.text = get_exception() | ||||
| 
 | ||||
|     def load_stack(self, stack, index=None): | ||||
|         self.stack = stack | ||||
|         self.clear() | ||||
| ##        if len(stack) > 10: | ||||
| ##            l["height"] = 10 | ||||
| ##            self.topframe.pack(expand=1) | ||||
| ##        else: | ||||
| ##            l["height"] = len(stack) | ||||
| ##            self.topframe.pack(expand=0) | ||||
|         for i in range(len(stack)): | ||||
|             frame, lineno = stack[i] | ||||
|             try: | ||||
|                 modname = frame.f_globals["__name__"] | ||||
|             except: | ||||
|                 modname = "?" | ||||
|             code = frame.f_code | ||||
|             filename = code.co_filename | ||||
|             funcname = code.co_name | ||||
|             sourceline = linecache.getline(filename, lineno) | ||||
|             sourceline = string.strip(sourceline) | ||||
|             if funcname in ("?", "", None): | ||||
|                 item = "%s, line %d: %s" % (modname, lineno, sourceline) | ||||
|             else: | ||||
|                 item = "%s.%s(), line %d: %s" % (modname, funcname, | ||||
|                                                  lineno, sourceline) | ||||
|             if i == index: | ||||
|                 item = "> " + item | ||||
|             self.append(item) | ||||
|         if index is not None: | ||||
|             self.select(index) | ||||
|     def GetText(self): | ||||
|         return self.text | ||||
| 
 | ||||
|     def popup_event(self, event): | ||||
|         if self.stack: | ||||
|             return ScrolledList.popup_event(self, event) | ||||
|     def GetSubList(self): | ||||
|         sublist = [] | ||||
|         for info in self.stack: | ||||
|             item = FrameTreeItem(info, self.flist) | ||||
|             sublist.append(item) | ||||
|         return sublist | ||||
| 
 | ||||
|     def fill_menu(self): | ||||
|         menu = self.menu | ||||
|         menu.add_command(label="Go to source line", | ||||
|                          command=self.goto_source_line) | ||||
|         menu.add_command(label="Show stack frame", | ||||
|                          command=self.show_stack_frame) | ||||
| class FrameTreeItem(TreeItem): | ||||
| 
 | ||||
|     def on_select(self, index): | ||||
|         if 0 <= index < len(self.stack): | ||||
|             self.browser.show_frame(self.stack[index]) | ||||
|     def __init__(self, info, flist): | ||||
|         self.info = info | ||||
|         self.flist = flist | ||||
| 
 | ||||
|     def on_double(self, index): | ||||
|         self.show_source(index) | ||||
| 
 | ||||
|     def goto_source_line(self): | ||||
|         index = self.listbox.index("active") | ||||
|         self.show_source(index) | ||||
| 
 | ||||
|     def show_stack_frame(self): | ||||
|         index = self.listbox.index("active") | ||||
|         if 0 <= index < len(self.stack): | ||||
|             self.browser.show_frame(self.stack[index]) | ||||
| 
 | ||||
|     def show_source(self, index): | ||||
|         if not (0 <= index < len(self.stack)): | ||||
|             return | ||||
|         frame, lineno = self.stack[index] | ||||
|     def GetText(self): | ||||
|         frame, lineno = self.info | ||||
|         try: | ||||
|             modname = frame.f_globals["__name__"] | ||||
|         except: | ||||
|             modname = "?" | ||||
|         code = frame.f_code | ||||
|         filename = code.co_filename | ||||
|         if os.path.isfile(filename): | ||||
|         funcname = code.co_name | ||||
|         sourceline = linecache.getline(filename, lineno) | ||||
|         sourceline = string.strip(sourceline) | ||||
|         if funcname in ("?", "", None): | ||||
|             item = "%s, line %d: %s" % (modname, lineno, sourceline) | ||||
|         else: | ||||
|             item = "%s.%s(...), line %d: %s" % (modname, funcname, | ||||
|                                              lineno, sourceline) | ||||
| ##        if i == index: | ||||
| ##            item = "> " + item | ||||
|         return item | ||||
| 
 | ||||
|     def GetSubList(self): | ||||
|         frame, lineno = self.info | ||||
|         sublist = [] | ||||
|         if frame.f_globals is not frame.f_locals: | ||||
|             item = VariablesTreeItem("<locals>", frame.f_locals, self.flist) | ||||
|             sublist.append(item) | ||||
|         item = VariablesTreeItem("<globals>", frame.f_globals, self.flist) | ||||
|         sublist.append(item) | ||||
|         return sublist | ||||
| 
 | ||||
|     def OnDoubleClick(self): | ||||
|         if self.flist: | ||||
|             frame, lineno = self.info | ||||
|             filename = frame.f_code.co_filename | ||||
|             edit = self.flist.open(filename) | ||||
|             if edit: | ||||
|                 edit.gotoline(lineno) | ||||
|             edit.gotoline(lineno) | ||||
| 
 | ||||
| class VariablesTreeItem(ObjectTreeItem): | ||||
| 
 | ||||
|     def GetText(self): | ||||
|         return self.labeltext | ||||
| 
 | ||||
|     def GetLabelText(self): | ||||
|         return None | ||||
| 
 | ||||
|     def IsExpandable(self): | ||||
|         return len(self.object) > 0 | ||||
| 
 | ||||
|     def keys(self): | ||||
|         return self.object.keys() | ||||
| 
 | ||||
|     def GetSubList(self): | ||||
|         sublist = [] | ||||
|         for key in self.keys(): | ||||
|             try: | ||||
|                 value = self.object[key] | ||||
|             except KeyError: | ||||
|                 continue | ||||
|             def setfunction(value, key=key, object=self.object): | ||||
|                 object[key] = value | ||||
|             item = make_objecttreeitem(key + " =", value, setfunction) | ||||
|             sublist.append(item) | ||||
|         return sublist | ||||
|          | ||||
| def get_stack(t=None, f=None): | ||||
|     if t is None: | ||||
|         t = sys.last_traceback | ||||
|  | @ -189,8 +118,7 @@ def get_stack(t=None, f=None): | |||
|         t = t.tb_next | ||||
|     return stack | ||||
| 
 | ||||
| 
 | ||||
| def getexception(type=None, value=None): | ||||
| def get_exception(type=None, value=None): | ||||
|     if type is None: | ||||
|         type = sys.last_type | ||||
|         value = sys.last_value | ||||
|  | @ -201,76 +129,7 @@ def getexception(type=None, value=None): | |||
|         s = s + ": " + str(value) | ||||
|     return s | ||||
| 
 | ||||
| 
 | ||||
| class NamespaceViewer: | ||||
| 
 | ||||
|     def __init__(self, master, title, dict=None): | ||||
|         width = 0 | ||||
|         height = 40 | ||||
|         if dict: | ||||
|             height = 20*len(dict) # XXX 20 == observed height of Entry widget | ||||
|         self.master = master | ||||
|         self.title = title | ||||
|         self.repr = Repr() | ||||
|         self.repr.maxstring = 60 | ||||
|         self.repr.maxother = 60 | ||||
|         self.frame = frame = Frame(master) | ||||
|         self.frame.pack(expand=1, fill="both") | ||||
|         self.label = Label(frame, text=title, borderwidth=2, relief="groove") | ||||
|         self.label.pack(fill="x") | ||||
|         self.vbar = vbar = Scrollbar(frame, name="vbar") | ||||
|         vbar.pack(side="right", fill="y") | ||||
|         self.canvas = canvas = Canvas(frame, | ||||
|                                       height=min(300, max(40, height)), | ||||
|                                       scrollregion=(0, 0, width, height)) | ||||
|         canvas.pack(side="left", fill="both", expand=1) | ||||
|         vbar["command"] = canvas.yview | ||||
|         canvas["yscrollcommand"] = vbar.set | ||||
|         self.subframe = subframe = Frame(canvas) | ||||
|         self.sfid = canvas.create_window(0, 0, window=subframe, anchor="nw") | ||||
|         self.load_dict(dict) | ||||
| 
 | ||||
|     dict = -1 | ||||
| 
 | ||||
|     def load_dict(self, dict, force=0): | ||||
|         if dict is self.dict and not force: | ||||
|             return | ||||
|         subframe = self.subframe | ||||
|         frame = self.frame | ||||
|         for c in subframe.children.values(): | ||||
|             c.destroy() | ||||
|         self.dict = None | ||||
|         if not dict: | ||||
|             l = Label(subframe, text="None") | ||||
|             l.grid(row=0, column=0) | ||||
|         else: | ||||
|             names = dict.keys() | ||||
|             names.sort() | ||||
|             row = 0 | ||||
|             for name in names: | ||||
|                 value = dict[name] | ||||
|                 svalue = self.repr.repr(value) # repr(value) | ||||
|                 l = Label(subframe, text=name) | ||||
|                 l.grid(row=row, column=0, sticky="nw") | ||||
|     ##            l = Label(subframe, text=svalue, justify="l", wraplength=300) | ||||
|                 l = Entry(subframe, width=0, borderwidth=0) | ||||
|                 l.insert(0, svalue) | ||||
|     ##            l["state"] = "disabled" | ||||
|                 l.grid(row=row, column=1, sticky="nw") | ||||
|                 row = row+1 | ||||
|         self.dict = dict | ||||
|         # XXX Could we use a <Configure> callback for the following? | ||||
|         subframe.update_idletasks() # Alas! | ||||
|         width = subframe.winfo_reqwidth() | ||||
|         height = subframe.winfo_reqheight() | ||||
|         canvas = self.canvas | ||||
|         self.canvas["scrollregion"] = (0, 0, width, height) | ||||
|         if height > 300: | ||||
|             canvas["height"] = 300 | ||||
|             frame.pack(expand=1) | ||||
|         else: | ||||
|             canvas["height"] = height | ||||
|             frame.pack(expand=0) | ||||
| 
 | ||||
|     def close(self): | ||||
|         self.frame.destroy() | ||||
| if __name__ == "__main__": | ||||
|     root = Tk() | ||||
|     root.withdraw() | ||||
|     StackBrowser(root) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Guido van Rossum
						Guido van Rossum