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