jpayne@68: # XXX TO DO: jpayne@68: # - popup menu jpayne@68: # - support partial or total redisplay jpayne@68: # - more doc strings jpayne@68: # - tooltips jpayne@68: jpayne@68: # object browser jpayne@68: jpayne@68: # XXX TO DO: jpayne@68: # - for classes/modules, add "open source" to object browser jpayne@68: from reprlib import Repr jpayne@68: jpayne@68: from idlelib.tree import TreeItem, TreeNode, ScrolledCanvas jpayne@68: jpayne@68: myrepr = Repr() jpayne@68: myrepr.maxstring = 100 jpayne@68: myrepr.maxother = 100 jpayne@68: jpayne@68: class ObjectTreeItem(TreeItem): jpayne@68: def __init__(self, labeltext, object, setfunction=None): jpayne@68: self.labeltext = labeltext jpayne@68: self.object = object jpayne@68: self.setfunction = setfunction jpayne@68: def GetLabelText(self): jpayne@68: return self.labeltext jpayne@68: def GetText(self): jpayne@68: return myrepr.repr(self.object) jpayne@68: def GetIconName(self): jpayne@68: if not self.IsExpandable(): jpayne@68: return "python" jpayne@68: def IsEditable(self): jpayne@68: return self.setfunction is not None jpayne@68: def SetText(self, text): jpayne@68: try: jpayne@68: value = eval(text) jpayne@68: self.setfunction(value) jpayne@68: except: jpayne@68: pass jpayne@68: else: jpayne@68: self.object = value jpayne@68: def IsExpandable(self): jpayne@68: return not not dir(self.object) jpayne@68: def GetSubList(self): jpayne@68: keys = dir(self.object) jpayne@68: sublist = [] jpayne@68: for key in keys: jpayne@68: try: jpayne@68: value = getattr(self.object, key) jpayne@68: except AttributeError: jpayne@68: continue jpayne@68: item = make_objecttreeitem( jpayne@68: str(key) + " =", jpayne@68: value, jpayne@68: lambda value, key=key, object=self.object: jpayne@68: setattr(object, key, value)) jpayne@68: sublist.append(item) jpayne@68: return sublist jpayne@68: jpayne@68: class ClassTreeItem(ObjectTreeItem): jpayne@68: def IsExpandable(self): jpayne@68: return True jpayne@68: def GetSubList(self): jpayne@68: sublist = ObjectTreeItem.GetSubList(self) jpayne@68: if len(self.object.__bases__) == 1: jpayne@68: item = make_objecttreeitem("__bases__[0] =", jpayne@68: self.object.__bases__[0]) jpayne@68: else: jpayne@68: item = make_objecttreeitem("__bases__ =", self.object.__bases__) jpayne@68: sublist.insert(0, item) jpayne@68: return sublist jpayne@68: jpayne@68: class AtomicObjectTreeItem(ObjectTreeItem): jpayne@68: def IsExpandable(self): jpayne@68: return False jpayne@68: jpayne@68: class SequenceTreeItem(ObjectTreeItem): jpayne@68: def IsExpandable(self): jpayne@68: return len(self.object) > 0 jpayne@68: def keys(self): jpayne@68: return range(len(self.object)) jpayne@68: def GetSubList(self): jpayne@68: sublist = [] jpayne@68: for key in self.keys(): jpayne@68: try: jpayne@68: value = self.object[key] jpayne@68: except KeyError: jpayne@68: continue jpayne@68: def setfunction(value, key=key, object=self.object): jpayne@68: object[key] = value jpayne@68: item = make_objecttreeitem("%r:" % (key,), value, setfunction) jpayne@68: sublist.append(item) jpayne@68: return sublist jpayne@68: jpayne@68: class DictTreeItem(SequenceTreeItem): jpayne@68: def keys(self): jpayne@68: keys = list(self.object.keys()) jpayne@68: try: jpayne@68: keys.sort() jpayne@68: except: jpayne@68: pass jpayne@68: return keys jpayne@68: jpayne@68: dispatch = { jpayne@68: int: AtomicObjectTreeItem, jpayne@68: float: AtomicObjectTreeItem, jpayne@68: str: AtomicObjectTreeItem, jpayne@68: tuple: SequenceTreeItem, jpayne@68: list: SequenceTreeItem, jpayne@68: dict: DictTreeItem, jpayne@68: type: ClassTreeItem, jpayne@68: } jpayne@68: jpayne@68: def make_objecttreeitem(labeltext, object, setfunction=None): jpayne@68: t = type(object) jpayne@68: if t in dispatch: jpayne@68: c = dispatch[t] jpayne@68: else: jpayne@68: c = ObjectTreeItem jpayne@68: return c(labeltext, object, setfunction) jpayne@68: jpayne@68: jpayne@68: def _object_browser(parent): # htest # jpayne@68: import sys jpayne@68: from tkinter import Toplevel jpayne@68: top = Toplevel(parent) jpayne@68: top.title("Test debug object browser") jpayne@68: x, y = map(int, parent.geometry().split('+')[1:]) jpayne@68: top.geometry("+%d+%d" % (x + 100, y + 175)) jpayne@68: top.configure(bd=0, bg="yellow") jpayne@68: top.focus_set() jpayne@68: sc = ScrolledCanvas(top, bg="white", highlightthickness=0, takefocus=1) jpayne@68: sc.frame.pack(expand=1, fill="both") jpayne@68: item = make_objecttreeitem("sys", sys) jpayne@68: node = TreeNode(sc.canvas, None, item) jpayne@68: node.update() jpayne@68: jpayne@68: if __name__ == '__main__': jpayne@68: from unittest import main jpayne@68: main('idlelib.idle_test.test_debugobj', verbosity=2, exit=False) jpayne@68: jpayne@68: from idlelib.idle_test.htest import run jpayne@68: run(_object_browser)