| 
									
										
										
										
											1998-10-10 18:48:31 +00:00
										 |  |  | import string | 
					
						
							|  |  |  | import sys | 
					
						
							|  |  |  | import os | 
					
						
							|  |  |  | from Tkinter import * | 
					
						
							|  |  |  | import linecache | 
					
						
							|  |  |  | from repr import Repr | 
					
						
							| 
									
										
										
										
											1999-01-02 21:28:54 +00:00
										 |  |  | from WindowList import ListedToplevel | 
					
						
							| 
									
										
										
										
											1998-10-10 18:48:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-10-16 04:02:28 +00:00
										 |  |  | from ScrolledList import ScrolledList | 
					
						
							| 
									
										
										
										
											1998-10-10 18:48:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-10-16 16:10:45 +00:00
										 |  |  | class StackBrowser: | 
					
						
							| 
									
										
										
										
											1999-01-02 21:28:54 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-10-16 16:10:45 +00:00
										 |  |  |     def __init__(self, root, flist, stack=None): | 
					
						
							| 
									
										
										
										
											1999-01-02 21:28:54 +00:00
										 |  |  |         self.top = top = ListedToplevel(root) | 
					
						
							| 
									
										
										
										
											1998-10-16 04:02:28 +00:00
										 |  |  |         top.protocol("WM_DELETE_WINDOW", self.close) | 
					
						
							| 
									
										
										
										
											1999-01-09 21:58:11 +00:00
										 |  |  |         top.bind("<Key-Escape>", self.close) | 
					
						
							| 
									
										
										
										
											1998-10-10 18:48:31 +00:00
										 |  |  |         top.wm_title("Stack viewer") | 
					
						
							| 
									
										
										
										
											1999-01-02 21:28:54 +00:00
										 |  |  |         top.wm_iconname("Stack") | 
					
						
							| 
									
										
										
										
											1998-10-10 19:15:32 +00:00
										 |  |  |         # 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") | 
					
						
							| 
									
										
										
										
											1998-10-16 04:02:28 +00:00
										 |  |  |         # | 
					
						
							| 
									
										
										
										
											1998-10-16 16:10:45 +00:00
										 |  |  |         self.sv = StackViewer(top, flist, self) | 
					
						
							|  |  |  |         if stack is None: | 
					
						
							|  |  |  |             stack = get_stack() | 
					
						
							|  |  |  |         self.sv.load_stack(stack) | 
					
						
							| 
									
										
										
										
											1999-01-02 21:28:54 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-01-09 21:58:11 +00:00
										 |  |  |     def close(self, event=None): | 
					
						
							| 
									
										
										
										
											1998-10-13 16:32:29 +00:00
										 |  |  |         self.top.destroy() | 
					
						
							| 
									
										
										
										
											1998-10-10 18:48:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     localsframe = None | 
					
						
							|  |  |  |     localsviewer = None | 
					
						
							|  |  |  |     localsdict = None | 
					
						
							|  |  |  |     globalsframe = None | 
					
						
							|  |  |  |     globalsviewer = None | 
					
						
							|  |  |  |     globalsdict = None | 
					
						
							|  |  |  |     curframe = None | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-10-16 04:02:28 +00:00
										 |  |  |     def show_frame(self, (frame, lineno)): | 
					
						
							| 
									
										
										
										
											1998-10-10 18:48:31 +00:00
										 |  |  |         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 | 
					
						
							| 
									
										
										
										
											1999-01-02 21:28:54 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-10-10 18:48:31 +00:00
										 |  |  |     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") | 
					
						
							| 
									
										
										
										
											1999-01-02 21:28:54 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-10-10 18:48:31 +00:00
										 |  |  |     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() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-10-16 16:10:45 +00:00
										 |  |  | class StackViewer(ScrolledList): | 
					
						
							| 
									
										
										
										
											1999-01-02 21:28:54 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-10-16 04:02:28 +00:00
										 |  |  |     def __init__(self, master, flist, browser): | 
					
						
							|  |  |  |         ScrolledList.__init__(self, master) | 
					
						
							|  |  |  |         self.flist = flist | 
					
						
							|  |  |  |         self.browser = browser | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-10-16 16:10:45 +00:00
										 |  |  |     def load_stack(self, stack, index=None): | 
					
						
							| 
									
										
										
										
											1998-10-16 04:02:28 +00:00
										 |  |  |         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) | 
					
						
							| 
									
										
										
										
											1998-10-16 18:59:39 +00:00
										 |  |  |         for i in range(len(stack)): | 
					
						
							|  |  |  |             frame, lineno = stack[i] | 
					
						
							| 
									
										
										
										
											1998-10-16 04:02:28 +00:00
										 |  |  |             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) | 
					
						
							| 
									
										
										
										
											1998-10-16 18:59:39 +00:00
										 |  |  |             if i == index: | 
					
						
							|  |  |  |                 item = "> " + item | 
					
						
							| 
									
										
										
										
											1998-10-16 04:02:28 +00:00
										 |  |  |             self.append(item) | 
					
						
							| 
									
										
										
										
											1998-10-16 16:10:45 +00:00
										 |  |  |         if index is not None: | 
					
						
							|  |  |  |             self.select(index) | 
					
						
							| 
									
										
										
										
											1998-10-16 04:02:28 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     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) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def on_select(self, index): | 
					
						
							|  |  |  |         self.browser.show_frame(self.stack[index]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     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") | 
					
						
							|  |  |  |         self.browser.show_frame(self.stack[index]) | 
					
						
							| 
									
										
										
										
											1999-01-02 21:28:54 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-10-16 04:02:28 +00:00
										 |  |  |     def show_source(self, index): | 
					
						
							|  |  |  |         frame, lineno = self.stack[index] | 
					
						
							|  |  |  |         code = frame.f_code | 
					
						
							|  |  |  |         filename = code.co_filename | 
					
						
							|  |  |  |         if os.path.isfile(filename): | 
					
						
							|  |  |  |             edit = self.flist.open(filename) | 
					
						
							|  |  |  |             if edit: | 
					
						
							|  |  |  |                 edit.gotoline(lineno) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def get_stack(t=None, f=None): | 
					
						
							| 
									
										
										
										
											1998-10-10 18:48:31 +00:00
										 |  |  |     if t is None: | 
					
						
							|  |  |  |         t = sys.last_traceback | 
					
						
							|  |  |  |     stack = [] | 
					
						
							|  |  |  |     if t and t.tb_frame is f: | 
					
						
							|  |  |  |         t = t.tb_next | 
					
						
							|  |  |  |     while f is not None: | 
					
						
							|  |  |  |         stack.append((f, f.f_lineno)) | 
					
						
							|  |  |  |         if f is self.botframe: | 
					
						
							| 
									
										
										
										
											1999-01-02 21:28:54 +00:00
										 |  |  |             break | 
					
						
							| 
									
										
										
										
											1998-10-10 18:48:31 +00:00
										 |  |  |         f = f.f_back | 
					
						
							|  |  |  |     stack.reverse() | 
					
						
							|  |  |  |     while t is not None: | 
					
						
							|  |  |  |         stack.append((t.tb_frame, t.tb_lineno)) | 
					
						
							|  |  |  |         t = t.tb_next | 
					
						
							|  |  |  |     return stack | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-10-10 19:15:32 +00:00
										 |  |  | def getexception(type=None, value=None): | 
					
						
							|  |  |  |     if type is None: | 
					
						
							|  |  |  |         type = sys.last_type | 
					
						
							|  |  |  |         value = sys.last_value | 
					
						
							|  |  |  |     if hasattr(type, "__name__"): | 
					
						
							|  |  |  |         type = type.__name__ | 
					
						
							|  |  |  |     s = str(type) | 
					
						
							|  |  |  |     if value is not None: | 
					
						
							|  |  |  |         s = s + ": " + str(value) | 
					
						
							|  |  |  |     return s | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-10-10 18:48:31 +00:00
										 |  |  | class NamespaceViewer: | 
					
						
							| 
									
										
										
										
											1999-01-02 21:28:54 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-10-16 18:59:39 +00:00
										 |  |  |     def __init__(self, master, title, dict=None): | 
					
						
							| 
									
										
										
										
											1998-10-10 18:48:31 +00:00
										 |  |  |         width = 0 | 
					
						
							| 
									
										
										
										
											1998-10-16 18:59:39 +00:00
										 |  |  |         height = 40 | 
					
						
							|  |  |  |         if dict: | 
					
						
							|  |  |  |             height = 20*len(dict) # XXX 20 == observed height of Entry widget | 
					
						
							| 
									
										
										
										
											1998-10-16 04:02:28 +00:00
										 |  |  |         self.master = master | 
					
						
							| 
									
										
										
										
											1998-10-10 18:48:31 +00:00
										 |  |  |         self.title = title | 
					
						
							|  |  |  |         self.repr = Repr() | 
					
						
							|  |  |  |         self.repr.maxstring = 60 | 
					
						
							|  |  |  |         self.repr.maxother = 60 | 
					
						
							| 
									
										
										
										
											1998-10-16 18:59:39 +00:00
										 |  |  |         self.frame = frame = Frame(master) | 
					
						
							|  |  |  |         self.frame.pack(expand=1, fill="both") | 
					
						
							|  |  |  |         self.label = Label(frame, text=title, borderwidth=2, relief="groove") | 
					
						
							| 
									
										
										
										
											1998-10-10 18:48:31 +00:00
										 |  |  |         self.label.pack(fill="x") | 
					
						
							| 
									
										
										
										
											1998-10-16 18:59:39 +00:00
										 |  |  |         self.vbar = vbar = Scrollbar(frame, name="vbar") | 
					
						
							| 
									
										
										
										
											1998-10-10 18:48:31 +00:00
										 |  |  |         vbar.pack(side="right", fill="y") | 
					
						
							| 
									
										
										
										
											1998-10-16 18:59:39 +00:00
										 |  |  |         self.canvas = canvas = Canvas(frame, | 
					
						
							| 
									
										
										
										
											1998-10-10 18:48:31 +00:00
										 |  |  |                                       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") | 
					
						
							| 
									
										
										
										
											1998-10-16 18:59:39 +00:00
										 |  |  |         self.load_dict(dict) | 
					
						
							| 
									
										
										
										
											1999-01-02 21:28:54 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-10-16 21:10:12 +00:00
										 |  |  |     dict = -1 | 
					
						
							| 
									
										
										
										
											1999-01-02 21:28:54 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-10-19 02:19:30 +00:00
										 |  |  |     def load_dict(self, dict, force=0): | 
					
						
							|  |  |  |         if dict is self.dict and not force: | 
					
						
							| 
									
										
										
										
											1998-10-16 21:10:12 +00:00
										 |  |  |             return | 
					
						
							| 
									
										
										
										
											1998-10-16 18:59:39 +00:00
										 |  |  |         subframe = self.subframe | 
					
						
							|  |  |  |         frame = self.frame | 
					
						
							|  |  |  |         for c in subframe.children.values(): | 
					
						
							|  |  |  |             c.destroy() | 
					
						
							| 
									
										
										
										
											1998-10-16 21:10:12 +00:00
										 |  |  |         self.dict = None | 
					
						
							| 
									
										
										
										
											1998-10-16 18:59:39 +00:00
										 |  |  |         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 | 
					
						
							| 
									
										
										
										
											1998-10-16 21:10:12 +00:00
										 |  |  |         self.dict = dict | 
					
						
							| 
									
										
										
										
											1998-10-16 18:59:39 +00:00
										 |  |  |         # XXX Could we use a <Configure> callback for the following? | 
					
						
							| 
									
										
										
										
											1998-10-16 04:02:28 +00:00
										 |  |  |         subframe.update_idletasks() # Alas! | 
					
						
							| 
									
										
										
										
											1998-10-10 18:48:31 +00:00
										 |  |  |         width = subframe.winfo_reqwidth() | 
					
						
							|  |  |  |         height = subframe.winfo_reqheight() | 
					
						
							| 
									
										
										
										
											1998-10-16 18:59:39 +00:00
										 |  |  |         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) | 
					
						
							| 
									
										
										
										
											1998-10-10 18:48:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def close(self): | 
					
						
							| 
									
										
										
										
											1998-10-16 18:59:39 +00:00
										 |  |  |         self.frame.destroy() |