|
1 import os |
|
2 import sys |
|
3 import linecache |
|
4 |
|
5 from TreeWidget import TreeNode, TreeItem, ScrolledCanvas |
|
6 from ObjectBrowser import ObjectTreeItem, make_objecttreeitem |
|
7 |
|
8 def StackBrowser(root, flist=None, tb=None, top=None): |
|
9 if top is None: |
|
10 from Tkinter import Toplevel |
|
11 top = Toplevel(root) |
|
12 sc = ScrolledCanvas(top, bg="white", highlightthickness=0) |
|
13 sc.frame.pack(expand=1, fill="both") |
|
14 item = StackTreeItem(flist, tb) |
|
15 node = TreeNode(sc.canvas, None, item) |
|
16 node.expand() |
|
17 |
|
18 class StackTreeItem(TreeItem): |
|
19 |
|
20 def __init__(self, flist=None, tb=None): |
|
21 self.flist = flist |
|
22 self.stack = self.get_stack(tb) |
|
23 self.text = self.get_exception() |
|
24 |
|
25 def get_stack(self, tb): |
|
26 if tb is None: |
|
27 tb = sys.last_traceback |
|
28 stack = [] |
|
29 if tb and tb.tb_frame is None: |
|
30 tb = tb.tb_next |
|
31 while tb is not None: |
|
32 stack.append((tb.tb_frame, tb.tb_lineno)) |
|
33 tb = tb.tb_next |
|
34 return stack |
|
35 |
|
36 def get_exception(self): |
|
37 type = sys.last_type |
|
38 value = sys.last_value |
|
39 if hasattr(type, "__name__"): |
|
40 type = type.__name__ |
|
41 s = str(type) |
|
42 if value is not None: |
|
43 s = s + ": " + str(value) |
|
44 return s |
|
45 |
|
46 def GetText(self): |
|
47 return self.text |
|
48 |
|
49 def GetSubList(self): |
|
50 sublist = [] |
|
51 for info in self.stack: |
|
52 item = FrameTreeItem(info, self.flist) |
|
53 sublist.append(item) |
|
54 return sublist |
|
55 |
|
56 class FrameTreeItem(TreeItem): |
|
57 |
|
58 def __init__(self, info, flist): |
|
59 self.info = info |
|
60 self.flist = flist |
|
61 |
|
62 def GetText(self): |
|
63 frame, lineno = self.info |
|
64 try: |
|
65 modname = frame.f_globals["__name__"] |
|
66 except: |
|
67 modname = "?" |
|
68 code = frame.f_code |
|
69 filename = code.co_filename |
|
70 funcname = code.co_name |
|
71 sourceline = linecache.getline(filename, lineno) |
|
72 sourceline = sourceline.strip() |
|
73 if funcname in ("?", "", None): |
|
74 item = "%s, line %d: %s" % (modname, lineno, sourceline) |
|
75 else: |
|
76 item = "%s.%s(...), line %d: %s" % (modname, funcname, |
|
77 lineno, sourceline) |
|
78 return item |
|
79 |
|
80 def GetSubList(self): |
|
81 frame, lineno = self.info |
|
82 sublist = [] |
|
83 if frame.f_globals is not frame.f_locals: |
|
84 item = VariablesTreeItem("<locals>", frame.f_locals, self.flist) |
|
85 sublist.append(item) |
|
86 item = VariablesTreeItem("<globals>", frame.f_globals, self.flist) |
|
87 sublist.append(item) |
|
88 return sublist |
|
89 |
|
90 def OnDoubleClick(self): |
|
91 if self.flist: |
|
92 frame, lineno = self.info |
|
93 filename = frame.f_code.co_filename |
|
94 if os.path.isfile(filename): |
|
95 self.flist.gotofileline(filename, lineno) |
|
96 |
|
97 class VariablesTreeItem(ObjectTreeItem): |
|
98 |
|
99 def GetText(self): |
|
100 return self.labeltext |
|
101 |
|
102 def GetLabelText(self): |
|
103 return None |
|
104 |
|
105 def IsExpandable(self): |
|
106 return len(self.object) > 0 |
|
107 |
|
108 def keys(self): |
|
109 return self.object.keys() |
|
110 |
|
111 def GetSubList(self): |
|
112 sublist = [] |
|
113 for key in self.keys(): |
|
114 try: |
|
115 value = self.object[key] |
|
116 except KeyError: |
|
117 continue |
|
118 def setfunction(value, key=key, object=self.object): |
|
119 object[key] = value |
|
120 item = make_objecttreeitem(key + " =", value, setfunction) |
|
121 sublist.append(item) |
|
122 return sublist |
|
123 |
|
124 |
|
125 def _test(): |
|
126 try: |
|
127 import testcode |
|
128 reload(testcode) |
|
129 except: |
|
130 sys.last_type, sys.last_value, sys.last_traceback = sys.exc_info() |
|
131 from Tkinter import Tk |
|
132 root = Tk() |
|
133 StackBrowser(None, top=root) |
|
134 root.mainloop() |
|
135 |
|
136 if __name__ == "__main__": |
|
137 _test() |