Kano001's picture
Upload 498 files
d12bc25 verified
raw
history blame
13.6 kB
# 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 commctrl
import win32api
import win32con
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()
return dlg
#
#
# 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)