debugobj.py 4.0 KB

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