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