refbrowser.py (7914B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\pympler\refbrowser.py 2 from __future__ import print_function 3 import gc 4 import inspect 5 import sys 6 from pympler import muppy 7 from pympler import summary 8 from pympler.util.compat import tkinter 9 10 class _Node(object): 11 12 def __init__(self, o, str_func = None): 13 self.o = o 14 self.children = [] 15 self.str_func = str_func 16 17 def __str__(self): 18 if self.str_func is not None: 19 return self.str_func(self.o) 20 else: 21 return str(self.o) 22 23 24 class RefBrowser(object): 25 26 def __init__(self, rootobject, maxdepth = 3, str_func = summary._repr, repeat = True, stream = None): 27 self.root = rootobject 28 self.maxdepth = maxdepth 29 self.str_func = str_func 30 self.repeat = repeat 31 self.stream = stream 32 self.ignore = [] 33 self.already_included = set() 34 self.ignore.append(self.already_included) 35 36 def get_tree(self): 37 self.ignore.append(inspect.currentframe()) 38 return self._get_tree(self.root, self.maxdepth) 39 40 def _get_tree(self, root, maxdepth): 41 objects = gc.get_referrers(root) 42 res = _Node(root, self.str_func) 43 self.already_included.add(id(root)) 44 if maxdepth == 0: 45 return res 46 self.ignore.append(inspect.currentframe()) 47 self.ignore.append(objects) 48 for o in objects: 49 if isinstance(o, dict): 50 if any((isinstance(ref, (_Node, RefBrowser)) for ref in gc.get_referrers(o))): 51 continue 52 _id = id(o) 53 if not self.repeat and _id in self.already_included: 54 s = self.str_func(o) 55 res.children.append('%s (already included, id %s)' % (s, _id)) 56 continue 57 if not isinstance(o, _Node) and o not in self.ignore: 58 res.children.append(self._get_tree(o, maxdepth - 1)) 59 60 return res 61 62 63 class StreamBrowser(RefBrowser): 64 hline = '-' 65 vline = '|' 66 cross = '+' 67 space = ' ' 68 69 def print_tree(self, tree = None): 70 if tree is None: 71 tree = self.get_tree() 72 self._print(tree, '', '') 73 74 def _print(self, tree, prefix, carryon): 75 level = prefix.count(self.cross) + prefix.count(self.vline) 76 len_children = 0 77 if isinstance(tree, _Node): 78 len_children = len(tree.children) 79 prefix += str(tree) 80 carryon += self.space * len(str(tree)) 81 if level == self.maxdepth or not isinstance(tree, _Node) or len_children == 0: 82 self.stream.write(prefix + '\n') 83 return 84 prefix += self.hline 85 carryon += self.space 86 if len(tree.children) > 1: 87 prefix += self.cross 88 carryon += self.vline 89 prefix += self.hline 90 carryon += self.space 91 if len_children > 0: 92 self._print(tree.children[0], prefix, carryon) 93 for b in range(1, len_children): 94 prefix = carryon[:-2] + self.cross + self.hline 95 if b == len_children - 1: 96 carryon = carryon[:-2] + 2 * self.space 97 self._print(tree.children[b], prefix, carryon) 98 if b == len_children - 1: 99 if len(carryon.strip(' ')) == 0: 100 return 101 self.stream.write(carryon[:-2].rstrip() + '\n') 102 103 104 class ConsoleBrowser(StreamBrowser): 105 106 def __init__(self, *args, **kwargs): 107 super(ConsoleBrowser, self).__init__(*args, **kwargs) 108 if not self.stream: 109 self.stream = sys.stdout 110 111 112 class FileBrowser(StreamBrowser): 113 114 def print_tree(self, filename, tree = None): 115 old_stream = self.stream 116 self.stream = open(filename, 'w') 117 try: 118 super(FileBrowser, self).print_tree(tree=tree) 119 finally: 120 self.stream.close() 121 self.stream = old_stream 122 123 124 try: 125 from idlelib import TreeWidget as _TreeWidget 126 127 class _TreeNode(_TreeWidget.TreeNode): 128 129 def reload_referrers(self): 130 self.item.node = self.item.reftree._get_tree(self.item.node.o, 1) 131 self.item._clear_children() 132 self.expand() 133 self.update() 134 135 def print_object(self): 136 print(self.item.node.o) 137 138 def drawtext(self): 139 _TreeWidget.TreeNode.drawtext(self) 140 menu = tkinter.Menu(self.canvas, tearoff=0) 141 menu.add_command(label='reload referrers', command=self.reload_referrers) 142 menu.add_command(label='print', command=self.print_object) 143 menu.add_separator() 144 menu.add_command(label='expand', command=self.expand) 145 menu.add_separator() 146 menu.add_command(label='Close Popup Menu') 147 148 def do_popup(event): 149 menu.post(event.x_root, event.y_root) 150 151 self.label.bind('<Button-3>', do_popup) 152 153 def edit(self, event = None): 154 pass 155 156 def edit_finish(self, event = None): 157 pass 158 159 def edit_cancel(self, event = None): 160 pass 161 162 163 class _ReferrerTreeItem(_TreeWidget.TreeItem, tkinter.Label): 164 165 def __init__(self, parentwindow, node, reftree): 166 _TreeWidget.TreeItem.__init__(self) 167 tkinter.Label.__init__(self, parentwindow) 168 self.node = node 169 self.parentwindow = parentwindow 170 self.reftree = reftree 171 172 def _clear_children(self): 173 new_children = [] 174 for child in self.node.children: 175 if not isinstance(child, _TreeNode): 176 new_children.append(child) 177 178 self.node.children = new_children 179 180 def GetText(self): 181 return str(self.node) 182 183 def GetIconName(self): 184 if not self.IsExpandable(): 185 return 'python' 186 187 def IsExpandable(self): 188 if not isinstance(self.node, _Node): 189 return False 190 elif len(self.node.children) > 0: 191 return True 192 else: 193 return muppy._is_containerobject(self.node.o) 194 195 def GetSubList(self): 196 sublist = [] 197 children = self.node.children 198 if len(children) == 0 and muppy._is_containerobject(self.node.o): 199 self.node = self.reftree._get_tree(self.node.o, 1) 200 self._clear_children() 201 children = self.node.children 202 for child in children: 203 item = _ReferrerTreeItem(self.parentwindow, child, self.reftree) 204 sublist.append(item) 205 206 return sublist 207 208 209 except ImportError: 210 _TreeWidget = None 211 212 def gui_default_str_function(o): 213 return summary._repr(o) + '(id=%s)' % id(o) 214 215 216 class InteractiveBrowser(RefBrowser): 217 218 def __init__(self, rootobject, maxdepth = 3, str_func = gui_default_str_function, repeat = True): 219 if tkinter is None: 220 raise ImportError('InteractiveBrowser requires Tkinter to be installed.') 221 RefBrowser.__init__(self, rootobject, maxdepth, str_func, repeat) 222 223 def main(self, standalone = False): 224 window = tkinter.Tk() 225 sc = _TreeWidget.ScrolledCanvas(window, bg='white', highlightthickness=0, takefocus=1) 226 sc.frame.pack(expand=1, fill='both') 227 item = _ReferrerTreeItem(window, self.get_tree(), self) 228 node = _TreeNode(sc.canvas, None, item) 229 node.expand() 230 if standalone: 231 window.mainloop() 232 233 234 superlist = [] 235 root = 'root' 236 for i in range(3): 237 tmp = [root] 238 superlist.append(tmp) 239 240 def foo(o): 241 return str(type(o)) 242 243 244 def print_sample(): 245 cb = ConsoleBrowser(root, str_func=foo) 246 cb.print_tree() 247 248 249 def write_sample(): 250 fb = FileBrowser(root, str_func=foo) 251 fb.print_tree('sample.txt') 252 253 254 if __name__ == '__main__': 255 write_sample()