openmedialibrary_platform_w.../Lib/site-packages/pythonwin/pywin/tools/browser.py
2016-04-14 21:54:42 +02:00

436 lines
12 KiB
Python

# 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,
str : HLIString,
int: HLIPythonObject,
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)