debugobj.py 3.96 KB
Newer Older
David Scherer's avatar
David Scherer committed
1 2 3 4 5 6 7 8 9 10
# XXX TO DO:
# - popup menu
# - support partial or total redisplay
# - more doc strings
# - tooltips

# object browser

# XXX TO DO:
# - for classes/modules, add "open source" to object browser
11
from reprlib import Repr
David Scherer's avatar
David Scherer committed
12

13
from idlelib.tree import TreeItem, TreeNode, ScrolledCanvas
David Scherer's avatar
David Scherer committed
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60

myrepr = Repr()
myrepr.maxstring = 100
myrepr.maxother = 100

class ObjectTreeItem(TreeItem):
    def __init__(self, labeltext, object, setfunction=None):
        self.labeltext = labeltext
        self.object = object
        self.setfunction = setfunction
    def GetLabelText(self):
        return self.labeltext
    def GetText(self):
        return myrepr.repr(self.object)
    def GetIconName(self):
        if not self.IsExpandable():
            return "python"
    def IsEditable(self):
        return self.setfunction is not None
    def SetText(self, text):
        try:
            value = eval(text)
            self.setfunction(value)
        except:
            pass
        else:
            self.object = value
    def IsExpandable(self):
        return not not dir(self.object)
    def GetSubList(self):
        keys = dir(self.object)
        sublist = []
        for key in keys:
            try:
                value = getattr(self.object, key)
            except AttributeError:
                continue
            item = make_objecttreeitem(
                str(key) + " =",
                value,
                lambda value, key=key, object=self.object:
                    setattr(object, key, value))
            sublist.append(item)
        return sublist

class ClassTreeItem(ObjectTreeItem):
    def IsExpandable(self):
Kurt B. Kaiser's avatar
Kurt B. Kaiser committed
61
        return True
David Scherer's avatar
David Scherer committed
62 63 64 65 66 67 68 69 70 71 72 73
    def GetSubList(self):
        sublist = ObjectTreeItem.GetSubList(self)
        if len(self.object.__bases__) == 1:
            item = make_objecttreeitem("__bases__[0] =",
                self.object.__bases__[0])
        else:
            item = make_objecttreeitem("__bases__ =", self.object.__bases__)
        sublist.insert(0, item)
        return sublist

class AtomicObjectTreeItem(ObjectTreeItem):
    def IsExpandable(self):
74
        return False
David Scherer's avatar
David Scherer committed
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89

class SequenceTreeItem(ObjectTreeItem):
    def IsExpandable(self):
        return len(self.object) > 0
    def keys(self):
        return range(len(self.object))
    def GetSubList(self):
        sublist = []
        for key in self.keys():
            try:
                value = self.object[key]
            except KeyError:
                continue
            def setfunction(value, key=key, object=self.object):
                object[key] = value
90
            item = make_objecttreeitem("%r:" % (key,), value, setfunction)
David Scherer's avatar
David Scherer committed
91 92 93 94 95
            sublist.append(item)
        return sublist

class DictTreeItem(SequenceTreeItem):
    def keys(self):
96
        keys = list(self.object.keys())
David Scherer's avatar
David Scherer committed
97 98 99 100 101 102 103
        try:
            keys.sort()
        except:
            pass
        return keys

dispatch = {
104 105 106 107 108 109 110
    int: AtomicObjectTreeItem,
    float: AtomicObjectTreeItem,
    str: AtomicObjectTreeItem,
    tuple: SequenceTreeItem,
    list: SequenceTreeItem,
    dict: DictTreeItem,
    type: ClassTreeItem,
David Scherer's avatar
David Scherer committed
111 112 113 114
}

def make_objecttreeitem(labeltext, object, setfunction=None):
    t = type(object)
115
    if t in dispatch:
David Scherer's avatar
David Scherer committed
116 117 118 119 120 121
        c = dispatch[t]
    else:
        c = ObjectTreeItem
    return c(labeltext, object, setfunction)


122
def _object_browser(parent):  # htest #
David Scherer's avatar
David Scherer committed
123
    import sys
124 125 126
    from tkinter import Toplevel
    top = Toplevel(parent)
    top.title("Test debug object browser")
127 128
    x, y = map(int, parent.geometry().split('+')[1:])
    top.geometry("+%d+%d" % (x + 100, y + 175))
129 130 131
    top.configure(bd=0, bg="yellow")
    top.focus_set()
    sc = ScrolledCanvas(top, bg="white", highlightthickness=0, takefocus=1)
David Scherer's avatar
David Scherer committed
132 133 134
    sc.frame.pack(expand=1, fill="both")
    item = make_objecttreeitem("sys", sys)
    node = TreeNode(sc.canvas, None, item)
135
    node.update()
David Scherer's avatar
David Scherer committed
136 137

if __name__ == '__main__':
138 139 140
    from unittest import main
    main('idlelib.idle_test.test_debugobj', verbosity=2, exit=False)

141 142
    from idlelib.idle_test.htest import run
    run(_object_browser)