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