123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434 |
- # basic module browser.
- # usage:
- # >>> import browser
- # >>> browser.Browse()
- # or
- # >>> browser.Browse(your_module)
- import sys
- import types
- import __main__
- import win32ui
- from pywin.mfc import dialog
- from . import hierlist
- special_names = [ '__doc__', '__name__', '__self__' ]
- #
- # HierList items
- class HLIPythonObject(hierlist.HierListItem):
- def __init__(self, myobject=None, name=None ):
- hierlist.HierListItem.__init__(self)
- self.myobject = myobject
- self.knownExpandable = None
- if name:
- self.name=name
- else:
- try:
- self.name=myobject.__name__
- except (AttributeError, TypeError):
- try:
- r = repr(myobject)
- if len(r)>20:
- r = r[:20] + "..."
- self.name=r
- except (AttributeError, TypeError):
- self.name="???"
- def __lt__(self, other):
- return self.name < other.name
- def __eq__(self, other):
- return self.name == other.name
- def __repr__(self):
- try:
- type = self.GetHLIType()
- except:
- type = "Generic"
- return "HLIPythonObject("+type+") - name: "+ self.name + " object: " + repr(self.myobject)
- def GetText(self):
- try:
- return str(self.name) + ' (' + self.GetHLIType() + ')'
- except AttributeError:
- return str(self.name) + ' = ' + repr(self.myobject)
- def InsertDocString(self, lst):
- ob = None
- try:
- ob = self.myobject.__doc__
- except (AttributeError, TypeError):
- pass
- # I don't quite grok descriptors enough to know how to
- # best hook them up. Eg:
- # >>> object.__getattribute__.__class__.__doc__
- # <attribute '__doc__' of 'wrapper_descriptor' objects>
- if ob and isinstance(ob, str):
- lst.insert(0, HLIDocString( ob, "Doc" ))
- def GetSubList(self):
- ret = []
- try:
- for (key, ob) in self.myobject.__dict__.items():
- if key not in special_names:
- ret.append(MakeHLI( ob, key ) )
- except (AttributeError, TypeError):
- pass
- try:
- for name in self.myobject.__methods__:
- ret.append(HLIMethod( name )) # no MakeHLI, as cant auto detect
- except (AttributeError, TypeError):
- pass
- try:
- for member in self.myobject.__members__:
- if not member in special_names:
- ret.append(MakeHLI(getattr(self.myobject, member), member))
- except (AttributeError, TypeError):
- pass
- ret.sort()
- self.InsertDocString(ret)
- return ret
- # if the has a dict, it is expandable.
- def IsExpandable(self):
- if self.knownExpandable is None:
- self.knownExpandable = self.CalculateIsExpandable()
- return self.knownExpandable
- def CalculateIsExpandable(self):
- if hasattr(self.myobject, '__doc__'):
- return 1
- try:
- for key in self.myobject.__dict__.keys():
- if key not in special_names:
- return 1
- except (AttributeError, TypeError):
- pass
- try:
- self.myobject.__methods__
- return 1
- except (AttributeError, TypeError):
- pass
- try:
- for item in self.myobject.__members__:
- if item not in special_names:
- return 1
- except (AttributeError, TypeError):
- pass
- return 0
- def GetBitmapColumn(self):
- if self.IsExpandable():
- return 0
- else:
- return 4
- def TakeDefaultAction(self):
- ShowObject(self.myobject, self.name)
- class HLIDocString(HLIPythonObject):
- def GetHLIType(self):
- return "DocString"
- def GetText(self):
- return self.myobject.strip()
- def IsExpandable(self):
- return 0
- def GetBitmapColumn(self):
- return 6
- class HLIModule(HLIPythonObject):
- def GetHLIType(self):
- return "Module"
- class HLIFrame(HLIPythonObject):
- def GetHLIType(self):
- return "Stack Frame"
- class HLITraceback(HLIPythonObject):
- def GetHLIType(self):
- return "Traceback"
- class HLIClass(HLIPythonObject):
- def GetHLIType(self):
- return "Class"
- def GetSubList(self):
- ret = []
- for base in self.myobject.__bases__:
- ret.append( MakeHLI(base, 'Base class: ' + base.__name__ ) )
- ret = ret + HLIPythonObject.GetSubList(self)
- return ret
- class HLIMethod(HLIPythonObject):
- # myobject is just a string for methods.
- def GetHLIType(self):
- return "Method"
- def GetText(self):
- return "Method: " + self.myobject + '()'
- class HLICode(HLIPythonObject):
- def GetHLIType(self):
- return "Code"
- def IsExpandable(self):
- return self.myobject
- def GetSubList(self):
- ret = []
- ret.append( MakeHLI( self.myobject.co_consts, "Constants (co_consts)" ))
- ret.append( MakeHLI( self.myobject.co_names, "Names (co_names)" ))
- ret.append( MakeHLI( self.myobject.co_filename, "Filename (co_filename)" ))
- ret.append( MakeHLI( self.myobject.co_argcount, "Number of args (co_argcount)"))
- ret.append( MakeHLI( self.myobject.co_varnames, "Param names (co_varnames)"))
-
- return ret
- class HLIInstance(HLIPythonObject):
- def GetHLIType(self):
- return "Instance"
- def GetText(self):
- return str(self.name) + ' (Instance of class ' + str(self.myobject.__class__.__name__) + ')'
- def IsExpandable(self):
- return 1
- def GetSubList(self):
- ret = []
- ret.append( MakeHLI( self.myobject.__class__) )
- ret = ret + HLIPythonObject.GetSubList(self)
- return ret
- class HLIBuiltinFunction(HLIPythonObject):
- def GetHLIType(self):
- return "Builtin Function"
- class HLIFunction(HLIPythonObject):
- def GetHLIType(self):
- return "Function"
- def IsExpandable(self):
- return 1
- def GetSubList(self):
- ret = []
- # ret.append( MakeHLI( self.myobject.func_argcount, "Arg Count" ))
- try:
- ret.append( MakeHLI( self.myobject.func_argdefs, "Arg Defs" ))
- except AttributeError:
- pass
- try:
- code = self.myobject.__code__
- globs = self.myobject.__globals__
- except AttributeError:
- # must be py2.5 or earlier...
- code = self.myobject.func_code
- globs = self.myobject.func_globals
- ret.append(MakeHLI(code, "Code" ))
- ret.append(MakeHLI(globs, "Globals" ))
- self.InsertDocString(ret)
- return ret
- class HLISeq(HLIPythonObject):
- def GetHLIType(self):
- return "Sequence (abstract!)"
- def IsExpandable(self):
- return len(self.myobject)>0
- def GetSubList(self):
- ret = []
- pos=0
- for item in self.myobject:
- ret.append(MakeHLI( item, '['+str(pos)+']' ) )
- pos=pos+1
- self.InsertDocString(ret)
- return ret
- class HLIList(HLISeq):
- def GetHLIType(self):
- return "List"
- class HLITuple(HLISeq):
- def GetHLIType(self):
- return "Tuple"
- class HLIDict(HLIPythonObject):
- def GetHLIType(self):
- return "Dict"
- def IsExpandable(self):
- try:
- self.myobject.__doc__
- return 1
- except (AttributeError, TypeError):
- return len(self.myobject) > 0
- def GetSubList(self):
- ret = []
- keys = list(self.myobject.keys())
- keys.sort()
- for key in keys:
- ob = self.myobject[key]
- ret.append(MakeHLI( ob, str(key) ) )
- self.InsertDocString(ret)
- return ret
- # In Python 1.6, strings and Unicode have builtin methods, but we dont really want to see these
- class HLIString(HLIPythonObject):
- def IsExpandable(self):
- return 0
- TypeMap = { type : HLIClass,
- types.FunctionType: HLIFunction,
- tuple: HLITuple,
- dict: HLIDict,
- list: HLIList,
- types.ModuleType: HLIModule,
- types.CodeType : HLICode,
- types.BuiltinFunctionType : HLIBuiltinFunction,
- types.FrameType : HLIFrame,
- types.TracebackType : HLITraceback,
- str : HLIString,
- int: HLIPythonObject,
- bool: HLIPythonObject,
- float: HLIPythonObject,
- }
- def MakeHLI( ob, name=None ):
- try:
- cls = TypeMap[type(ob)]
- except KeyError:
- # hrmph - this check gets more and more bogus as Python
- # improves. Its possible we should just *always* use
- # HLIInstance?
- if hasattr(ob, '__class__'): # 'new style' class
- cls = HLIInstance
- else:
- cls = HLIPythonObject
- return cls( ob, name )
- #########################################
- #
- # Dialog related.
- class DialogShowObject(dialog.Dialog):
- def __init__(self, object, title):
- self.object = object
- self.title = title
- dialog.Dialog.__init__(self, win32ui.IDD_LARGE_EDIT)
- def OnInitDialog(self):
- import re
- self.SetWindowText(self.title)
- self.edit = self.GetDlgItem(win32ui.IDC_EDIT1)
- try:
- strval = str(self.object)
- except:
- t, v, tb = sys.exc_info()
- strval = "Exception getting object value\n\n%s:%s" % (t, v)
- tb = None
- strval = re.sub('\n','\r\n', strval)
- self.edit.ReplaceSel(strval)
-
- def ShowObject(object, title):
- dlg = DialogShowObject(object, title)
- dlg.DoModal()
- # And some mods for a sizable dialog from Sam Rushing!
- import win32con
- import win32api
- import commctrl
- class dynamic_browser (dialog.Dialog):
- style = win32con.WS_OVERLAPPEDWINDOW | win32con.WS_VISIBLE
- cs = (
- win32con.WS_CHILD |
- win32con.WS_VISIBLE |
- commctrl.TVS_HASLINES |
- commctrl.TVS_LINESATROOT |
- commctrl.TVS_HASBUTTONS
- )
- dt = [
- ["Python Object Browser", (0, 0, 200, 200), style, None, (8, "MS Sans Serif")],
- ["SysTreeView32", None, win32ui.IDC_LIST1, (0, 0, 200, 200), cs]
- ]
- def __init__ (self, hli_root):
- dialog.Dialog.__init__ (self, self.dt)
- self.hier_list = hierlist.HierListWithItems (
- hli_root,
- win32ui.IDB_BROWSER_HIER
- )
- self.HookMessage (self.on_size, win32con.WM_SIZE)
- def OnInitDialog (self):
- self.hier_list.HierInit (self)
- return dialog.Dialog.OnInitDialog (self)
- def OnOK(self):
- self.hier_list.HierTerm()
- self.hier_list = None
- return self._obj_.OnOK()
- def OnCancel(self):
- self.hier_list.HierTerm()
- self.hier_list = None
- return self._obj_.OnCancel()
- def on_size (self, params):
- lparam = params[3]
- w = win32api.LOWORD(lparam)
- h = win32api.HIWORD(lparam)
- self.GetDlgItem (win32ui.IDC_LIST1).MoveWindow((0,0,w,h))
- def Browse (ob=__main__):
- " Browse the argument, or the main dictionary "
- root = MakeHLI (ob, 'root')
- if not root.IsExpandable():
- raise TypeError("Browse() argument must have __dict__ attribute, or be a Browser supported type")
-
- dlg = dynamic_browser (root)
- dlg.CreateWindow()
- #
- #
- # Classes for using the browser in an MDI window, rather than a dialog
- #
- from pywin.mfc import docview
- class BrowserTemplate(docview.DocTemplate):
- def __init__(self):
- docview.DocTemplate.__init__(self, win32ui.IDR_PYTHONTYPE, BrowserDocument, None, BrowserView)
- def OpenObject(self, root): # Use this instead of OpenDocumentFile.
- # Look for existing open document
- for doc in self.GetDocumentList():
- if doc.root==root:
- doc.GetFirstView().ActivateFrame()
- return doc
- # not found - new one.
- doc = BrowserDocument(self, root)
- frame = self.CreateNewFrame(doc)
- doc.OnNewDocument()
- self.InitialUpdateFrame(frame, doc, 1)
- return doc
- class BrowserDocument (docview.Document):
- def __init__(self, template, root):
- docview.Document.__init__(self, template)
- self.root = root
- self.SetTitle("Browser: " + root.name)
- def OnOpenDocument (self, name):
- raise TypeError("This template can not open files")
- return 0
- class BrowserView(docview.TreeView):
- def OnInitialUpdate(self):
- import commctrl
- rc = self._obj_.OnInitialUpdate()
- list=hierlist.HierListWithItems( self.GetDocument().root, win32ui.IDB_BROWSER_HIER, win32ui.AFX_IDW_PANE_FIRST)
- list.HierInit(self.GetParent())
- list.SetStyle(commctrl.TVS_HASLINES | commctrl.TVS_LINESATROOT | commctrl.TVS_HASBUTTONS)
- return rc
- template = None
- def MakeTemplate():
- global template
- if template is None:
- template = BrowserTemplate() #win32ui.IDR_PYTHONTYPE, BrowserDocument, None, BrowserView)
- def BrowseMDI(ob=__main__):
- """Browse an object using an MDI window.
- """
- MakeTemplate()
- root = MakeHLI(ob, repr(ob))
- if not root.IsExpandable():
- raise TypeError("Browse() argument must have __dict__ attribute, or be a Browser supported type")
-
- template.OpenObject(root)
|