blob: c8c802ce2a68b8eaff03a1bf2da6249724430b33 [file] [log] [blame]
Kurt B. Kaisera4c9be82001-07-14 05:15:29 +00001import os
2import sys
David Scherer7aced172000-08-15 01:13:23 +00003import linecache
Terry Jan Reedya2fc99e2014-05-25 18:44:05 -04004import re
5import tkinter as tk
David Scherer7aced172000-08-15 01:13:23 +00006
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -04007from idlelib.tree import TreeNode, TreeItem, ScrolledCanvas
8from idlelib.debugobj import ObjectTreeItem, make_objecttreeitem
David Scherer7aced172000-08-15 01:13:23 +00009
Kurt B. Kaisera4c9be82001-07-14 05:15:29 +000010def StackBrowser(root, flist=None, tb=None, top=None):
11 if top is None:
Terry Jan Reedya78ebe62015-08-18 13:26:57 -040012 top = tk.Toplevel(root)
David Scherer7aced172000-08-15 01:13:23 +000013 sc = ScrolledCanvas(top, bg="white", highlightthickness=0)
14 sc.frame.pack(expand=1, fill="both")
Kurt B. Kaisera4c9be82001-07-14 05:15:29 +000015 item = StackTreeItem(flist, tb)
David Scherer7aced172000-08-15 01:13:23 +000016 node = TreeNode(sc.canvas, None, item)
17 node.expand()
18
19class StackTreeItem(TreeItem):
20
Kurt B. Kaisera4c9be82001-07-14 05:15:29 +000021 def __init__(self, flist=None, tb=None):
David Scherer7aced172000-08-15 01:13:23 +000022 self.flist = flist
Kurt B. Kaiser5f7c4b32002-12-02 05:08:54 +000023 self.stack = self.get_stack(tb)
24 self.text = self.get_exception()
25
26 def get_stack(self, tb):
27 if tb is None:
28 tb = sys.last_traceback
29 stack = []
30 if tb and tb.tb_frame is None:
31 tb = tb.tb_next
32 while tb is not None:
33 stack.append((tb.tb_frame, tb.tb_lineno))
34 tb = tb.tb_next
35 return stack
36
37 def get_exception(self):
38 type = sys.last_type
39 value = sys.last_value
40 if hasattr(type, "__name__"):
41 type = type.__name__
42 s = str(type)
43 if value is not None:
44 s = s + ": " + str(value)
45 return s
David Scherer7aced172000-08-15 01:13:23 +000046
47 def GetText(self):
48 return self.text
49
50 def GetSubList(self):
51 sublist = []
52 for info in self.stack:
53 item = FrameTreeItem(info, self.flist)
54 sublist.append(item)
55 return sublist
56
57class FrameTreeItem(TreeItem):
58
59 def __init__(self, info, flist):
60 self.info = info
61 self.flist = flist
62
63 def GetText(self):
64 frame, lineno = self.info
65 try:
66 modname = frame.f_globals["__name__"]
67 except:
68 modname = "?"
69 code = frame.f_code
70 filename = code.co_filename
71 funcname = code.co_name
72 sourceline = linecache.getline(filename, lineno)
Kurt B. Kaiser7879ad02002-09-18 03:15:56 +000073 sourceline = sourceline.strip()
David Scherer7aced172000-08-15 01:13:23 +000074 if funcname in ("?", "", None):
75 item = "%s, line %d: %s" % (modname, lineno, sourceline)
76 else:
77 item = "%s.%s(...), line %d: %s" % (modname, funcname,
78 lineno, sourceline)
David Scherer7aced172000-08-15 01:13:23 +000079 return item
80
81 def GetSubList(self):
82 frame, lineno = self.info
83 sublist = []
84 if frame.f_globals is not frame.f_locals:
85 item = VariablesTreeItem("<locals>", frame.f_locals, self.flist)
86 sublist.append(item)
87 item = VariablesTreeItem("<globals>", frame.f_globals, self.flist)
88 sublist.append(item)
89 return sublist
90
91 def OnDoubleClick(self):
92 if self.flist:
93 frame, lineno = self.info
94 filename = frame.f_code.co_filename
Kurt B. Kaisera4c9be82001-07-14 05:15:29 +000095 if os.path.isfile(filename):
96 self.flist.gotofileline(filename, lineno)
David Scherer7aced172000-08-15 01:13:23 +000097
98class VariablesTreeItem(ObjectTreeItem):
99
100 def GetText(self):
101 return self.labeltext
102
103 def GetLabelText(self):
104 return None
105
106 def IsExpandable(self):
107 return len(self.object) > 0
108
David Scherer7aced172000-08-15 01:13:23 +0000109 def GetSubList(self):
110 sublist = []
Terry Jan Reedya78ebe62015-08-18 13:26:57 -0400111 for key in self.object.keys():
David Scherer7aced172000-08-15 01:13:23 +0000112 try:
113 value = self.object[key]
114 except KeyError:
115 continue
116 def setfunction(value, key=key, object=self.object):
117 object[key] = value
118 item = make_objecttreeitem(key + " =", value, setfunction)
119 sublist.append(item)
120 return sublist
Terry Jan Reedya2fc99e2014-05-25 18:44:05 -0400121
Terry Jan Reedya7480322016-07-10 17:28:10 -0400122def _stack_viewer(parent): # htest #
Terry Jan Reedy6cf0e132016-07-15 02:43:03 -0400123 from idlelib.pyshell import PyShellFileList
Terry Jan Reedyb60adc52016-06-21 18:41:38 -0400124 top = tk.Toplevel(parent)
125 top.title("Test StackViewer")
Terry Jan Reedya7480322016-07-10 17:28:10 -0400126 x, y = map(int, parent.geometry().split('+')[1:])
127 top.geometry("+%d+%d" % (x + 50, y + 175))
Terry Jan Reedyb60adc52016-06-21 18:41:38 -0400128 flist = PyShellFileList(top)
Terry Jan Reedya2fc99e2014-05-25 18:44:05 -0400129 try: # to obtain a traceback object
Terry Jan Reedy092b3cf2014-07-01 21:33:31 -0400130 intentional_name_error
131 except NameError:
Terry Jan Reedya2fc99e2014-05-25 18:44:05 -0400132 exc_type, exc_value, exc_tb = sys.exc_info()
133
134 # inject stack trace to sys
135 sys.last_type = exc_type
136 sys.last_value = exc_value
137 sys.last_traceback = exc_tb
138
Terry Jan Reedyb60adc52016-06-21 18:41:38 -0400139 StackBrowser(top, flist=flist, top=top, tb=exc_tb)
Terry Jan Reedya2fc99e2014-05-25 18:44:05 -0400140
141 # restore sys to original state
142 del sys.last_type
143 del sys.last_value
144 del sys.last_traceback
145
146if __name__ == '__main__':
147 from idlelib.idle_test.htest import run
148 run(_stack_viewer)