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