jpayne@69
|
1 # XXX TO DO:
|
jpayne@69
|
2 # - popup menu
|
jpayne@69
|
3 # - support partial or total redisplay
|
jpayne@69
|
4 # - more doc strings
|
jpayne@69
|
5 # - tooltips
|
jpayne@69
|
6
|
jpayne@69
|
7 # object browser
|
jpayne@69
|
8
|
jpayne@69
|
9 # XXX TO DO:
|
jpayne@69
|
10 # - for classes/modules, add "open source" to object browser
|
jpayne@69
|
11 from reprlib import Repr
|
jpayne@69
|
12
|
jpayne@69
|
13 from idlelib.tree import TreeItem, TreeNode, ScrolledCanvas
|
jpayne@69
|
14
|
jpayne@69
|
15 myrepr = Repr()
|
jpayne@69
|
16 myrepr.maxstring = 100
|
jpayne@69
|
17 myrepr.maxother = 100
|
jpayne@69
|
18
|
jpayne@69
|
19 class ObjectTreeItem(TreeItem):
|
jpayne@69
|
20 def __init__(self, labeltext, object, setfunction=None):
|
jpayne@69
|
21 self.labeltext = labeltext
|
jpayne@69
|
22 self.object = object
|
jpayne@69
|
23 self.setfunction = setfunction
|
jpayne@69
|
24 def GetLabelText(self):
|
jpayne@69
|
25 return self.labeltext
|
jpayne@69
|
26 def GetText(self):
|
jpayne@69
|
27 return myrepr.repr(self.object)
|
jpayne@69
|
28 def GetIconName(self):
|
jpayne@69
|
29 if not self.IsExpandable():
|
jpayne@69
|
30 return "python"
|
jpayne@69
|
31 def IsEditable(self):
|
jpayne@69
|
32 return self.setfunction is not None
|
jpayne@69
|
33 def SetText(self, text):
|
jpayne@69
|
34 try:
|
jpayne@69
|
35 value = eval(text)
|
jpayne@69
|
36 self.setfunction(value)
|
jpayne@69
|
37 except:
|
jpayne@69
|
38 pass
|
jpayne@69
|
39 else:
|
jpayne@69
|
40 self.object = value
|
jpayne@69
|
41 def IsExpandable(self):
|
jpayne@69
|
42 return not not dir(self.object)
|
jpayne@69
|
43 def GetSubList(self):
|
jpayne@69
|
44 keys = dir(self.object)
|
jpayne@69
|
45 sublist = []
|
jpayne@69
|
46 for key in keys:
|
jpayne@69
|
47 try:
|
jpayne@69
|
48 value = getattr(self.object, key)
|
jpayne@69
|
49 except AttributeError:
|
jpayne@69
|
50 continue
|
jpayne@69
|
51 item = make_objecttreeitem(
|
jpayne@69
|
52 str(key) + " =",
|
jpayne@69
|
53 value,
|
jpayne@69
|
54 lambda value, key=key, object=self.object:
|
jpayne@69
|
55 setattr(object, key, value))
|
jpayne@69
|
56 sublist.append(item)
|
jpayne@69
|
57 return sublist
|
jpayne@69
|
58
|
jpayne@69
|
59 class ClassTreeItem(ObjectTreeItem):
|
jpayne@69
|
60 def IsExpandable(self):
|
jpayne@69
|
61 return True
|
jpayne@69
|
62 def GetSubList(self):
|
jpayne@69
|
63 sublist = ObjectTreeItem.GetSubList(self)
|
jpayne@69
|
64 if len(self.object.__bases__) == 1:
|
jpayne@69
|
65 item = make_objecttreeitem("__bases__[0] =",
|
jpayne@69
|
66 self.object.__bases__[0])
|
jpayne@69
|
67 else:
|
jpayne@69
|
68 item = make_objecttreeitem("__bases__ =", self.object.__bases__)
|
jpayne@69
|
69 sublist.insert(0, item)
|
jpayne@69
|
70 return sublist
|
jpayne@69
|
71
|
jpayne@69
|
72 class AtomicObjectTreeItem(ObjectTreeItem):
|
jpayne@69
|
73 def IsExpandable(self):
|
jpayne@69
|
74 return False
|
jpayne@69
|
75
|
jpayne@69
|
76 class SequenceTreeItem(ObjectTreeItem):
|
jpayne@69
|
77 def IsExpandable(self):
|
jpayne@69
|
78 return len(self.object) > 0
|
jpayne@69
|
79 def keys(self):
|
jpayne@69
|
80 return range(len(self.object))
|
jpayne@69
|
81 def GetSubList(self):
|
jpayne@69
|
82 sublist = []
|
jpayne@69
|
83 for key in self.keys():
|
jpayne@69
|
84 try:
|
jpayne@69
|
85 value = self.object[key]
|
jpayne@69
|
86 except KeyError:
|
jpayne@69
|
87 continue
|
jpayne@69
|
88 def setfunction(value, key=key, object=self.object):
|
jpayne@69
|
89 object[key] = value
|
jpayne@69
|
90 item = make_objecttreeitem("%r:" % (key,), value, setfunction)
|
jpayne@69
|
91 sublist.append(item)
|
jpayne@69
|
92 return sublist
|
jpayne@69
|
93
|
jpayne@69
|
94 class DictTreeItem(SequenceTreeItem):
|
jpayne@69
|
95 def keys(self):
|
jpayne@69
|
96 keys = list(self.object.keys())
|
jpayne@69
|
97 try:
|
jpayne@69
|
98 keys.sort()
|
jpayne@69
|
99 except:
|
jpayne@69
|
100 pass
|
jpayne@69
|
101 return keys
|
jpayne@69
|
102
|
jpayne@69
|
103 dispatch = {
|
jpayne@69
|
104 int: AtomicObjectTreeItem,
|
jpayne@69
|
105 float: AtomicObjectTreeItem,
|
jpayne@69
|
106 str: AtomicObjectTreeItem,
|
jpayne@69
|
107 tuple: SequenceTreeItem,
|
jpayne@69
|
108 list: SequenceTreeItem,
|
jpayne@69
|
109 dict: DictTreeItem,
|
jpayne@69
|
110 type: ClassTreeItem,
|
jpayne@69
|
111 }
|
jpayne@69
|
112
|
jpayne@69
|
113 def make_objecttreeitem(labeltext, object, setfunction=None):
|
jpayne@69
|
114 t = type(object)
|
jpayne@69
|
115 if t in dispatch:
|
jpayne@69
|
116 c = dispatch[t]
|
jpayne@69
|
117 else:
|
jpayne@69
|
118 c = ObjectTreeItem
|
jpayne@69
|
119 return c(labeltext, object, setfunction)
|
jpayne@69
|
120
|
jpayne@69
|
121
|
jpayne@69
|
122 def _object_browser(parent): # htest #
|
jpayne@69
|
123 import sys
|
jpayne@69
|
124 from tkinter import Toplevel
|
jpayne@69
|
125 top = Toplevel(parent)
|
jpayne@69
|
126 top.title("Test debug object browser")
|
jpayne@69
|
127 x, y = map(int, parent.geometry().split('+')[1:])
|
jpayne@69
|
128 top.geometry("+%d+%d" % (x + 100, y + 175))
|
jpayne@69
|
129 top.configure(bd=0, bg="yellow")
|
jpayne@69
|
130 top.focus_set()
|
jpayne@69
|
131 sc = ScrolledCanvas(top, bg="white", highlightthickness=0, takefocus=1)
|
jpayne@69
|
132 sc.frame.pack(expand=1, fill="both")
|
jpayne@69
|
133 item = make_objecttreeitem("sys", sys)
|
jpayne@69
|
134 node = TreeNode(sc.canvas, None, item)
|
jpayne@69
|
135 node.update()
|
jpayne@69
|
136
|
jpayne@69
|
137 if __name__ == '__main__':
|
jpayne@69
|
138 from unittest import main
|
jpayne@69
|
139 main('idlelib.idle_test.test_debugobj', verbosity=2, exit=False)
|
jpayne@69
|
140
|
jpayne@69
|
141 from idlelib.idle_test.htest import run
|
jpayne@69
|
142 run(_object_browser)
|