17db96d56Sopenharmony_ci# XXX TO DO: 27db96d56Sopenharmony_ci# - popup menu 37db96d56Sopenharmony_ci# - support partial or total redisplay 47db96d56Sopenharmony_ci# - more doc strings 57db96d56Sopenharmony_ci# - tooltips 67db96d56Sopenharmony_ci 77db96d56Sopenharmony_ci# object browser 87db96d56Sopenharmony_ci 97db96d56Sopenharmony_ci# XXX TO DO: 107db96d56Sopenharmony_ci# - for classes/modules, add "open source" to object browser 117db96d56Sopenharmony_cifrom reprlib import Repr 127db96d56Sopenharmony_ci 137db96d56Sopenharmony_cifrom idlelib.tree import TreeItem, TreeNode, ScrolledCanvas 147db96d56Sopenharmony_ci 157db96d56Sopenharmony_cimyrepr = Repr() 167db96d56Sopenharmony_cimyrepr.maxstring = 100 177db96d56Sopenharmony_cimyrepr.maxother = 100 187db96d56Sopenharmony_ci 197db96d56Sopenharmony_ciclass ObjectTreeItem(TreeItem): 207db96d56Sopenharmony_ci def __init__(self, labeltext, object, setfunction=None): 217db96d56Sopenharmony_ci self.labeltext = labeltext 227db96d56Sopenharmony_ci self.object = object 237db96d56Sopenharmony_ci self.setfunction = setfunction 247db96d56Sopenharmony_ci def GetLabelText(self): 257db96d56Sopenharmony_ci return self.labeltext 267db96d56Sopenharmony_ci def GetText(self): 277db96d56Sopenharmony_ci return myrepr.repr(self.object) 287db96d56Sopenharmony_ci def GetIconName(self): 297db96d56Sopenharmony_ci if not self.IsExpandable(): 307db96d56Sopenharmony_ci return "python" 317db96d56Sopenharmony_ci def IsEditable(self): 327db96d56Sopenharmony_ci return self.setfunction is not None 337db96d56Sopenharmony_ci def SetText(self, text): 347db96d56Sopenharmony_ci try: 357db96d56Sopenharmony_ci value = eval(text) 367db96d56Sopenharmony_ci self.setfunction(value) 377db96d56Sopenharmony_ci except: 387db96d56Sopenharmony_ci pass 397db96d56Sopenharmony_ci else: 407db96d56Sopenharmony_ci self.object = value 417db96d56Sopenharmony_ci def IsExpandable(self): 427db96d56Sopenharmony_ci return not not dir(self.object) 437db96d56Sopenharmony_ci def GetSubList(self): 447db96d56Sopenharmony_ci keys = dir(self.object) 457db96d56Sopenharmony_ci sublist = [] 467db96d56Sopenharmony_ci for key in keys: 477db96d56Sopenharmony_ci try: 487db96d56Sopenharmony_ci value = getattr(self.object, key) 497db96d56Sopenharmony_ci except AttributeError: 507db96d56Sopenharmony_ci continue 517db96d56Sopenharmony_ci item = make_objecttreeitem( 527db96d56Sopenharmony_ci str(key) + " =", 537db96d56Sopenharmony_ci value, 547db96d56Sopenharmony_ci lambda value, key=key, object=self.object: 557db96d56Sopenharmony_ci setattr(object, key, value)) 567db96d56Sopenharmony_ci sublist.append(item) 577db96d56Sopenharmony_ci return sublist 587db96d56Sopenharmony_ci 597db96d56Sopenharmony_ciclass ClassTreeItem(ObjectTreeItem): 607db96d56Sopenharmony_ci def IsExpandable(self): 617db96d56Sopenharmony_ci return True 627db96d56Sopenharmony_ci def GetSubList(self): 637db96d56Sopenharmony_ci sublist = ObjectTreeItem.GetSubList(self) 647db96d56Sopenharmony_ci if len(self.object.__bases__) == 1: 657db96d56Sopenharmony_ci item = make_objecttreeitem("__bases__[0] =", 667db96d56Sopenharmony_ci self.object.__bases__[0]) 677db96d56Sopenharmony_ci else: 687db96d56Sopenharmony_ci item = make_objecttreeitem("__bases__ =", self.object.__bases__) 697db96d56Sopenharmony_ci sublist.insert(0, item) 707db96d56Sopenharmony_ci return sublist 717db96d56Sopenharmony_ci 727db96d56Sopenharmony_ciclass AtomicObjectTreeItem(ObjectTreeItem): 737db96d56Sopenharmony_ci def IsExpandable(self): 747db96d56Sopenharmony_ci return False 757db96d56Sopenharmony_ci 767db96d56Sopenharmony_ciclass SequenceTreeItem(ObjectTreeItem): 777db96d56Sopenharmony_ci def IsExpandable(self): 787db96d56Sopenharmony_ci return len(self.object) > 0 797db96d56Sopenharmony_ci def keys(self): 807db96d56Sopenharmony_ci return range(len(self.object)) 817db96d56Sopenharmony_ci def GetSubList(self): 827db96d56Sopenharmony_ci sublist = [] 837db96d56Sopenharmony_ci for key in self.keys(): 847db96d56Sopenharmony_ci try: 857db96d56Sopenharmony_ci value = self.object[key] 867db96d56Sopenharmony_ci except KeyError: 877db96d56Sopenharmony_ci continue 887db96d56Sopenharmony_ci def setfunction(value, key=key, object=self.object): 897db96d56Sopenharmony_ci object[key] = value 907db96d56Sopenharmony_ci item = make_objecttreeitem(f"{key!r}:", value, setfunction) 917db96d56Sopenharmony_ci sublist.append(item) 927db96d56Sopenharmony_ci return sublist 937db96d56Sopenharmony_ci 947db96d56Sopenharmony_ciclass DictTreeItem(SequenceTreeItem): 957db96d56Sopenharmony_ci def keys(self): 967db96d56Sopenharmony_ci keys = list(self.object.keys()) 977db96d56Sopenharmony_ci try: 987db96d56Sopenharmony_ci keys.sort() 997db96d56Sopenharmony_ci except: 1007db96d56Sopenharmony_ci pass 1017db96d56Sopenharmony_ci return keys 1027db96d56Sopenharmony_ci 1037db96d56Sopenharmony_cidispatch = { 1047db96d56Sopenharmony_ci int: AtomicObjectTreeItem, 1057db96d56Sopenharmony_ci float: AtomicObjectTreeItem, 1067db96d56Sopenharmony_ci str: AtomicObjectTreeItem, 1077db96d56Sopenharmony_ci tuple: SequenceTreeItem, 1087db96d56Sopenharmony_ci list: SequenceTreeItem, 1097db96d56Sopenharmony_ci dict: DictTreeItem, 1107db96d56Sopenharmony_ci type: ClassTreeItem, 1117db96d56Sopenharmony_ci} 1127db96d56Sopenharmony_ci 1137db96d56Sopenharmony_cidef make_objecttreeitem(labeltext, object, setfunction=None): 1147db96d56Sopenharmony_ci t = type(object) 1157db96d56Sopenharmony_ci if t in dispatch: 1167db96d56Sopenharmony_ci c = dispatch[t] 1177db96d56Sopenharmony_ci else: 1187db96d56Sopenharmony_ci c = ObjectTreeItem 1197db96d56Sopenharmony_ci return c(labeltext, object, setfunction) 1207db96d56Sopenharmony_ci 1217db96d56Sopenharmony_ci 1227db96d56Sopenharmony_cidef _object_browser(parent): # htest # 1237db96d56Sopenharmony_ci import sys 1247db96d56Sopenharmony_ci from tkinter import Toplevel 1257db96d56Sopenharmony_ci top = Toplevel(parent) 1267db96d56Sopenharmony_ci top.title("Test debug object browser") 1277db96d56Sopenharmony_ci x, y = map(int, parent.geometry().split('+')[1:]) 1287db96d56Sopenharmony_ci top.geometry("+%d+%d" % (x + 100, y + 175)) 1297db96d56Sopenharmony_ci top.configure(bd=0, bg="yellow") 1307db96d56Sopenharmony_ci top.focus_set() 1317db96d56Sopenharmony_ci sc = ScrolledCanvas(top, bg="white", highlightthickness=0, takefocus=1) 1327db96d56Sopenharmony_ci sc.frame.pack(expand=1, fill="both") 1337db96d56Sopenharmony_ci item = make_objecttreeitem("sys", sys) 1347db96d56Sopenharmony_ci node = TreeNode(sc.canvas, None, item) 1357db96d56Sopenharmony_ci node.update() 1367db96d56Sopenharmony_ci 1377db96d56Sopenharmony_ciif __name__ == '__main__': 1387db96d56Sopenharmony_ci from unittest import main 1397db96d56Sopenharmony_ci main('idlelib.idle_test.test_debugobj', verbosity=2, exit=False) 1407db96d56Sopenharmony_ci 1417db96d56Sopenharmony_ci from idlelib.idle_test.htest import run 1427db96d56Sopenharmony_ci run(_object_browser) 143