codekingpro/portable-devtools
114k
1# basic module browser.2 3# usage:4# >>> import browser5# >>> browser.Browse()6# or7# >>> browser.Browse(your_module)8import sys9import types10 11import __main__12import win32ui13from pywin.mfc import dialog14 15from . import hierlist16 17special_names = ["__doc__", "__name__", "__self__"]18 19 20#21# HierList items22class HLIPythonObject(hierlist.HierListItem):23 def __init__(self, myobject=None, name=None):24 hierlist.HierListItem.__init__(self)25 self.myobject = myobject26 self.knownExpandable = None27 if name:28 self.name = name29 else:30 try:31 self.name = myobject.__name__32 except (AttributeError, TypeError):33 try:34 r = repr(myobject)35 if len(r) > 20:36 r = r[:20] + "..."37 self.name = r38 except (AttributeError, TypeError):39 self.name = "???"40 41 def __lt__(self, other):42 return self.name < other.name43 44 def __eq__(self, other):45 return self.name == other.name46 47 def __repr__(self):48 try:49 type = self.GetHLIType()50 except:51 type = "Generic"52 return (53 "HLIPythonObject("54 + type55 + ") - name: "56 + self.name57 + " object: "58 + repr(self.myobject)59 )60 61 def GetText(self):62 try:63 return str(self.name) + " (" + self.GetHLIType() + ")"64 except AttributeError:65 return str(self.name) + " = " + repr(self.myobject)66 67 def InsertDocString(self, lst):68 ob = None69 try:70 ob = self.myobject.__doc__71 except (AttributeError, TypeError):72 pass73 # I don't quite grok descriptors enough to know how to74 # best hook them up. Eg:75 # >>> object.__getattribute__.__class__.__doc__76 # <attribute '__doc__' of 'wrapper_descriptor' objects>77 if ob and isinstance(ob, str):78 lst.insert(0, HLIDocString(ob, "Doc"))79 80 def GetSubList(self):81 ret = []82 try:83 for key, ob in self.myobject.__dict__.items():84 if key not in special_names:85 ret.append(MakeHLI(ob, key))86 except (AttributeError, TypeError):87 pass88 try:89 for name in self.myobject.__methods__:90 ret.append(HLIMethod(name)) # no MakeHLI, as cant auto detect91 except (AttributeError, TypeError):92 pass93 try:94 for member in self.myobject.__members__:95 if not member in special_names:96 ret.append(MakeHLI(getattr(self.myobject, member), member))97 except (AttributeError, TypeError):98 pass99 ret.sort()100 self.InsertDocString(ret)101 return ret102 103 # if the has a dict, it is expandable.104 def IsExpandable(self):105 if self.knownExpandable is None:106 self.knownExpandable = self.CalculateIsExpandable()107 return self.knownExpandable108 109 def CalculateIsExpandable(self):110 if hasattr(self.myobject, "__doc__"):111 return 1112 try:113 for key in self.myobject.__dict__.keys():114 if key not in special_names:115 return 1116 except (AttributeError, TypeError):117 pass118 try:119 self.myobject.__methods__120 return 1121 except (AttributeError, TypeError):122 pass123 try:124 for item in self.myobject.__members__:125 if item not in special_names:126 return 1127 except (AttributeError, TypeError):128 pass129 return 0130 131 def GetBitmapColumn(self):132 if self.IsExpandable():133 return 0134 else:135 return 4136 137 def TakeDefaultAction(self):138 ShowObject(self.myobject, self.name)139 140 141class HLIDocString(HLIPythonObject):142 def GetHLIType(self):143 return "DocString"144 145 def GetText(self):146 return self.myobject.strip()147 148 def IsExpandable(self):149 return 0150 151 def GetBitmapColumn(self):152 return 6153 154 155class HLIModule(HLIPythonObject):156 def GetHLIType(self):157 return "Module"158 159 160class HLIFrame(HLIPythonObject):161 def GetHLIType(self):162 return "Stack Frame"163 164 165class HLITraceback(HLIPythonObject):166 def GetHLIType(self):167 return "Traceback"168 169 170class HLIClass(HLIPythonObject):171 def GetHLIType(self):172 return "Class"173 174 def GetSubList(self):175 ret = []176 for base in self.myobject.__bases__:177 ret.append(MakeHLI(base, "Base class: " + base.__name__))178 ret = ret + HLIPythonObject.GetSubList(self)179 return ret180 181 182class HLIMethod(HLIPythonObject):183 # myobject is just a string for methods.184 def GetHLIType(self):185 return "Method"186 187 def GetText(self):188 return "Method: " + self.myobject + "()"189 190 191class HLICode(HLIPythonObject):192 def GetHLIType(self):193 return "Code"194 195 def IsExpandable(self):196 return self.myobject197 198 def GetSubList(self):199 ret = []200 ret.append(MakeHLI(self.myobject.co_consts, "Constants (co_consts)"))201 ret.append(MakeHLI(self.myobject.co_names, "Names (co_names)"))202 ret.append(MakeHLI(self.myobject.co_filename, "Filename (co_filename)"))203 ret.append(MakeHLI(self.myobject.co_argcount, "Number of args (co_argcount)"))204 ret.append(MakeHLI(self.myobject.co_varnames, "Param names (co_varnames)"))205 206 return ret207 208 209class HLIInstance(HLIPythonObject):210 def GetHLIType(self):211 return "Instance"212 213 def GetText(self):214 return (215 str(self.name)216 + " (Instance of class "217 + str(self.myobject.__class__.__name__)218 + ")"219 )220 221 def IsExpandable(self):222 return 1223 224 def GetSubList(self):225 ret = []226 ret.append(MakeHLI(self.myobject.__class__))227 ret = ret + HLIPythonObject.GetSubList(self)228 return ret229 230 231class HLIBuiltinFunction(HLIPythonObject):232 def GetHLIType(self):233 return "Builtin Function"234 235 236class HLIFunction(HLIPythonObject):237 def GetHLIType(self):238 return "Function"239 240 def IsExpandable(self):241 return 1242 243 def GetSubList(self):244 ret = []245 # ret.append( MakeHLI( self.myobject.func_argcount, "Arg Count" ))246 try:247 ret.append(MakeHLI(self.myobject.func_argdefs, "Arg Defs"))248 except AttributeError:249 pass250 try:251 code = self.myobject.__code__252 globs = self.myobject.__globals__253 except AttributeError:254 # must be py2.5 or earlier...255 code = self.myobject.func_code256 globs = self.myobject.func_globals257 ret.append(MakeHLI(code, "Code"))258 ret.append(MakeHLI(globs, "Globals"))259 self.InsertDocString(ret)260 return ret261 262 263class HLISeq(HLIPythonObject):264 def GetHLIType(self):265 return "Sequence (abstract!)"266 267 def IsExpandable(self):268 return len(self.myobject) > 0269 270 def GetSubList(self):271 ret = []272 pos = 0273 for item in self.myobject:274 ret.append(MakeHLI(item, "[" + str(pos) + "]"))275 pos = pos + 1276 self.InsertDocString(ret)277 return ret278 279 280class HLIList(HLISeq):281 def GetHLIType(self):282 return "List"283 284 285class HLITuple(HLISeq):286 def GetHLIType(self):287 return "Tuple"288 289 290class HLIDict(HLIPythonObject):291 def GetHLIType(self):292 return "Dict"293 294 def IsExpandable(self):295 try:296 self.myobject.__doc__297 return 1298 except (AttributeError, TypeError):299 return len(self.myobject) > 0300 301 def GetSubList(self):302 ret = []303 keys = list(self.myobject.keys())304 keys.sort()305 for key in keys:306 ob = self.myobject[key]307 ret.append(MakeHLI(ob, str(key)))308 self.InsertDocString(ret)309 return ret310 311 312# In Python 1.6, strings and Unicode have builtin methods, but we dont really want to see these313class HLIString(HLIPythonObject):314 def IsExpandable(self):315 return 0316 317 318TypeMap = {319 type: HLIClass,320 types.FunctionType: HLIFunction,321 tuple: HLITuple,322 dict: HLIDict,323 list: HLIList,324 types.ModuleType: HLIModule,325 types.CodeType: HLICode,326 types.BuiltinFunctionType: HLIBuiltinFunction,327 types.FrameType: HLIFrame,328 types.TracebackType: HLITraceback,329 str: HLIString,330 int: HLIPythonObject,331 bool: HLIPythonObject,332 float: HLIPythonObject,333}334 335 336def MakeHLI(ob, name=None):337 try:338 cls = TypeMap[type(ob)]339 except KeyError:340 # hrmph - this check gets more and more bogus as Python341 # improves. Its possible we should just *always* use342 # HLIInstance?343 if hasattr(ob, "__class__"): # 'new style' class344 cls = HLIInstance345 else:346 cls = HLIPythonObject347 return cls(ob, name)348 349 350#########################################351#352# Dialog related.353 354 355class DialogShowObject(dialog.Dialog):356 def __init__(self, object, title):357 self.object = object358 self.title = title359 dialog.Dialog.__init__(self, win32ui.IDD_LARGE_EDIT)360 361 def OnInitDialog(self):362 import re363 364 self.SetWindowText(self.title)365 self.edit = self.GetDlgItem(win32ui.IDC_EDIT1)366 try:367 strval = str(self.object)368 except:369 t, v, tb = sys.exc_info()370 strval = "Exception getting object value\n\n%s:%s" % (t, v)371 tb = None372 strval = re.sub("\n", "\r\n", strval)373 self.edit.ReplaceSel(strval)374 375 376def ShowObject(object, title):377 dlg = DialogShowObject(object, title)378 dlg.DoModal()379 380 381# And some mods for a sizable dialog from Sam Rushing!382import commctrl383import win32api384import win32con385 386 387class dynamic_browser(dialog.Dialog):388 style = win32con.WS_OVERLAPPEDWINDOW | win32con.WS_VISIBLE389 cs = (390 win32con.WS_CHILD391 | win32con.WS_VISIBLE392 | commctrl.TVS_HASLINES393 | commctrl.TVS_LINESATROOT394 | commctrl.TVS_HASBUTTONS395 )396 397 dt = [398 ["Python Object Browser", (0, 0, 200, 200), style, None, (8, "MS Sans Serif")],399 ["SysTreeView32", None, win32ui.IDC_LIST1, (0, 0, 200, 200), cs],400 ]401 402 def __init__(self, hli_root):403 dialog.Dialog.__init__(self, self.dt)404 self.hier_list = hierlist.HierListWithItems(hli_root, win32ui.IDB_BROWSER_HIER)405 self.HookMessage(self.on_size, win32con.WM_SIZE)406 407 def OnInitDialog(self):408 self.hier_list.HierInit(self)409 return dialog.Dialog.OnInitDialog(self)410 411 def OnOK(self):412 self.hier_list.HierTerm()413 self.hier_list = None414 return self._obj_.OnOK()415 416 def OnCancel(self):417 self.hier_list.HierTerm()418 self.hier_list = None419 return self._obj_.OnCancel()420 421 def on_size(self, params):422 lparam = params[3]423 w = win32api.LOWORD(lparam)424 h = win32api.HIWORD(lparam)425 self.GetDlgItem(win32ui.IDC_LIST1).MoveWindow((0, 0, w, h))426 427 428def Browse(ob=__main__):429 "Browse the argument, or the main dictionary"430 root = MakeHLI(ob, "root")431 if not root.IsExpandable():432 raise TypeError(433 "Browse() argument must have __dict__ attribute, or be a Browser supported type"434 )435 436 dlg = dynamic_browser(root)437 dlg.CreateWindow()438 return dlg439 440 441#442#443# Classes for using the browser in an MDI window, rather than a dialog444#445from pywin.mfc import docview446 447 448class BrowserTemplate(docview.DocTemplate):449 def __init__(self):450 docview.DocTemplate.__init__(451 self, win32ui.IDR_PYTHONTYPE, BrowserDocument, None, BrowserView452 )453 454 def OpenObject(self, root): # Use this instead of OpenDocumentFile.455 # Look for existing open document456 for doc in self.GetDocumentList():457 if doc.root == root:458 doc.GetFirstView().ActivateFrame()459 return doc460 # not found - new one.461 doc = BrowserDocument(self, root)462 frame = self.CreateNewFrame(doc)463 doc.OnNewDocument()464 self.InitialUpdateFrame(frame, doc, 1)465 return doc466 467 468class BrowserDocument(docview.Document):469 def __init__(self, template, root):470 docview.Document.__init__(self, template)471 self.root = root472 self.SetTitle("Browser: " + root.name)473 474 def OnOpenDocument(self, name):475 raise TypeError("This template can not open files")476 return 0477 478 479class BrowserView(docview.TreeView):480 def OnInitialUpdate(self):481 import commctrl482 483 rc = self._obj_.OnInitialUpdate()484 list = hierlist.HierListWithItems(485 self.GetDocument().root,486 win32ui.IDB_BROWSER_HIER,487 win32ui.AFX_IDW_PANE_FIRST,488 )489 list.HierInit(self.GetParent())490 list.SetStyle(491 commctrl.TVS_HASLINES | commctrl.TVS_LINESATROOT | commctrl.TVS_HASBUTTONS492 )493 return rc494 495 496template = None497 498 499def MakeTemplate():500 global template501 if template is None:502 template = (503 BrowserTemplate()504 ) # win32ui.IDR_PYTHONTYPE, BrowserDocument, None, BrowserView)505 506 507def BrowseMDI(ob=__main__):508 """Browse an object using an MDI window."""509 510 MakeTemplate()511 root = MakeHLI(ob, repr(ob))512 if not root.IsExpandable():513 raise TypeError(514 "Browse() argument must have __dict__ attribute, or be a Browser supported type"515 )516 517 template.OpenObject(root)518 